appwidget listview update issue in android

1.8k views Asked by At

duplicate question enter link description here

even i am facing same problem ,so i have imageview on app widget on click to that, app widget listview should be updated, in my code when i call to update list view in onreceive method action=UPDATE_ACTION ,it calls updateWidgetListView method which update the widget but in my case it is not updating listview, were i am going wrong please suggest

here is my code

package com.wordpress.laaptu;

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.util.Log;
import android.view.View;
import android.widget.RemoteViews;

public class WidgetProvider extends AppWidgetProvider {

    // String to be sent on Broadcast as soon as Data is Fetched
    // should be included on WidgetProvider manifest intent action
    // to be recognized by this WidgetProvider to receive broadcast
    public static final String DATA_FETCHED = "com.wordpress.laaptu.DATA_FETCHED";
    public static String MANIFEST_DEFINED_STRING = "com.refresh.widget";
    final static String WIDGET_UPDATE_ACTION ="UPDATE_WIDGET";
    AppWidgetManager appWidgetManager;
    ComponentName currentWidget;

    /*
     * this method is called every 30 mins as specified on widgetinfo.xml this
     * method is also called on every phone reboot from this method nothing is
     * updated right now but instead RetmoteFetchService class is called this
     * service will fetch data,and send broadcast to WidgetProvider this
     * broadcast will be received by WidgetProvider onReceive which in turn
     * updates the widget
     */

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
            int[] appWidgetIds) {
        final int N = appWidgetIds.length;
        Log.i("inside", "WidgetProvider");

        /*
         * RemoteViews viewClick = new
         * RemoteViews(context.getPackageName(),R.layout.widget_layout);
         * 
         * Intent informationIntent = new Intent(context,info.class);
         * PendingIntent infoPendingIntent =
         * PendingIntent.getActivity(context,0, informationIntent, 0); //
         * viewClick.setOnClickPendingIntent(R.id.txtSeeMore,infoPendingIntent);
         * 
         * viewClick.setOnClickPendingIntent(R.id.txtSeeMore,
         * PendingIntent.getBroadcast(context, 0, new Intent(context,
         * info.class) .setAction("android.intent.category.INFO"),
         * PendingIntent.FLAG_UPDATE_CURRENT));
         */

        for (int i = 0; i < N; i++) {
            Log.i("appWidgetIds", Integer.toString(appWidgetIds[i]));
            Intent serviceIntent = new Intent(context, RemoteFetchService.class);
            serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
                    appWidgetIds[i]);
            context.startService(serviceIntent);
        }

        /*
         * this.appWidgetManager = appWidgetManager; //this is a onclick event
         * while no internet connection, currentWidget = new
         * ComponentName(context, WidgetProvider.class); RemoteViews
         * defaultRemoteView = new RemoteViews( context.getPackageName(),
         * R.layout.widget_layout); Intent informationIntent = new
         * Intent(context, MainActivity.class); PendingIntent infoPendingIntent
         * = PendingIntent.getActivity(context, 0, informationIntent, 0);
         * defaultRemoteView.setOnClickPendingIntent(R.id.img_SeeMore,
         * infoPendingIntent); appWidgetManager.updateAppWidget(currentWidget,
         * defaultRemoteView);
         * defaultRemoteView.setEmptyView(R.id.listViewWidget, R.id.empty_view);
         */
        super.onUpdate(context, appWidgetManager, appWidgetIds);
    }

    private RemoteViews updateWidgetListView(Context context, int appWidgetId) {
        Log.i("inside", "updateWidgetListView");
        Log.i("appWidgetIds", Integer.toString(appWidgetId));
        // which layout to show on widget
        RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
                R.layout.widget_layout);

        final Intent refreshIntent = new Intent(context, WidgetProvider.class);
        refreshIntent
                .putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        refreshIntent.setAction(WidgetProvider.MANIFEST_DEFINED_STRING);

        /*
         * final PendingIntent refreshPendingIntent =
         * PendingIntent.getBroadcast( context, appWidgetId, refreshIntent,
         * PendingIntent.FLAG_UPDATE_CURRENT);
         * remoteViews.setOnClickPendingIntent(R.id.img_SeeMore,
         * refreshPendingIntent);
         */
        // RemoteViews Service needed to provide adapter for ListView
        Intent svcIntent = new Intent(context, WidgetService.class);
        // passing app widget id to that RemoteViews Service
        svcIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        // setting a unique Uri to the intent
        // don't know its purpose to me right now
        svcIntent.setData(Uri.parse(svcIntent.toUri(Intent.URI_INTENT_SCHEME)));
        // setting adapter to listview of the widget
        remoteViews.setRemoteAdapter(appWidgetId, R.id.listViewWidget,
                svcIntent);

        // setting an empty view in case of no data
        remoteViews.setEmptyView(R.id.listViewWidget, R.id.empty_view);

        return remoteViews;
    }

    /*
     * It receives the broadcast as per the action set on intent filters on
     * Manifest.xml once data is fetched from RemotePostService,it sends
     * broadcast and WidgetProvider notifies to change the data the data change
     * right now happens on ListProvider as it takes RemoteFetchService
     * listItemList as data
     */
    @Override
    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);
        Log.i("inside", "onReceive");
        Log.i("getaction", intent.getAction());
        if (intent.getAction().equals(DATA_FETCHED)) {
            Log.i("inside action", "DATA_FETCHED");
            int appWidgetId = intent.getIntExtra(
                    AppWidgetManager.EXTRA_APPWIDGET_ID,
                    AppWidgetManager.INVALID_APPWIDGET_ID);
            Log.i("appWidgetIds", Integer.toString(appWidgetId));
            AppWidgetManager appWidgetManager = AppWidgetManager
                    .getInstance(context);
            RemoteViews remoteViews = updateWidgetListView(context, appWidgetId);

            Intent informationIntent = new Intent(context, MainActivity.class);
            PendingIntent infoPendingIntent = PendingIntent.getActivity(
                    context, 0, informationIntent, 0);
            remoteViews.setOnClickPendingIntent(R.id.img_SeeMore,
                    infoPendingIntent);

             Intent widgetIntent = new Intent(context, WidgetProvider.class);
                widgetIntent.setAction(WIDGET_UPDATE_ACTION);
                widgetIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
                //PendingIntent widgetPendingIntent = PendingIntent.getBroadcast(context, 0, widgetIntent, 0);
                PendingIntent widgetPendingIntent = PendingIntent.getBroadcast(context, appWidgetId, widgetIntent, 0);
            remoteViews.setOnClickPendingIntent(R.id.img_refresh,widgetPendingIntent);

            // remoteViews.setViewVisibility(R.id.txtSeeMore, View.VISIBLE);

            /*
             * RemoteViews newView = new RemoteViews(context.getPackageName(),
             * R.layout.seemore); newView.setTextViewText(R.id.txt_extra,
             * "1234"); remoteViews.addView(R.id.lay_title, newView);
             */

            appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
        }

        // this is on clickclick event of view more when internet connection is
        // there
        // & service running
        else if (MANIFEST_DEFINED_STRING.equals(intent.getAction())) {
            Log.i("inside action", "MANIFEST_DEFINED_STRING");
            Intent settingIntent = new Intent(context, MainActivity.class);
            settingIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(settingIntent);
        }
        else if (WIDGET_UPDATE_ACTION.equals(intent.getAction())) {
            Log.i("inside action", "WIDGET_UPDATE_ACTION");
             AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context.getApplicationContext());
                int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context.getApplicationContext(), WidgetProvider.class));
                for (int i = 0; i < appWidgetIds.length; i++) 
                {
                    Log.i("appWidgetIds", Integer.toString(appWidgetIds[i]));
                    Intent serviceIntent = new Intent(context, RemoteFetchService.class);
                    serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
                            appWidgetIds[i]);
                    context.startService(serviceIntent);
                }
                //onUpdate(context,appWidgetManager,appWidgetIds); 
        }

    }

    /*public static PendingIntent refreshWidget(Context context) {

        // initiate widget update request
        Intent intent = new Intent();
        intent.setAction(WIDGET_UPDATE_ACTION);
        return PendingIntent.getBroadcast(context, 0, intent,
                PendingIntent.FLAG_UPDATE_CURRENT);
    }*/

} 

here is my logcat when i run my code

12-12 14:13:53.221: I/inside(5904): WidgetProvider
12-12 14:13:53.221: I/appWidgetIds(5904): 107
12-12 14:13:53.301: I/inside(5904): onReceive
12-12 14:13:53.301: I/getaction(5904): android.appwidget.action.APPWIDGET_UPDATE
12-12 14:13:53.441: I/widgetFor(5904): timeline
12-12 14:13:53.606: W/IInputConnectionWrapper(5904): showStatusIcon on inactive InputConnection
12-12 14:14:05.976: I/inside(5904): RemoteFetchService
12-12 14:14:06.106: I/calling(5904): populateWidget
12-12 14:14:06.106: I/inside(5904): populateWidget
12-12 14:14:06.131: I/inside(5904): onReceive
12-12 14:14:06.131: I/getaction(5904): com.wordpress.laaptu.DATA_FETCHED
12-12 14:14:06.131: I/inside action(5904): DATA_FETCHED
12-12 14:14:06.131: I/appWidgetIds(5904): 107
12-12 14:14:06.131: I/inside(5904): updateWidgetListView

here is logcat outut when i click on imageview of appwidget to update the listview

> 12-12 14:31:59.441: I/inside(11237): onReceive 12-12 14:31:59.441:
> I/inside action(11237): WIDGET_UPDATE_ACTION 12-12 14:31:59.441:
> I/appWidgetIds(11237): 107 12-12 14:31:59.461: I/widgetFor(11237):
> timeline 12-12 14:31:59.791: I/inside(11237): RemoteFetchService 12-12
> 14:31:59.816: I/calling(11237): populateWidget 12-12 14:31:59.816:
> I/inside(11237): populateWidget 12-12 14:31:59.841: I/inside(11237):
> onReceive 12-12 14:31:59.841: I/getaction(11237):
> com.wordpress.laaptu.DATA_FETCHED 12-12 14:31:59.841: I/inside
> action(11237): DATA_FETCHED 12-12 14:31:59.841: I/appWidgetIds(11237):
> 107 12-12 14:31:59.841: I/inside(11237): updateWidgetListView 12-12
> 14:31:59.841: I/appWidgetIds(11237): 107

so please help, to overcome this issue, thank you..

1

There are 1 answers

2
pitu On BEST ANSWER

finally i solved it, because RemoteViewsFactory caches the factory it creates for each widget ID. Hence when the same widget sends a request to create a new factory (through your Widget Adapter Service), the same factory is returned. Hence, the list view is not "updated".

so i tried (updateWidgetListView())

svcIntent.setData(Uri.fromParts("content",
                String.valueOf(appWidgetId + randomNumber), null));

& onGetViewFactory()

int appWidgetId = Integer.valueOf(intent.getData().getSchemeSpecificPart()) - WidgetProvider.randomNumber;