remoteviewsFactoryによってレンダリングされるように、AppWidgetから既存のRemoteviewsServiceに一連の整数を渡す
-
28-10-2019 - |
質問
スタックビューが含まれている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
}