广播机制
为了方便进行系统级别的消息通知,Android
引用一套广播消息机制。Android
中的每个应用程序可以对自己感兴趣的广播进行注册。
- 标志广播:是一种完全异步执行的广播,广播发出时,所有广播接收器几乎在同一时刻接收到这条广播信息。
- 有序广播:是一种同步执行的广播,在广播发出时,同一时刻只会有一个广播接收器能够收到这条广播信息,当这个广播接收器逻辑执行完毕后,广播才会继续传递。此时的广播具有优先级,优先级高的广播接收器可以先收到广播信息,并且前面的广播接收器还可以截断正在传递的广播。
接收系统广播
- 动态注册:在代码中注册
- 静态注册:
AndroidManifest.xml
注册
动态注册
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); intentFilter = new IntentFilter(); intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE"); networkChangeReceiver = new NetworkChangeReceiver(); registerReceiver(networkChangeReceiver,intentFilter);
}
@Override protected void onDestroy() { super.onDestroy(); } class NetworkChangeReceiver extends BroadcastReceiver{
@Override public void onReceive(Context context, Intent intent) { Log.d("onReceive", "onReceive: 11111"); Toast.makeText(context,"network changes",Toast.LENGTH_SHORT).show(); } }
|
IntentFilter
:意图拦截器,用于拦截符合action
和category
的意图,这里需要接收网络修改的广播,因此行为为"android.net.conn.CONNECTIVITY_CHANGE"
NetworkChangeReceiver
类是继承了广播类并重写了接收到广播的方法
registerReceiver()
方法用于注册广播接收器
- 参数一:需要注册的广播接收器
- 参数二:需要接收广播的行为
unregisterReceiver()
方法用于取消注册
1 2 3 4 5 6 7 8 9 10 11 12 13
| public void onReceive(Context context, Intent intent) { ConnectivityManager connectivityManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); if(networkInfo != null && networkInfo.isAvailable()) { Toast.makeText(context,"network is available", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(context,"network is unavailable",Toast.LENGTH_SHORT).show(); }
}
|
getSystemService()
方法用于获取系统服务类
ConnectivityManager
类是专门用于管理网络连接
getActiveNetworkInfo()
方法用于获取网络状态
静态注册
动态注册更灵活但是必须程序运行时才能接收广播,但是静态注册可以在程序未启动的时候接收广播。
1 2 3 4
| <receiver android:name=".BootCompleteReceiver" android:enabled="true" android:exported="true"></receiver>
|
android:name
用于指定注册的广播接收器
android:enabled
表示是否启用该广播接收器
android:exported
表示是否允许这个广播接收器接收本程序以外的广播
1 2 3 4 5 6 7 8 9 10
| <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> ... <receiver android:name=".BootCompleteReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver>
|
由于Android
系统启动时会发出值为android.intent.action.BOOT_COMPLETED
的广播,因此添加相应的action
。
发送自定义广播
发送标准广播
首先自定义一个广播接收器,<intent-filter>
标签内需要拦截的行为为"com.example.mybroadcastreceiver.MY_BROADCAST"
,接着发送广播的行为也为这个,即可发送和接收广播。
1 2
| Intent intent = new Intent("com.example.mybroadcastreceiver.MY_BROADCAST"); sendBroadcast(intent);
|
发送有序广播
广播可以跨进程通信。
sendOrderedBroadcast(intent,null)
方法可以发送有序广播
- 参数一:
Intent
对象
- 参数二:与权限相关的字符串
android:prority
可以自定义广播的优先级
abortBroadcast()
方法可以拦截广播
本地广播
- 本地广播是在程序内部的广播,防止接收垃圾广播,或者广播中携带安全数据被恶意劫持。
- 本地广播无法静止注册
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
| public class MainActivity extends AppCompatActivity { private IntentFilter intentFilter; private LocalReceiver localReceiver; private LocalBroadcastManager localBroadcastManager;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); localBroadcastManager = LocalBroadcastManager.getInstance(this); Button button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent("com.example.mybroadcastreceiver.MY_BROADCAST"); localBroadcastManager.sendBroadcast(intent); } }); }
@Override protected void onDestroy() { super.onDestroy(); localBroadcastManager.unregisterReceiver(localReceiver); }
class LocalReceiver extends BroadcastReceiver{
@Override public void onReceive(Context context, Intent intent) { Toast.makeText(context,"received local broadcast",Toast.LENGTH_SHORT).show(); } } }
|
本地广播使用动态注册。
LocalBroadcastManager
:用于在同一个应用内的不同组件间发送Broadcast
强制下线功能
ActivityConllector
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class ActivityCollector { public static List<Activity>activities = new ArrayList<>(); public static void addActivity(Activity activity){ activities.add(activity); } public static void removeActivity(Activity activity){ activities.remove(activity); } public static void finishAll(){ for(Activity activity:activities){ if(!activity.isFinishing()){ activity.finish(); } } } }
|
ForceOfflineReceiver类
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
| ..... @Override protected void onResume() { super.onResume(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("com.example.broadcastbestpractice.FORCE_OFFLINE"); receiver = new ForceOfflineReceiver(); registerReceiver(receiver,intentFilter); }
@Override protected void onPause() { super.onPause(); if(receiver!=null){ unregisterReceiver(receiver); receiver = null; } } ..... class ForceOfflineReceiver extends BroadcastReceiver{
@Override public void onReceive(final Context context, Intent intent) { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle("Warning"); builder.setMessage("You are forced to be offline. Please try to login agin"); builder.setCancelable(false); builder.setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ActivityCollector.finishAll(); Intent intent = new Intent(context,LoginActivity.class); context.startActivity(intent); } }); builder.show(); }
|