remoteviewsFactoryによってレンダリングされるように、AppWidgetから既存のRemoteviewsServiceに一連の整数を渡す

StackOverflow https://stackoverflow.com/questions/7367257

質問

スタックビューが含まれているAppWidgetがあります。 AppWidgetに加えて、ユーザーが2時間ごとに新しいデータを投票するホーム画面にAppWidgetを追加するときに開始されるサービスがあります。サービスが新しいデータを見つけたら、AppWidgetに警告する必要があり、そのデータをRemoteviewsService(RemoteviewsFactoryを備えています)に渡して、新しいデータに必要なビューを作成できるようにします。

現在、サービスが新しいデータを見つけたとき、新しいデータが見つかったことをAppWidgetにブロードキャストし、そのデータを意図の範囲内で整数の配列として渡します。

AppWidgetProviderの私のreceiveメソッドはそのデータを引き出し、AppWidgetのRemoteviewsに渡される新しい意図を設定するプロセスを実行します。以下のサンプルコード:

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 );
}

これは初めて機能します。データは、RemoteviewsService/RemoteviewsFactoryによって表示されます。その後の新しいデータは、その工場のサービスが既に実行されているため、RemoteviewsFactoryのコンストラクターにヒットしません。

データを更新するにはどうすればよいですか? ondatasethagedを使用する必要があると感じていますが、Appwidgetのreceiveから渡した意図にどのようにアクセスできますか?

これを適切に進める方法についての洞察に感謝します。ありがとう。

役に立ちましたか?

解決

RemoteviewsFactoryに渡される整数アレイに対する私の解決策は、BroadCastReceiverを使用して解決されました。 RemoteviewsFactoryを拡張して、Broadcastreceiver(特にReceive)を実装し、工場のコンストラクターでのアプリケーションに登録しました(これは、Ondestroyに登録されていないことも意味します)。それで、私は自分のappWidgetProviderのreceiveに持っていた整数アレイで意図をブロードキャストし、RemoteviewsFactory内でそれを受け取ることができました。

また、AppWidgetManagerのNotifyAppWidgetViewDatachangedにも電話してください。RemoteviewsFactoryは、以前に使用していたデータが無効になり、新しい整数アレイが提示されて新しいRemoteviewsを作成することを知っています。

他のヒント

Arne.jansなどの利益のために上記のSteveのソリューションについてさらに詳しく説明するために、私は次のようにStevenのソリューションを実装しました。

  • 抽出 StackRemoteViewsFactory 独自のクラスファイルに
  • で拡張します BroadcastReceiver
  • 実装 onReceive() 新しいデータを静的変数に保存する方法 StackRemoteViewsFactory クラスは、そのときにアクセスすることもできます getViewAt データが必要でした
  • すべてのウィジェットIDを介して渡します Intent だから私はaに電話することができます notifyAndUpdate のすべてのウィジェットの onReceive() 方法。
  • 最後に、レシーバーの標準定義をAndroidManifest.xmlに追加しました

BroadCastReceiverでRemoteviewFactoryを拡張することはありませんでしたが、AppWidgetProviderからRemoteViewFactoryに文字列を渡すために動的なBroadCastReceiverを実装しました。

このような:

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;
        }
    }
}

もう1つの選択肢は、ファイルシステムまたは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
 } 
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top