Widget frozen after HomeScreen restart
I've created widget which can be multiple instantiated with different settings stored in SharedPreferences. After solving initial problem with non-updating widgets directly after Configuration Activity (Multiple, configurable widgets - update issue ) everything seems to be working fine. But. When Home Screen application is killed/rebooted (Trebuchet in my case, Android 4.3 & 4.2.2) widget is not refreshed and onClick listeners are gone (onUpdate action is not triggered). I see only non-responsive, empty WigdetView with default, non-updated layout from xml. What is more weird - after phone reboot or after add another instance of my widget - everything works fine again.
I've tried many different ways to solve this strange issue (like single reference to RemoteViews, use Service instead of AsyncTask etc) - but none of this ideas solved the problem..
There are a lot of important logic in code, shortcut:
AppWidgetProvider :
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {  
// ASYNCTASK WAY    
    new DownloadTask(context, appWidgetManager).execute("http://sampleurl/");
/*      
// OR SERVICE WAY   
// SERVICE LOGIC IS ALMOST THE SAME AS IN DownloadTask              
    ComponentName thisWidget = new ComponentName(context, MyWidget.class);
    int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
    Intent intent = new Intent(context.getApplicationContext(), UpdateWidgetService.class);
    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds);
    context.startService(intent);
*/      
}
@Override
public void onReceive(Context context, Intent intent){
    Bundle extras = intent.getExtras();
    int mAppWidgetId=0;;
    if (extras != null) {
        mAppWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
    }
    String action = intent.getAction();
    if (action.equals("PreferencesUpdated")) {
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_lay);
        views.setViewVisibility(R.id.menuLayout, View.GONE);
        appWidgetManager.updateAppWidget(mAppWidgetId, views);
        int[] appWidgetIds = new int[] {mAppWidgetId};
        onUpdate(context, appWidgetManager, appWidgetIds);
    }
    else if (action.equals("ShowMenu")) {
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_lay);
        views.setViewVisibility(R.id.menuLayout, View.VISIBLE);
        appWidgetManager.updateAppWidget(mAppWidgetId, views);
    }   
    super.onReceive(context, intent);
}
DownloadTask
public DownloadTask(Context context, AppWidgetManager appWidgetManager) {
    this.context = context;
    this.appWidgetManager = appWidgetManager;
}
@Override
protected String doInBackground(String... url) {
    // 1. DOWNLOAD FILE
    // 2. PROCESS FILE, ADD TO DATABASE, ETC
    // 3. UPDATE ALL WIDGETS
        ComponentName thisWidget = new ComponentName(context, MyWidget.class);
        int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
        for (int widgetId : allWidgetIds) {
            SharedPreferences settings = context.getSharedPreferences(PREFS_NAME, 0);
            int myPref= settings.getInt("myPref"+widgetId, -1);
            if(myPref!= -1){
                Log.d("DownloadTask", "widget id:"+widgetId);
                updateWidget(db, widgetId, selectedStation);
            }
        }
        db.close();
    return null;
}
@Override
protected void onPreExecute() {
  super.onPreExecute();
  //SHOW PROGRESSBAR (LOADER) ON ALL WIDGETS
  //ADD onClicks
  ComponentName thisWidget = new ComponentName(context, MyWidget.class);
  RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_lay);
  int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
  for (int widgetId : allWidgetIds) {
      views.setViewVisibility(R.id.progressLayout, View.VISIBLE);
      views.setOnClickPendingIntent(R.id.linearLayout1, getMenuPendingIntent(context, widgetId));
      views.setOnClickPendingIntent(R.id.refreshButton, getRefreshPendingIntent(context, widgetId));
      views.setOnClickPendingIntent(R.id.settingsButton, getSettingsPendingIntent(context, widgetId));
      appWidgetManager.updateAppWidget(widgetId, views);
  }
}
@Override
protected void onPostExecute(String result) {
   super.onPostExecute(result);
   //HIDE PROGRESSBAR (LOADER) ON ALL WIDGETS
   ComponentName thisWidget = new ComponentName(context, MyWidget.class);
   RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_lay);
   views.setViewVisibility(R.id.progressLayout, View.INVISIBLE);
   appWidgetManager.updateAppWidget(thisWidget, views);
   if (exception){
       Toast.makeText(context, context.getString(R.string.net_exc), Toast.LENGTH_LONG).show();
   }
}
public void updateWidget(MySQLiteHelper db, int widgetId, int myPref){
    // UPDATE SINGLE WIDGET
    RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_lay);
    views.setTextViewText(R.id.someText, "someText");
    // ETC
    appWidgetManager.updateAppWidget(widgetId, views);
}
I really hope that you guys can help me, cause I'm stuck.
ps. This is expected behaviour that all widgets are refreshed together.
After having had a similar problem, my widget not working after restart of the launcher/homescreen, here a possible solution:
.setOnClickPendingIntent(...) again.   So basically speaking, in your onReceive() where you modify your RemoteViews add the corresponding lines to add the PendingIntent s, too, and everywhere else where you might modify those.  
 PS:  
 You can drop your for loop iterating over ALL widgetIds and just use  
void AppWidgetManager.updateAppWidget(ComponentName provider, RemoteViews views)
to update all your views at once.
链接地址: http://www.djcxy.com/p/8934.html上一篇: Android小部件上的按钮事件
