このアプリには、バックグラウンドで動作するActivity
とService
で構成される機能を実装する必要がありました(Service
ではなくIntentService
を実装します)。
動作するはずのインターネット上のチュートリアルをいくつか試しましたが、それらはすべてLocalBroadcastManager
を使用しています。これは、Androidで推奨されています。
アプリケーション間でブロードキャストを送信する必要がない場合は、以下で説明するより一般的な機能の代わりに、このクラスを
LocalBroadcastManager
とともに使用することを検討してください。
なぜそれが機能しないのかという問題を見つけるために、文字通り1日を失いました。それは、Context.sendBroadcast()
を使用した場合にのみ機能します。 LocalBroadcastManager
メソッドの代わりにContext.registerReceiver()
。
現在、私のアプリは機能していますが、ベストプラクティスに反していると感じており、その理由はわかりません。なぜそれが起こっているのか考えはありますか?
編集:
この質問を書いた後、私はさらに問題を進めました。 LocalBroadcastManager
は、LocalBroadcastManager.getInstance(this).method()
を呼び出す必要があるため、シングルトンを介して機能します。両方のインスタンスを(Activity
とService
に)記録しましたが、メモリアドレスが異なります。今、私は別の質問に行きました、Service
はそれを呼んだContext
と同じActivity
を持つべきではありませんか? From この記事 サービスはメインスレッドで実行されるため、Context
は同じだと思います。
それについて何か考えはありますか? (長い投稿でごめんなさい)
コードサンプル:
MyService
public class MyService extends Service {
...
// When an event is triggered, sends a broadcast
Intent myIntent = new Intent(MainActivity.MY_INTENT);
myIntent.putExtra("myMsg","msg");
sendBroadcast(myIntent);
// Previously I was trying:
// LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(myIntent);
}
MyActivity
public class MainActivity {
...
private BroadcastReceiver messageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("onReceive", "received!");
// TODO something
}
};
@Override
protected void onResume() {
super.onResume();
registerReceiver(messageReceiver, new IntentFilter(MY_INTENT));
// Previously I was trying:
// LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(messageReceiver, new IntentFilter(MY_INTENT));
}
}
LocalBroadcastManagerを使用したことはありませんが、 レシーバーをそこに登録する (つまり、lbm.registerReceiver(...)
ではなくmycontext.registerReceiver(...)
)する必要があるようです。あなたはそれをしていますか?
今、私は別の質問に行き着きました、サービスはそれを呼び出したアクティビティと同じコンテキストを持つべきではありませんか?この記事から、サービスはメインスレッドで実行されるため、コンテキストは同じだと思います。
Contextクラスはスレッドとは関係ありません。実際、ServiceとActivityはどちらもContextの(間接的な)サブクラスであるため、独自のContextです。
そのため、「this」をコンテキストとして使用できます。
ただし、LocalBroadcastManager.getInstance()
に送信するコンテキストに関係なく、 まったく同じLBMインスタンス を取得する必要があります。アクティビティとサービスを異なるプロセスで実行している場合を除いて、そうしない理由は考えられません。
宣言:
private BroadcastReceiver receiver;
初期化:
receiver = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent)
{
//todo
}
};
登録:
LocalBroadcastManager.getInstance(context).registerReceiver(receiver, new IntentFilter("RECEIVER_FILTER"));
context
は任意のタイプのContext
にすることができ、アプリケーションコンテキストを使用できます。
登録解除:
LocalBroadcastManager.getInstance(context).unregisterReceiver(receiver);
放送:
Intent intent = new Intent("RECEIVER_FILTER");
intent.putExtra("EXTRA", someExtra);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
サービスとアクティビティが異なるプロセスで実行されているかどうかを確認してください。LocalBroadcastManagerは異なるプロセスに適用できません(AndroidManifest.xmlファイルに表示されます)。