Кнопки виджета Android перестают работать - PullRequest
12 голосов
/ 14 июля 2011

У меня есть приложение Android с виджетом, у которого есть кнопки. Этот код работает.

Кнопки на виджете перестают работать , когда что-то происходит, например, при смене языка телефона. Я использую общие настройки, поэтому , если пользователь переустанавливает приложение ( без удаления ), кнопки снова работают и настройки остаются установленными.

  • Я заметил, что Intents в моем AppWidgetProvider классе (код под этим анализом) не запускаются должным образом.
  • Я добавил сообщение Toast в класс Call1, созданный из AppWidgetProvider, но оно не отображается.
  • Мой UpdateService.java просто получает заданные настройки и настраивает внешний вид виджета, поэтому я не думаю, что это может быть связано с моей проблемой.
  • Мой Main.java файл просто состоит из счетчиков и сохраняет общие настройки, что означает, что я выбираю «Компьютер» в счетчике, так что текст «Компьютер» появляется на виджете. Он также не исчезает при смене языка телефона, как и изображения. Поэтому я считаю, UpdateService.java должно быть в порядке.

Вот класс AppWidgetProvider:

public class HelloWidget extends AppWidgetProvider {

    public static String ACTION_WIDGET_CONFIGURE = "ConfigureWidget";
    public static String ACTION_WIDGET_CONFIGURE2 = "ConfigureWidget";
    public static String ACTION_WIDGET_RECEIVER = "ActionReceiverWidget";
    public static String ACTION_WIDGET_RECEIVER2 = "ActionReceiverWidget";
    private static final int REQUEST_CODE_FOUR = 40;
    private static final int REQUEST_CODE_FIVE = 50;
    private static final int REQUEST_CODE_SIX = 60;
    private static final int REQUEST_CODE_SEVEN = 70;
    private static final int REQUEST_CODE_EIGHT = 80;

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        context.startService(new Intent(context, UpdateService.class));
        //Intent widgetUpdateIntent = new Intent(context, UpdateService.class);
        //context.startService(widgetUpdateIntent );

         RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widgetmain2);

         //P1 starts Call1.class
         Intent configIntent4 = new Intent(context, Call1.class);
         configIntent4.setAction(ACTION_WIDGET_CONFIGURE);
         PendingIntent configPendingIntent4 = PendingIntent.getActivity(context, REQUEST_CODE_FOUR, configIntent4, 0);
         remoteViews.setOnClickPendingIntent(R.id.ImageView01, configPendingIntent4);

         //P2 starts Call2.class
         Intent configIntent5 = new Intent(context, Call2.class);
         configIntent5.setAction(ACTION_WIDGET_CONFIGURE);
         PendingIntent configPendingIntent5 = PendingIntent.getActivity(context, REQUEST_CODE_FIVE, configIntent5, 0);
         remoteViews.setOnClickPendingIntent(R.id.ImageView02, configPendingIntent5);

         //P3 starts Call3.class
         Intent configIntent6 = new Intent(context, Call3.class);
         configIntent6.setAction(ACTION_WIDGET_CONFIGURE);
         PendingIntent configPendingIntent6 = PendingIntent.getActivity(context, REQUEST_CODE_SIX, configIntent6, 0);
         remoteViews.setOnClickPendingIntent(R.id.ImageView03, configPendingIntent6);

         //P4 starts Call4.class
         Intent configIntent7 = new Intent(context, Call4.class);
         configIntent7.setAction(ACTION_WIDGET_CONFIGURE);
         PendingIntent configPendingIntent7 = PendingIntent.getActivity(context, REQUEST_CODE_SEVEN, configIntent7, 0);
         remoteViews.setOnClickPendingIntent(R.id.ImageView04, configPendingIntent7);

         //P5 starts Call5.class
         Intent configIntent8 = new Intent(context, Call5.class);
         configIntent8.setAction(ACTION_WIDGET_CONFIGURE);
         PendingIntent configPendingIntent8 = PendingIntent.getActivity(context, REQUEST_CODE_EIGHT, configIntent8, 0);
         remoteViews.setOnClickPendingIntent(R.id.ImageView05, configPendingIntent8);

         appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
   }

    @Override
    public void onReceive(Context context, Intent intent) {

        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 
        {
            if (intent.getAction().equals(ACTION_WIDGET_RECEIVER)) 
            {
                String msg = "null";
                try {
                    msg = intent.getStringExtra("msg");
                    } catch (NullPointerException e) {
                    //Log.e("Error", "msg = null");
                    }
            }
            super.onReceive(context, intent);
            }
    }
}

У меня также есть EditPreferences.java, GlobalVars.java и некоторые другие ныне бессмысленные классы. Названия классов говорят сами за себя.

Еще одна вещь. У меня также есть Widgetmain.java:

  public class WidgetMain extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.widgetmain2);
    }
    static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) 
    {
        RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widgetmain2);

          appWidgetManager.updateAppWidget(appWidgetId, remoteViews);

    }
}

Редактировать: Как насчет этого:

Когда я устанавливаю это приложение на ZTE Blade моего коллеги, текстовые представления на виджете загружаются не с соответствующим текстом, а с тем, который определен в strings.xml.

Когда я переустанавливаю приложение (без деинсталляции), загружаются текстовые представления и все в порядке. Эта проблема не возникает на моем HTC Desire HD.

Текстовые представления загружаются в вышеупомянутый UpdateService.java следующим образом (часть кода):

RemoteViews updateViews = new RemoteViews(this.getPackageName(), R.layout.main);
updateViews.setTextViewText(R.id.widget_textview, name);
ComponentName thisWidget = new ComponentName(this, HelloWidget.class);
AppWidgetManager manager = AppWidgetManager.getInstance(this);
manager.updateAppWidget(thisWidget, updateViews);

Даже если «name» является статическим (например, String name = «Something»), это текстовое представление по-прежнему не загружается при первой установке.

Ответы [ 7 ]

6 голосов
/ 07 ноября 2011

Попробуйте обновить RemoteView с помощью прослушивателей щелчков при каждом создании нового экземпляра с помощью «новых RemoteView». Возможно, при некоторых обстоятельствах RemoteView заново загружаются из XML, поэтому прослушиватели щелчков необходимо переназначить.

5 голосов
/ 19 октября 2011

Мой UpdateService.java просто получает заданные настройки и настраивает внешний вид виджета, поэтому я не думаю, что это может быть связано с моей проблемой.

Возможно, это связано с тем, что вы можете использовать его для «обновления» ожидаемого намерения. У меня есть похожая проблема в моем appwidget, что кнопка изображения перестает реагировать на нажатия после некоторого случайного времени выполнения (часы).

Я нашел эту тему: Кнопка AppWidget onClick перестает работать

И эта цитата:

Ожидаемое намерение «сжигается» после каждого использования. Вам нужно установить его снова. Или подождите, пока обновится виджет, тогда это тоже случится, но это, вероятно, не тот путь.

Учитывая, что время обновления виджета обычно устанавливается на много часов или дней (у меня это 86400000 миллисекунд), чтобы не допускать зависания телефона каждые столько минут, ваш виджет не будет часто запускаться при обновлении. Возможно, что установка ожидающего намерения ТАКЖЕ в службе обновлений предотвратит описанную вами проблему. Каждый раз, когда служба обновлений запускает ожидающее намерение, создается заново.

Сегодня я добавил это возможное исправление в мой appwidget, и мне нужно подождать и посмотреть, действительно ли исправление работает, но пока все хорошо.

Я добавил следующий код в цикл службы обновлений, где он обновляет каждый виджет:

for (int i=0; i<appWidgetIds.length; i++)
{
  appWidgetId=appWidgetIds[i];

  /* other stuff to do */

  RemoteViews views=new RemoteViews(context.getPackageName(), R.layout.example_appwidget);

  /* here you "refresh" the pending intent for the button */
  Intent clickintent=new Intent("net.example.appwidget.ACTION_WIDGET_CLICK");
  PendingIntent pendingIntentClick=PendingIntent.getBroadcast(context, 0, clickintent, 0);
  views.setOnClickPendingIntent(R.id.example_appwidget_button, pendingIntentClick);
  appWidgetManager.updateAppWidget(appWidgetId, views);

  /* then tell the widget manager to update */
  appWidgetManager.updateAppWidget(appWidgetId, views);
}
2 голосов
/ 24 мая 2014

Проблема в том, что вы не можете выполнить частичное обновление для виджета, вы должны установить все функции виджета, такие как набор PendingIntent, каждый раз, когда вы нажимаете новый remoteView. (Частичные обновления доступны только для API14 и выше ...).

Причина, по которой ваши виджеты теряют свои pendingIntents, заключается в том, что система Android сохраняет remoteView и перестраивает ваш виджет с ним, если он сбрасывает виджет (нехватка памяти, использование TaskManager / taskKiller и т. Д.), поэтому вы должны установить весь код обновления для виджета в remoteView в вашем updateService. В противном случае он просто не установит pendingIntents снова.

Так что просто добавьте код, устанавливающий pendingIntents в сервис, и ваша проблема будет решена =]

0 голосов
/ 22 апреля 2019

Если у кого-то все еще есть эта проблема, попробуйте установить атрибут android: updatePeriodMillis в вашем AppWidgetProviderInfo; По разным причинам операционная система может убить ожидающее намерение, и ваши кнопки могут перестать работать. Когда вы устанавливаете этот атрибут, вы сообщаете Android, когда он должен вызывать метод onUpdate в AppWidgetProvider, поэтому все ожидающие намерения будут воссозданы.

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    ...
    android:updatePeriodMillis="3600000">
</appwidget-provider>
0 голосов
/ 18 июня 2012

У меня была эта проблема в течение долгого времени.У моего виджета есть кнопка @ (onUpdate).У виджета есть сервис обновлений.Кнопка на виджете перестает работать, когда что-то происходит, например: изменение шрифта и т. Д.

Когда я переустанавливаю приложение, кнопка снова работает.Наконец, я понял, что никогда не вызывал onUpdate в своем классе Service.

Вызов onUpdate из класса обслуживания устранил проблему.

0 голосов
/ 06 сентября 2011

Учитывая всю предоставленную вами информацию, я бы сказал, что ваш метод обновления не запускается должным образом при изменении настроек.

Полагаю, что после стольких тестов вы убедились, что ваш файл манифеста содержит:

    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>

Подтверждено ли, что onUpdate запускается?Мне кажется, что если переустановка приложения без деинсталляции решает ваши проблемы, это может быть вызвано тем, что он вызывает вызов обновления.

После тщательной проверки выясняется, что ScanPlayGames имеет смысл: официальная документация пример использует super.onUpdate ().Обратите внимание, что он использует его в конце метода, но несколько примеров о состоянии Интернета вам лучше использовать, используя его в начале вашего метода.

0 голосов
/ 10 августа 2011

Я думаю, что PendingIntents, возможно, понадобится передать флаг, возможно, попробуйте изменить:

PendingIntent.getActivity(context, REQUEST_CODE, configIntent, 0);

до:

PendingIntent.getActivity(context, REQUEST_CODE, configIntent, PendingIntent.FLAG_UPDATE_CURRENT);

Из документации PendingIntent я думаю, что код '0' не определен. В этом случае FLAG_UPDATE_CURRENT будет работать лучше всего, так как вы, вероятно, захотите обновлять Intent каждый раз, когда нажимаете кнопку.

...