简体   繁体   中英

onDataSetChanged is not called in RemoteViewsFactory after notifyAppWidgetViewDataChanged is called

I'm trying to implement android app with widget, but found strange behavior on nexus 5 devices (i have two - one with lollipop, one with marshmallow). If I call AppWidgetManager.notifyAppWidgetViewDataChanged, widget's ListView content is refreshed on other devices (Nexus 3, ASUS K010), but on these two nothing happens. Couldn't find any info about this.

So here's my code: MainActivity.java.

public class MainActivity extends AppCompatActivity {
    public static final String PREFS_TAG = "StringList";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        View v = findViewById(R.id.fill);
        v.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                fillWidget();
            }
        });

        v= findViewById(R.id.clear);
        v.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                clearWidget();
            }
        });
    }

    private void fillWidget(){
        SharedPreferences preferences = getSharedPreferences(WidgetRemoteService.class.getSimpleName(), Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = preferences.edit();
        Set<String> strings = new HashSet<>();
        strings.add("111111111111111");
        strings.add("222222222222222");
        strings.add("333333333333333");
        strings.add("444444444444444");
        strings.add("555555555555555");
        strings.add("666666666666666");
        strings.add("777777777777777");
        strings.add("888888888888888");
        strings.add("999999999999999");
        editor.putStringSet(PREFS_TAG, strings);
        editor.commit();
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
        ComponentName componentName = new ComponentName(getApplicationContext(),WidgetProvider.class);
        int[] appWidgetIds = appWidgetManager.getAppWidgetIds(componentName);
        appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.listView);
    }

    private void clearWidget(){
        SharedPreferences preferences = getSharedPreferences(WidgetRemoteService.class.getSimpleName(), Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = preferences.edit();
        editor.remove(PREFS_TAG);
        editor.commit();
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
        ComponentName componentName = new ComponentName(getApplicationContext(),WidgetProvider.class);
        int[] appWidgetIds = appWidgetManager.getAppWidgetIds(componentName);
        appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.listView);
    }
}

WidgetProvider.java

public class WidgetProvider extends AppWidgetProvider {
    private static final String TAG = WidgetProvider.class.getSimpleName();

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        super.onUpdate(context, appWidgetManager, appWidgetIds);
        for (int appWidgetId : appWidgetIds) {
            appWidgetManager.updateAppWidget(appWidgetId,createRemoteViews(context, appWidgetId));
        }
    }

    public static RemoteViews createRemoteViews(Context context, int appWidgetId){
        Log.e(TAG, "Creating remote views");

        Intent intent = new Intent(context, WidgetRemoteService.class);
        // Add the app widget ID to the intent extras.
        Log.e(TAG, "Creating remote views for widget #"+appWidgetId);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));

        RemoteViews result = new RemoteViews(WidgetProvider.class.getPackage().getName(),R.layout.widget_layout);
        result.setRemoteAdapter(R.id.listView,intent);
        return result;
    }
}

WidgetRemoteService.java

public class WidgetRemoteService extends RemoteViewsService {
    private static final String TAG = WidgetRemoteService.class.getSimpleName();

    @Override
    public RemoteViewsFactory onGetViewFactory(Intent intent) {
        int appWidgetID = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
                AppWidgetManager.INVALID_APPWIDGET_ID);
        return new WidgetViewsFactory(getApplicationContext(), appWidgetID);
    }

    public static class WidgetViewsFactory implements RemoteViewsService.RemoteViewsFactory{
        private Context context;
        private String[] strings;
        private int appWidgetId;

        public WidgetViewsFactory(Context context, int appWidgetId){
            Log.e(TAG, "Factory created");
            this.context = context;
            this.appWidgetId = appWidgetId;
        }

        @Override
        public void onCreate() {

        }

        @Override
        public void onDataSetChanged() {
            Log.e(TAG, "Dataset changed");
            SharedPreferences preferences = context.getSharedPreferences(WidgetRemoteService.class.getSimpleName(), Context.MODE_PRIVATE);
            Set<String> stringSet = preferences.getStringSet(MainActivity.PREFS_TAG, new HashSet<String>());
            strings = stringSet.toArray(new String[]{});
        }

        @Override
        public void onDestroy() {

        }

        @Override
        public int getCount() {
            if (strings==null)
                return 0;
            else
                return strings.length;
        }

        @Override
        public RemoteViews getViewAt(int position) {
            RemoteViews result = new RemoteViews(getClass().getPackage().getName(),R.layout.widget_item);
            result.setTextViewText(R.id.textTitle,"This is title");
            result.setTextViewText(R.id.textContent,strings[position]);
            return result;
        }

        @Override
        public RemoteViews getLoadingView() {
            return null;
        }

        @Override
        public int getViewTypeCount() {
            return 1;
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

        @Override
        public boolean hasStableIds() {
            return false;
        }
    }
}

Here I try to update widget from MainActivity, but somehow it doesn't work on my nexus 5 devices - according to logs onDataSetChanged() is never called on this devices, but on others it works. Maybe I misunderstood something in guides, and it wasn't supposed to work, and works on other devices only because of some bug, which was fixed in later android versions?

try add

android:permission="android.permission.BIND_REMOTEVIEWS"

to RemoteViewsService in your AndroidManifest.xml , I was facing this problem too today.

I had a breakpoint set, wondering why onDataSetChanged wasn't getting called. It turns out that it got called, but only after I backgrounded my app and the widget was visible!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM