【问题标题】:AppWidget setFillInIntent can't handle data set in setData or componentName?AppWidget setFillInIntent 无法处理 setData 或 componentName 中的数据集?
【发布时间】:2012-10-04 00:20:54
【问题描述】:

我想从我的应用小部件启动不同的应用。小部件是一个项目列表,单击一个项目应该会打开一个应用程序,例如 Google Plus。当按下列表中的项目时,没有任何反应。当我删除 setData 和 setComponentName 时,它​​会弹出一个对话框,询问要使用什么应用程序。 appWidget 集合上的 PendingIntent 不能合并数据和组件名吗?

我的 AppWidgetProvider 如下所示:

public class StreamsWidgetProvider extends AppWidgetProvider {

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
        int[] appWidgetIds) {

    final int N = appWidgetIds.length;

        for (int i=0; i<N; i++) {
            int appWidgetId = appWidgetIds[i];

            RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);

            ...

            //set service for list view
            Intent listIntent = new Intent(context, StreamsWidgetService.class);
            listIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
            listIntent.setData(Uri.parse(listIntent.toUri(Intent.URI_INTENT_SCHEME)));
            views.setRemoteAdapter(R.id.streamItemsList, listIntent);

            ...

            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
            views.setPendingIntentTemplate(R.id.streamItemsList, pendingIntent);
            appWidgetManager.updateAppWidget(appWidgetId, views);
        }

        super.onUpdate(context, appWidgetManager, appWidgetIds);
    }
}

}

StreamsWidgetService 看起来像这样:

public class StreamsWidgetService extends RemoteViewsService {
    private static final String TAG = "StreamsWidgetService";

    @Override
    public RemoteViewsFactory onGetViewFactory(Intent intent) {
        return new StreamItemWidgetFactory(intent);
    }

    private class StreamItemWidgetFactory implements RemoteViewsService.RemoteViewsFactory {
        @Override
        public RemoteViews getViewAt(int position) {
            StreamItem item = mItems.get(position);

            RemoteViews rv = new RemoteViews(getPackageName(), R.layout.widget_item);
            ...

            Intent intent = new Intent();
            intent.setData(ContentUris.withAppendedId(StreamItems.CONTENT_URI, item.getId()));

            AccountType at = item.getAccountType();
            intent.setComponent(new ComponentName(at.getPackageName(), at.getViewStreamItemActivity()));
            rv.setOnClickFillInIntent(R.id.streamItemRowId, intent);
            Log.d(TAG, "FillIntent set for " + item.getId() + " at position " + position + " with data " + intent.getDataString() + " and component " + intent.getComponent().toString());

            return rv;
        }

        ...
    }
}

当使用没有 fillIntent 的正常活动时,这可行:

final AccountType at = item.getAccountType();
final Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(ContentUris.withAppendedId(StreamItems.CONTENT_URI, item.getId()));
intent.setClassName(at.getPackageName(), at.getViewStreamItemActivity());
startActivity(intent);

我该如何解决这个问题?我做错了什么?

【问题讨论】:

    标签: android android-intent android-appwidget android-pendingintent appwidgetprovider


    【解决方案1】:

    PendingIntent 不允许填写组件,除非您特别要求。

    PendingIntent pendingIntent = PendingIntent.getActivity(context,
        0, intent, Intent.FILL_IN_COMPONENT);
    

    请注意,这与其他 FILL_IN_* 标志的工作方式不同。

    【讨论】:

    • 我会试试这个,如果可行的话,我会把你的答案设置为接受的答案。 :)
    • 我使用来自Daverix answer 的方法,但它看起来很慢。所以我尝试直接从点击开始活动,并用你的答案实现了它,但它看起来并没有更快。是“正常的”吗?我能期待更好吗?
    • 如果您的应用程序已从内存中删除,Daverix 的答案将要求将其加载回内存,而此答案将允许点击直接启动目标应用程序而无需加载您的应用程序,这可能是明显更快。但是,如果设备有足够的内存,那么这种差异就无关紧要了。影响响应时间的主要因素将是启动器正在做什么以及其他应用正在做什么,这两者您都无法控制。
    【解决方案2】:

    我通过对我自己的 AppWidgetProvider 使用广播意图解决了这个问题。我有自己的操作,我在 onReceive 中检查。然后,我使用包名、类名和数据 ID 的参数设置 fillInIntent。在 onReceive 方法中使用它,我可以创建一个看起来与我的 ListActivity 中的意图完全相同的新意图。

    在服务中:

    Intent intent = new Intent();
    intent.putExtra(StreamsWidgetProvider.BROADCAST_PARAM_ITEM_ID, item.getId());
    AccountType at = item.getAccountType();
    intent.putExtra(StreamsWidgetProvider.BROADCAST_PARAM_CLASS_NAME, at.getViewStreamItemActivity());
    intent.putExtra(StreamsWidgetProvider.BROADCAST_PARAM_PACKAGE_NAME, at.getPackageName());
    
    rv.setOnClickFillInIntent(R.id.streamItemRowId, intent);
    

    在 AppWidgetProvider 中:

    public static final String ACTION_START_ACTIVITY = "startActivity";
    public static final String BROADCAST_PARAM_ITEM_ID = "intentId";
    public static final String BROADCAST_PARAM_PACKAGE_NAME = "intentPackage";
    public static final String BROADCAST_PARAM_CLASS_NAME = "intentClassName";
    
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
            int[] appWidgetIds) {
    
        final int N = appWidgetIds.length;
    
        for (int i=0; i<N; i++) {
            int appWidgetId = appWidgetIds[i];
    
            RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
    
            ...
    
            Intent intent = new Intent(context, StreamsWidgetProvider.class);
            intent.setAction(ACTION_START_ACTIVITY);
            PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
            views.setPendingIntentTemplate(R.id.streamItemsList, pendingIntent);
    
            appWidgetManager.updateAppWidget(appWidgetId, views);
        }
    
        super.onUpdate(context, appWidgetManager, appWidgetIds);
    }
    
    @Override
    public void onReceive(Context context, Intent intent) {
        if(ACTION_START_ACTIVITY.equals(intent.getAction())) {
            long itemId = intent.getLongExtra(BROADCAST_PARAM_ITEM_ID, 0);
            String packageName = intent.getStringExtra(BROADCAST_PARAM_PACKAGE_NAME);
            String className = intent.getStringExtra(BROADCAST_PARAM_CLASS_NAME);
    
            Intent i = new Intent(Intent.ACTION_VIEW);
            i.setData(ContentUris.withAppendedId(StreamItems.CONTENT_URI, itemId));
            i.setComponent(new ComponentName(packageName, className));
            i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    
            context.startActivity(i);
        }
    
        super.onReceive(context, intent);
    }
    

    【讨论】:

    • 这一切都不是必须的;请参阅下面的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-19
    • 1970-01-01
    • 2022-08-22
    • 1970-01-01
    • 1970-01-01
    • 2018-01-13
    • 2021-03-10
    相关资源
    最近更新 更多