Broadcast は幅広く投げる、いわゆる放送することです。相手を厳密に限定している訳ではないのですが、LocalBroadcast は放送する範囲を自分のプロセスに限定できます。
API 29
LocalBroadcast
Localbroadcastmanager
LiveData の概要 | Android デベロッパー
しばらくは残しておきますがいずれこの記事も削除する予定です。
- 自アプリからデータが出て行かない
- 他のアプリケーションからBroadcastIntentを使ってハッキングされにくい
- Broadcast はグローバルにデータをシステムに投げるより効率的
逆に考えると、LocalではないBroadcastは、受信機があれば受信できてしまう
ということでしょう
例として、AlarmManager と Service を使って10秒毎にカウントするテストアプリを作ってみます
Service からBroadcastしてActivityでBoradcastReceiverで時間を受け取ります
繰り返しのアラームは AlarmManager で setWindow() を使った
テストアプリを元にしています
LocalBroadcast の設定は
- LocalBroadcastManager.getInstance(this).registerReceiver() の設定
- LocalBroadcastManager.getInstance(this).sendBroadcast() にて発信設定
- BroadcastReceiver クラスを受信用にセット
まとめるとこうなります。
build.gradle(Modular:app)
1 2 3 4 5 6 |
... dependencies { ... implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0' } |
AndroidXから必要になりましたがサポートはそこで終わりのようです。
androidx.localbroadcastmanager は、バージョン 1.1.0-alpha01 でサポートを終了する予定
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
package your.package.name; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); IntentFilter messageFilter = new IntentFilter("AlarmEvent"); // Broadcast を受け取る BroadcastReceiver を設定 DataReceiver dataReceiver = new DataReceiver(); // LocalBroadcast の設定 LocalBroadcastManager.getInstance(this) .registerReceiver(dataReceiver, messageFilter); // 初期の画面表示 setScreen("Alarm Start"); } private void setScreen(String str){ TextView textView = findViewById(R.id.text); // Broadcast で受け取った時刻を表示する textView.setText(str); // Alarm の開始 Button buttonStart = findViewById(R.id.button_start); buttonStart.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // Serviceを呼び出す Intent intent = new Intent(getApplication(), AlarmService.class); // Alarm の停止を解除 intent.putExtra("StopAlarm", false); startService(intent); } }); // Alarm を停止する Button buttonStop = findViewById(R.id.button_stop); buttonStop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(getApplication(), AlarmService.class); intent.putExtra("StopAlarm", true); startService(intent); } }); Toast toast = Toast.makeText(this, "Recieved Message", Toast.LENGTH_SHORT); toast.show(); } // Broadcast を受け取る BroadcastReceiver public class DataReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Log.d("DataReceiver", "onReceive"); // Broadcast されたメッセージを取り出す String message = intent.getStringExtra("Message"); // スクリーンにメッセージを表示 setScreen(message); } } } |
AlarmService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
package your.package.name; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import android.app.AlarmManager; import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; import android.os.IBinder; import android.util.Log; import java.util.Calendar; import java.util.Locale; public class AlarmService extends Service { // 繰り返し間隔、1分 private long repeatPeriod = 1000*10; // setWindow()でのwindow幅、4秒 private long windowLengthMillis = 1000*4; private Context context; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); Log.d("AlarmService", "start"); context = getApplicationContext(); } // Alarm によって呼び出される @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d("AlarmService", "received"); Boolean stopFlag = intent.getBooleanExtra("StopAlarm", false); Log.d("stopFlag", ""+stopFlag); // Alarm が解除されない限り継続 if(!stopFlag){ setNextAlarmService(); // 現在時刻を取り出す Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); int hour = calendar.get(Calendar.HOUR_OF_DAY); int minute = calendar.get(Calendar.MINUTE); int second = calendar.get(Calendar.SECOND); String time = String.format( Locale.US,"%1$02d:%2$02d:%3$02d", hour, minute, second); // Local Broadcast で発信する Intent messageIntent = new Intent("AlarmEvent"); messageIntent.putExtra("Message", time); LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent); } else{ stopAlarmService(); } return super.onStartCommand(intent, flags, startId); } // 次のアラームの設定 private void setNextAlarmService(){ Intent intent = new Intent(context, AlarmService.class); long startMillis = System.currentTimeMillis() + repeatPeriod; PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0); AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); if(alarmManager != null){ // SDK 19 以下ではsetを使う if(android.os.Build.VERSION.SDK_INT < 19) { alarmManager.set(AlarmManager.RTC_WAKEUP, startMillis, pendingIntent); } else{ alarmManager.setWindow(AlarmManager.RTC_WAKEUP, startMillis, windowLengthMillis, pendingIntent); } } } private void stopAlarmService(){ Intent indent = new Intent(context, AlarmService.class); PendingIntent pendingIntent = PendingIntent.getService(context, 0, indent, 0); // アラームを解除する AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); if(alarmManager != null){ alarmManager.cancel(pendingIntent); } } } |
AndroidManifest.xml
1 2 3 4 5 6 7 8 9 10 |
... <application <activity </activity> <service android:name=".AlarmService" /> </application> </manifest> |
レイアウトです
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center" android:background="#dfe" tools:context=".MainActivity"> <TextView android:id="@+id/text" android:text="@string/text" android:layout_margin="20dp" android:textColor="#000000" android:textSize="30sp" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Button android:id="@+id/button_start" android:text="@string/start" android:layout_margin="10dp" android:layout_width="200dp" android:layout_height="wrap_content" /> <Button android:id="@+id/button_stop" android:text="@string/stop" android:layout_margin="10dp" android:layout_width="200dp" android:layout_height="wrap_content" /> </LinearLayout> |
strings.xml
1 2 3 4 5 6 |
<resources> <string name="app_name">YourAppName</string> <string name="text">Alarm Test</string> <string name="start">Alarm Start</string> <string name="stop">Alarm Syop</string> </resources> |
Reference:
http://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html