Search code examples
androidandroid-appwidgetappwidgetprovider

parcelable object in appwidget provider always return null


I am always getting null, when getting parcelable object from RemoteViewsService in onReceive() method of AppWidgetProvider.

I tried it, passing string and int and it worked perfectly but not incase of parcelable.

StackWidgetProvider.java extends AppWidgetProvider

@Override
    public void onReceive(Context context, Intent intent) {
        if(intent.getAction().equals(INTENT_ACTION)){

            Artwork artwork = (Artwork) intent.getParcelableExtra(EXTRA_ART);
            Log.e("Intent","->"+artwork.getTitle());
            Intent showArtDetail = new Intent(context, ArtsDetailsActivity.class);
            showArtDetail.putExtra(ArtsDetailsActivity.TAG_ARTWORK, artwork);
            showArtDetail.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(showArtDetail);
        }

        super.onReceive(context, intent);
    }

StackWidgetService.java extends RemoteServiceView

Bundle extras = new Bundle();
extras.putParcelable(StackWidgetProvider.EXTRA_ART, artwork);

Intent fillInIntent = new Intent();
fillInIntent.putExtras(extras);
remoteViews.setOnClickFillInIntent(R.id.widget_item, fillInIntent);

Solution

  • A custom Parcelable class can only be used by processes that contain that class. Usually, that means the custom Parcelable class only works with an app's own process.

    The corollary to this is that there are many places where custom Parcelable implementations do not work, because some other process tries working with the Parcelable and fails with a ClassNotFoundException (or the equivalent).

    One such pattern is when you put a custom Parcelable as an extra in an Intent wrapped in a PendingIntent, and some other process wants to fill in that Intent with additional extras. Along the way, the other process will need access to the full Bundle of extras in the Intent, and that will fail because the other process lacks the custom Parcelable. In this case, the home screen would not have your custom Parcelable.

    Either:

    • Skip this custom Parcelable outright, or

    • Skip the custom Parcelable but put some identifier in as an extra that will allow you to get that Parcelable back later on (e.g., from a cache or, if needed, reloaded from a data store), or

    • Convert it into some other format first, such as converting it to a byte[], before putting it in the extra