Изменение значка виджета из onUpdate

У меня есть виджет, который должен менять свой значок каждый раз, когда он получает трансляцию обновления. Однако виджету никогда не удается правильно отобразить свой значок, отображая текст «Проблема с загрузкой виджета». Сообщение Logcat:

WARN/AppWidgetHostView(612): updateAppWidget couldn't find any view, using error view
WARN/AppWidgetHostView(612): android.widget.RemoteViews$ActionException: can't find view: 0x7f060003

Код для моего onUpdate:

public class ImageWidgetProvider extends AppWidgetProvider{
private  static final String TAG = "Steve";

public static final int[] IMAGES = { R.drawable.ic_launcher_alarmclock,
    /*and many more*/};

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds){

    for (int appWidgetId : appWidgetIds) {
        Log.d(TAG, "onUpdate:");
        int imageNum = (new java.util.Random().nextInt(IMAGES.length));
        Log.d(TAG, Integer.toString(IMAGES[imageNum]));
        RemoteViews remoteView = new RemoteViews(context.getPackageName(), R.layout.widget);
        remoteView.setImageViewResource(R.id.image_in_widget, IMAGES[imageNum]);
        appWidgetManager.updateAppWidget(appWidgetId, remoteView);
    }

}
}

Теперь, когда я навожу указатель мыши на «R.id.image_in_widget», он показывает, что его значение равно 0x7f060003 — вид, который он не может найти в соответствии с Logcat. Используя второй оператор Log, я убедился, что IMAGES[imageNum] действительно ссылается на случайное изображение из массива IMAGES. (Если это имеет значение, это десятичное значение, а не шестнадцатеричное.) Есть идеи, что я делаю неправильно? Большое спасибо!

--

Редактировать: Вот файл макета для виджета, где объявлен image_in_widget ImageView.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">

<ImageView android:name="@+id/image_in_widget"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
</LinearLayout>

person Steve Haley    schedule 29.12.2009    source источник
comment
Это действительно странно. Кажется, вы все делаете правильно. Вы используете разрешенные компоненты пользовательского интерфейса в своем файле макета, он должен просто работать. Этот виджет Проблема с загрузкой отображается сразу после того, как вы поместите виджет на экран, верно? Я действительно не знаю, в чем причина... извините. Может попробовать запустить свой виджет на эмуляторе 1.6?   -  person Ramps    schedule 30.12.2009
comment
Да, сразу отображается виджет Проблема с загрузкой. То же самое в эмуляторе v1.6. Спасибо за попытку - я рад видеть, что не только я считаю это странным :)   -  person Steve Haley    schedule 30.12.2009


Ответы (3)


Еще одна причина, по которой это может произойти (для тех, кто ищет в Интернете этот вопрос, а не оригинальный постер):

Если у вас есть отдельные макеты для альбомной и вертикальной ориентации, оба макета должны содержать любые представления, на которые вы ссылаетесь во время обновления. Если вы ссылаетесь на представление, которое присутствует только в одном режиме, скажем, в портретном, то в альбомном режиме вы получите сообщение «Проблема с загрузкой виджета» в окне виджета.

Простое решение состоит в том, чтобы установить видимость на «ИСКЛЮЧЕНО» в режиме, в котором вы не хотите, чтобы эти представления появлялись.

person Kris Giesing    schedule 11.07.2010
comment
Бам, это решило то, на что могли уйти часы. Спасибо за совет. - person jakebasile; 24.11.2010
comment
Я только что столкнулся с этим тестированием с API 10, и что-то вроде этого было причиной. Я устанавливал свойства для представлений, которые не появлялись во всех моих макетах. В более поздних версиях API это больше не проблема (эти вызовы просто игнорируются). - person trooper; 25.04.2015

В Android 1.5 есть проблема с вызовом OnDelete для виджетов.

Поместите этот код в свой AppWidgetProvider, и он должен решить проблему.

public void onReceive(Context context, Intent intent) {
    // v1.5 fix that doesn't call onDelete Action
    final String action = intent.getAction();
    if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) {
        final int appWidgetId = intent.getExtras().getInt(
                AppWidgetManager.EXTRA_APPWIDGET_ID,
                AppWidgetManager.INVALID_APPWIDGET_ID);
        if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
            this.onDeleted(context, new int[] { appWidgetId });
        }
    } else {
        super.onReceive(context, intent);
    }
}
person Tom    schedule 10.02.2010
comment
Спасибо. Я видел эту ошибку раньше, но предположил, что она не связана, но моя интуиция несколько раз ошибалась в этом путешествии по программированию... Как только я вернусь к этому проекту, я попробую. - person Steve Haley; 10.02.2010

Может быть, это не относится к вашему примеру, но у меня тоже были похожие проблемы с виджетом приложения. В андроиде 1.5 была досадная проблема с виджетами на главном экране. В конкретном случае виджеты приложений все еще были активны в памяти, но больше не были видны.
Вы выполняете перечисление через appWidgetIds, проверьте, содержит ли этот массив именно то количество идентификаторов, которое вы ожидаете. Просто поместите еще один Log.d() для регистрации идентификаторов. Возможно, у вас также есть какие-то "призрачные" виджеты.
Какую версию Android вы используете?

person Ramps    schedule 29.12.2009
comment
Интересно... Я действительно программирую для Android v1.5. Это объясняет некоторые странные вещи, которые я видел в Logcat — строки отладки из другого виджета, который я удалил. Я только что попытался добавить больше строк отладки, и он начинает считать с 37 (хотя у меня не так много виджетов на главном экране), но массив правильно имеет только 1 запись. Что это говорит нам? Мне кажется, это означает, что это не источник проблемы, но, пожалуйста, дайте мне знать, что вы думаете. - person Steve Haley; 30.12.2009
comment
На самом деле, это не источник проблемы в вашем случае. Но ваш код выглядит нормально, поэтому не могли бы вы предоставить дополнительную информацию: 1. Как вы обновляете свой виджет (вручную или с помощью android:updatePeriodMillis в вашем файле appwidget-provider)? 2. Я предполагаю, что ваш файл макета для виджета содержит ImageView с идентификатором image_in_widget, верно? 3. Вы устанавливаете первоначальный макет в appwidget-provider? - person Ramps; 30.12.2009
comment
1. Я попытался обновить его с помощью действия конфигурации, которое передает намерение, и, проще говоря, с помощью строки android:updatePeriodMillis в файле xml. 2. Действительно. Насколько я могу судить, идентификатор правильно распознан, поскольку ему присвоено значение в файле R.java. 3. Нет, исходную раскладку я больше нигде не устанавливал. Я попробую сделать это, чтобы увидеть, что происходит. - person Steve Haley; 30.12.2009
comment
На самом деле, все примеры, которые я прочитал до сих пор, похоже, не объявляют начальный макет, поэтому, если вы не думаете, что я должен это сделать, я оставлю код как есть. Кстати, я добавил XML-макет виджета в основной пост выше. Еще раз спасибо за вашу помощь! - person Steve Haley; 30.12.2009