Android 将整数数组从AppWidget传递给RemoteViewsFactory要呈现的现有RemoteViewsService

Android 将整数数组从AppWidget传递给RemoteViewsFactory要呈现的现有RemoteViewsService,android,android-widget,android-service,android-appwidget,stackview,Android,Android Widget,Android Service,Android Appwidget,Stackview,我有一个AppWidget,其中包含一个StackView。除了AppWidget之外,我还有一个服务,当用户将我的AppWidget添加到他们的主屏幕上,每两小时轮询一次新数据时,该服务就会启动。当服务发现新数据时,我需要它通知我的AppWidget,并将该数据传递给RemoteViewsService(其中包含我的RemoteViewsFactory),以便它可以为新数据创建必要的视图 目前,当服务发现新数据时,我让它向我的AppWidget广播发现了新数据,并将该数据作为intent中的整

我有一个AppWidget,其中包含一个StackView。除了AppWidget之外,我还有一个服务,当用户将我的AppWidget添加到他们的主屏幕上,每两小时轮询一次新数据时,该服务就会启动。当服务发现新数据时,我需要它通知我的AppWidget,并将该数据传递给RemoteViewsService(其中包含我的RemoteViewsFactory),以便它可以为新数据创建必要的视图

目前,当服务发现新数据时,我让它向我的AppWidget广播发现了新数据,并将该数据作为intent中的整数数组传递

我的AppWidgetProvider中的onReceive方法将该数据取出,然后我将完成设置新意图的过程,该意图将传递给AppWidget的RemoteView。示例代码如下:

public void onReceive( Context context, Intent intent )
{
    int[] appWidgetIds = appWidgetManager.getAppWidgetIds( new ComponentName( context,  SampleAppWidgetProvider.class ) );

    int[] sampleData = intent.getIntArrayExtra( Intent.EXTRA_TITLE );
    for ( int i = 0; i < appWidgetIds.length; i++ )
    {
        // RemoteViewsFactory service intent
        Intent remoteViewsFactoryIntent = new Intent( context, SampleAppWidgetService.class );
        remoteViewsFactoryIntent.putExtra( AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i] );
        remoteViewsFactoryIntent.setData( Uri.parse( remoteViewsFactoryIntent.toUri( Intent.URI_INTENT_SCHEME ) ) );
        remoteViewsFactoryIntent.putExtra( Intent.EXTRA_TITLE, sampleData );

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

        // Sync up the remoteviews factory
        rv.setRemoteAdapter( appWidgetIds[i], R.id.sample_widget, remoteViewsFactoryIntent );           
        rv.setEmptyView( R.id.sample_widget, R.id.empty_view );

        appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
    }

    super.onUpdate( context, appWidgetManager, appWidgetIds );
}
public void onReceive(上下文、意图)
{
int[]appWidgetIds=appWidgetManager.getAppWidgetIds(新组件名称(上下文,SampleAppWidgetProvider.class));
int[]sampleData=intent.getIntArrayExtra(intent.EXTRA_TITLE);
for(int i=0;i
这是第一次。数据由RemoteViewsService/RemoteViewsFactory显示。后续的新数据不会命中RemoteViewsFactory的构造函数,因为该工厂的服务已在运行

如何更新数据?我觉得应该使用onDataSetChanged,但是如何访问从AppWidget的onReceive传递的意图呢


对于如何正确处理这件事,我非常感激。谢谢。

我对传递给RemoteViewsFactory的整数数组的解决方案是使用BroadcastReceiver解决的。我扩展了RemoteViewsFactory以实现BroadcastReceiver(特别是onReceive),并在工厂的构造函数中向我的应用程序注册了它(这也意味着我在onDestroy中注销了它)。这样,我就可以使用AppWidgetProvider的onReceive中的整数数组广播意图,并在RemoteViewsFactory中接收它


确保同时调用AppWidgetManager的notifyAppWidgetViewDataChanged,以便RemoteViewsFactory知道它以前使用的数据已无效,并提供一个新的整数数组来创建新的RemoteView。

为了arne.jans和其他人的利益,进一步阐述Steve的解决方案,我通过以下方式实施了Steven的解决方案:

  • StackRemoteViewsFactory
    提取到自己的类文件中
  • 使用
    广播接收器扩展它
  • 实现
    onReceive()
    方法将新数据保存到静态变量中,
    StackRemoteViewsFactory
    类在其
    getViewAt
    需要数据时也可以访问该静态变量
  • 通过
    Intent
    传入所有小部件ID,以便调用
    onReceive()
    方法中所有小部件的
    notifyAndUpdate
  • 最后,我将接收器的标准定义添加到AndroidManifest.xml中

我没有使用BroadcastReceiver扩展RemoteViewFactory,而是在其上实现动态BroadcastReceiver以将字符串从AppWidgetProvider传递到RemoteViewFactory

像这样:

public class MyWidgetProvider extends AppWidgetProvider {
    @Override
    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);

        String action = intent.getAction();
        if (action.equals("android.appwidget.action.APPWIDGET_UPDATE")) {
            .....
        } else if (action.equals("some.string.you.want.ACTION_TODO")) {
            String url = intent.getStringExtra("some.string.you.want.EXTRA_URL");

            // Send broadcast intent to pass mUrl variable to the MyContentFactory.
            Intent broadcastIntent = new Intent("some.string.you.want.ACTION_UPDATE_URL");
            broadcastIntent.putExtra("some.string.you.want.EXTRA_URL", url);
            context.sendBroadcast(broadcastIntent);
        }
        .....
    }
}

public class MyContentFactory implements RemoteViewsService.RemoteViewsFactory {
    private Context mContext;
    private String mUrl; // target to update
    private BroadcastReceiver mIntentListener;

    public MyContentFactory(Context context, Intent intent) {
        mContext = context;
        setupIntentListener();
    }

    @Override
    public void onDestroy() {
        teardownIntentListener();
    }

    private void setupIntentListener() {
        if (mIntentListener == null) {
            mIntentListener = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    // Update mUrl through BroadCast Intent
                    mUrl = intent.getStringExtra("some.string.you.want.EXTRA_URL");
                }
            };
            IntentFilter filter = new IntentFilter();
            filter.addAction("some.string.you.want.ACTION_UPDATE_URL");
            mContext.registerReceiver(mIntentListener, filter);
        }
    }

    private void teardownIntentListener() {
        if (mIntentListener != null) {
            mContext.unregisterReceiver(mIntentListener);
            mIntentListener = null;
        }
    }
}

另一种选择是使用文件系统或sqlite数据库,例如

在AppWidgetProvider中:

 File file = new File(context.getCacheDir(), "filename that service also knows");
 writeFile(file, "my content");  // impl. not shown; uses BufferedWriter.java
在RemoteViewsService中:

 File file = new File(context.getCacheDir(), "filename that service also knows");
 if (file.exists()) {
     // handle params contained within file
     file.delete(); // clear for next run
 } 

如果我可以让RemoteViewsService中的onGetViewFactory再次运行,我将能够从传递给数据的意图中获取新数据。或者,如果我能告诉服务刷新它的数据…你能发布详细的代码说明你是如何实现的吗?我搞不清楚。谢谢你的提示!