Broadcast Recieverとは?
- BroadcastReceiver(ブロードキャストレシーバー)とは、ブロードキャストしたインテントを受け取る仕組みのこと
- OSのAndroidシステム側でブロードキャストされるイベント(スクリーンのON/OFFなど)以外でも、自分で作成したアプリでも独自のインテントを生成してブロードキャストできる
intentとは?
- intentとは、アプリケーションの中の1つ1つの機能のこと。たとえばアプリケーション同士や、アプリケーションとウィジェット、アプリケーションとシステムを橋渡しする仕組みのこと
- BroadcastRecieverを使わずとも、intentだけでも利用が可能で、例えば電話をかけたりカメラを起動することもできる
- BroadcastRecieverでは、例えばアプリをインストールした際などに発生するintentを検知することができます。例えば...
- スクリーンのON/OFFを検知する
- 電池の状態を検知する
- アプリのインストールを検知する
- 振動を検知する 等
使ってみよう
アクティビティからサービスを起動 → サービスでレシーバーを登録 という流れでやってみました
MyReceiver.java
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() != null) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
Log.d("registerReceiver: ", "ON");
}
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
Log.d("registerReceiver: ", "OFF");
}
}
}
}
MyActivity.java
public class MyActivity extends Activity {
Button startButton;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startButton = (Button)findViewById(R.id.start_button);
startButton.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(new Intent(this(), MyService.class));
} else {
startService(new Intent(this(), MyService.class));
}
}
}
}
MyService.java
public class MyService extends Service {
private MyReceiver mReceiver;
private IntentFilter mIntentFilter;
@Override
public void onCreate() {
super.onCreate();
// Receiver登録を実行
registerScreenReceiver();
}
@Override
public void onDestroy() {
super.onDestroy();
// Receiverを解除
unregisterReceiver(mReceiver);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
startInForeground();
return START_STICKY;
}
// receiverを登録
private void registerScreenReceiver() {
mReceiver = new MyReceiver();
mIntentFilter = new IntentFilter();
mIntentFilter.addAction(Intent.ACTION_SCREEN_ON);
mIntentFilter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(mReceiver, mIntentFilter);
}
// サービスをアライブさせるために通知を生成
private void startInForeground() {
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(getResources().getString(R.string.app_name))
.setContentText("test notification")
.setTicker(getResources().getString(R.string.app_name))
.setContentIntent(pendingIntent);
Notification notification = builder.build();
if (Build.VERSION.SDK_INT >= 26) {
NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID
, NOTIFICATION_CHANNEL_NAME
, NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription(NOTIFICATION_CHANNEL_DESC);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
notificationManager.createNotificationChannel(channel);
}
}
startForeground(NOTIFICATION_ID, notification);
}
}
解説
- MyReceiverのonReceiveにて、intent.getAction()が登録したintentFilterのアクションと合致したらログを出す様に処理
- MyActivityにボタンを設置。ボタンを押すとサービスを起動するという単純な構造
- MyService内でReceiverの登録を行なっている。startInForegroundはForegroundService用でとりあえず実装(あまり気にしなくていいです)
- サービスが起動している間に、スクリーンをOn/Offにしたらその度にログが出る
備考
- 最ライフログやヘルスケアのアプリをよく見るので、どんな風にデータを集計しているのか気になったところ、intentを使っているパターンが多い様に感じたので調査してみた
- 今回紹介した以外にも、intentはものすごく沢山あるので、アプリによっては有用なものもある...かもしれない