web-dev-qa-db-ja.com

Context.registerReceiverの代わりにLocalBroadcastManagerが機能しないのはなぜですか?

このアプリには、バックグラウンドで動作するActivityServiceで構成される機能を実装する必要がありました(ServiceではなくIntentServiceを実装します)。

動作するはずのインターネット上のチュートリアルをいくつか試しましたが、それらはすべてLocalBroadcastManagerを使用しています。これは、Androidで推奨されています。

アプリケーション間でブロードキャストを送信する必要がない場合は、以下で説明するより一般的な機能の代わりに、このクラスをLocalBroadcastManagerとともに使用することを検討してください。

なぜそれが機能しないのかという問題を見つけるために、文字通り1日を失いました。それは、Context.sendBroadcast()を使用した場合にのみ機能します。 LocalBroadcastManagerメソッドの代わりにContext.registerReceiver()

現在、私のアプリは機能していますが、ベストプラクティスに反していると感じており、その理由はわかりません。なぜそれが起こっているのか考えはありますか?

編集:

この質問を書いた後、私はさらに問題を進めました。 LocalBroadcastManagerは、LocalBroadcastManager.getInstance(this).method()を呼び出す必要があるため、シングルトンを介して機能します。両方のインスタンスを(ActivityServiceに)記録しましたが、メモリアドレスが異なります。今、私は別の質問に行きました、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));
}
}
10
Teo Inke

LocalBroadcastManagerを使用したことはありませんが、 レシーバーをそこに登録する (つまり、lbm.registerReceiver(...)ではなくmycontext.registerReceiver(...))する必要があるようです。あなたはそれをしていますか?

今、私は別の質問に行き着きました、サービスはそれを呼び出したアクティビティと同じコンテキストを持つべきではありませんか?この記事から、サービスはメインスレッドで実行されるため、コンテキストは同じだと思います。

Contextクラスはスレッドとは関係ありません。実際、ServiceとActivityはどちらもContextの(間接的な)サブクラスであるため、独自のContextです。
そのため、「this」をコンテキストとして使用できます。

ただし、LocalBroadcastManager.getInstance()に送信するコンテキストに関係なく、 まったく同じLBMインスタンス を取得する必要があります。アクティビティとサービスを異なるプロセスで実行している場合を除いて、そうしない理由は考えられません。

9
Snild Dolkow

宣言:

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);
10
smb

サービスとアクティビティが異なるプロセスで実行されているかどうかを確認してください。LocalBroadcastManagerは異なるプロセスに適用できません(AndroidManifest.xmlファイルに表示されます)。

5
Michael