Pergunta

I've implementing a widget with RemoteViewsService containing with a ListView of items where all the items are clickable to launch a service. In short I'm using setPendingIntentTemplate in my AppWidgetProvider.onUpdate() and setOnClickFillInIntent in my RemoteViewsService.RemoteViewsFactory().

And in most cases I get the expected behavior. However, when using up some memory and going back to try to click on an item in the list again sometimes nothing happens when clicking on items in a list: the service isn't launched, and no touch feedback is given. If I have several widgets one of the lists may have the problem while the others don't.

Does anyone know how to solve this problem?

Some other testing has revealed that:

  • If I scroll for a while in a list with the problem and then try to click again, it works! My first thought was that the reason was that RemoteViewsFactory.getView was called and so updated the pending intent, but checking the logs I can see that this method isn't entered.
  • I've also logged RemoteViewsService.RemoteViewsFactory.onDestroy to see if the reason for the problem was that this was removed, but this was not the case.
  • If I manage to call AppWidgetManager.updateAppWidget (so that AppWidgetProvider.onUpdate will run) the problem dissapears (I call updateAppWidget from inside my main app).

These three observations seems to point to the problem being in AppWidgetManager rather than RemoteViewsFactory.

AppWidgetProvider.onUpdate:

@Override
public void onUpdate(Context iContext, AppWidgetManager iWidgetMgr,
        int[] iWidgetIds){
    Log.d(DbgU.getAppTag(), DbgU.getMethodName());

    //Going through all widgets placed (could be more than one)
    for(int i = 0; i < iWidgetIds.length; i++){
        //Setting up the remote view service
        Intent tmpRVServiceIntent = new Intent(iContext,
                RemoteViewsServiceC.class);
        tmpRVServiceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
                iWidgetIds[i]);
        tmpRVServiceIntent.setData(Uri.parse(tmpRVServiceIntent.toUri(
                Intent.URI_INTENT_SCHEME)));

        //Setting up the remote views
        RemoteViews tmpRemoteViews = new RemoteViews(iContext.getPackageName(),
                R.layout.widget);
        tmpRemoteViews.setRemoteAdapter(R.id.widget_listview,
                tmpRVServiceIntent);
        tmpRemoteViews.setEmptyView(R.id.widget_listview,
                R.id.widget_empty_view);

        //Setting up the pending intent template (the id will be filled
        //in later in RemoteViewsFactoryC.getViewAt())
        Intent tmpTemplateIntent = new Intent(iContext,
                LauncherServiceC.class);

        tmpTemplateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
                iWidgetIds[i]);
        PendingIntent tmpPendingIntent = PendingIntent.getService(iContext,
                0, tmpTemplateIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        tmpRemoteViews.setPendingIntentTemplate(R.id.widget_listview,
                tmpPendingIntent);

        //Applying the update for the views
        iWidgetMgr.updateAppWidget(iWidgetIds[i], tmpRemoteViews);
    }
}

RemoteViewsService.RemoteViewsFactory.getViewAt:

@Override
public RemoteViews getViewAt(int inPosition) {
    Log.v(DbgU.getAppTag(), DbgU.getMethodName()
            + ", inPosition = " + inPosition);

    //Moving the cursor to the current position
    mItemCursor.moveToPosition(inPosition);

    //Extracting values from the database
    String tmpName = mItemCursor.getString(
            mItemCursor.getColumnIndexOrThrow(ItemTableM.COLUMN_NAME));
    long tmpItemId = mItemCursor.getLong(
            mItemCursor.getColumnIndexOrThrow(ItemTableM.COLUMN_ID));
    Uri tmpItemUri = DatabaseU.getItemUriFromId(tmpItemId);

    //Setting up the remote views object
    RemoteViews retRemoteViews = new RemoteViews(
            mContext.getPackageName(), R.layout.widget_listitem);
    retRemoteViews.setTextViewText(R.id.widget_listitem_textView, tmpName);

    //Adding action URI to the intent template which was set for all the
    //list rows in WidgetProviderC.onUpdate
    Intent tmpFillInIntent = new Intent();
    tmpFillInIntent.setData(tmpItemUri);
    retRemoteViews.setOnClickFillInIntent(R.id.widget_listitem_textView,
            tmpFillInIntent);

    return retRemoteViews;
}

I've been having this problem for a long time and am very grateful for any help

Foi útil?

Solução

I have also had the same problem for a long time.

On Sony devices that have Android 4.0, if you swipe to another home pane and then back to the one where the widget is, then widget list elements will not be clickable. Sony Android 4.1 and above do not have this problem but sometimes they show wrong list element. On some Samsung devices that have Android 4.1 I have seen the same problem. Android 4.0 emulator homescreen does not have this problem.

I have tried to fix it in many ways, also in this way: stackoverflow.com/questions/21891008/a-textview-in-a-listview-s-row-cannot-click-after-setting-descendantfocusabilit

However, I could not fix the problem which lead me to believe that it is a homescreen problem. To confirm that, I decided to install "Go Launcher" on a Sony Android 4.0 device, and there everything works as it should!

The answer: It is a homescreen problem which is most likely not possible to solve without using some kind of hack. Please tell me I am wrong.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top