LocalBroadcastManager
※ローカルのネタ帳からのほぼコピペ
一言で言えばアプリ内ローカルでのみ利用可能なブロードキャスト的な感じかなと。一般的には
<receiver android:name=".SampleBroadcastReceiver">
<intent-filter>
<action android:name="sample.test.broadcast" />
</intent-filter>
</receiver>
的な感じでグローバルなBroadcastReceiverを設定するんだと思うけど、これでやると
adb shell am broadcast -a sample.test.broadcast
等でも反応できちゃう。特に必要性が無い場合とかであったりだとかの場合とかだとLocalBroadcastManagerを使ってアプリ内のコンテキストのみでブロードキャスト可能にしたり出来るとか。説明ムズイ
とりまぁやってみる。要件的には
- Activity(LocalBroadcastManager#registerReceiver)
- Service(LocalBroadcastManager#sendBroadcast)
- BroadcastReceiver(Handler#sendMessage)
- Activity(Handler#handleMessage)
っていう流れだけ。
SampleService.java
package sample.test;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
public class SampleService extends Service {
private LocalBroadcastManager mBroadcast;
private Timer timer = null;
@Override
public void onCreate() {
super.onCreate();
mBroadcast = LocalBroadcastManager.getInstance(this);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
sendBroadcast("--- START ---");
timer = new Timer();
timer.schedule(
new TimerTask() {
@Override
public void run() {
sendBroadcast(new Date().toString());
}
},
0,
10000
);
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
sendBroadcast("--- STOP ---");
super.onDestroy();
timer.cancel();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
private void sendBroadcast(String message) {
Intent intent = new Intent(SampleBroadcastReceiver.ACTION);
intent.putExtra("message", message);
mBroadcast.sendBroadcast(intent);
}
}
SampleBroadcastReceiver.java
package sample.test;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.text.TextUtils;
public class SampleBroadcastReceiver extends BroadcastReceiver {
public static final String ACTION = "sample.test.broadcast";
private Handler mHandler;
public SampleBroadcastReceiver(Handler handler) {
this.mHandler = handler;
}
@Override
public void onReceive(Context context, Intent intent) {
if (mHandler == null) {
return;
}
if (intent.hasExtra("message")) {
String message = intent.getStringExtra("message");
if (!TextUtils.isEmpty(message)) {
mHandler.sendMessage(
mHandler.obtainMessage(0, message)
);
}
}
}
}
MainActivity.java
package sample.test;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getName();
private BroadcastReceiver mBroadcast;
private static EditText mText;
private static final Handler sHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
String str = (String)msg.obj;
if (TextUtils.isEmpty(str)) {
return;
}
mText.append(str + "rn");
}
};
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.main);
mText = (EditText)findViewById(R.id.logs);
mBroadcast = new SampleBroadcastReceiver(sHandler);
((Button)findViewById(R.id.start)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
startService(new Intent(MainActivity.this, SampleService.class));
}
});
((Button)findViewById(R.id.stop)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
stopService(new Intent(MainActivity.this, SampleService.class));
}
});
}
@Override
public void onResume() {
Log.v(TAG, "onResume");
super.onResume();
LocalBroadcastManager.getInstance(this).registerReceiver(
mBroadcast,
new IntentFilter(SampleBroadcastReceiver.ACTION)
);
}
@Override
public void onPause() {
Log.v(TAG, "onPause");
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcast);
stopService(new Intent(this, SampleService.class));
}
}
終わり。実行してServiceを起動してほっとくと
っつー感じに。LocalBroadcastManagerでregisterReceiverをしたBroadcastReceiverは
adb shell am broadcast -a sample.test.broadcast
的なので要求を出しても反応しない。
<receiver android:name=".SampleBroadcastReceiver">
<intent-filter>
<action android:name="sample.test.broadcast" />
</intent-filter>
</receiver>
的な事をすれば上記コマンドで反応させる事は出来る。という事で意図しないブロードキャストを許容しないのであればLocalBroadcastManagerを使ったブロードキャストな設計を組み込むべきというオチで
ちなみに以下を参考にした方が良いという。今までなんだったんだと..orz
参考: http://stackoverflow.com/questions/8802157/how-to-use-localbroadcastmanager/8875292