知识点整理
5.1 广播机制简介
Android中的广播主要分为两种类型:标准广播和有序广播。
标准广播
完全异步的在广播
在广播发出后,所有的广播接收器几乎在同一时刻接受到这条广播信息。
特点:广播效率高、没有任何先后顺序、无法被拦截
有序广播
同步执行的广播
广播发出后同一时刻,只会有一个BroadcastReceiver能够接收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传递。
特点:广播接收器有先后顺序,优先级高的广播接收器先收到广播消息,可以被优先级高的广播接收器拦截。
5.2 接受系统广播
Android 内置了很多系统级别的广播,我们可以在应用程序中通过监听这些广播来得到系统状态信息。
例如:
:开机广播
:电池电量发生变化广播
:时间或时区发生改变广播
广播接收器可以自由注册自己感兴趣的广播进行注册。注册的方式有两种:
● 代码中注册(也称为动态注册)
● AndroidManifest.xml中注册(也称为静态注册)
5.2.1 动态注册监听系统广播
动态注册系统广播步骤:
1.创建类继承BroadcastReceiver 重写onReceive()方法
2.通过 IntentFilter 类 注册或者取消注册广播
例如:动态注册广播监听时间变化
创建MyReceiver类继承BroadcastReceiver 重写onReceive()方法
在MainActivity里面通过IntentFilter 注册广播
MyReceiver 类
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if ("android.intent.action.TIME_TICK".equals(action)) {
Toast.makeText(context,"Timer",Toast.LENGTH_LONG).show();
}
}
}
MainActivity类
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private Button Time;
private Button unTime;
private IntentFilter intentFilter;
private MyReceiver myReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Time = findViewById(R.id.time);
Time.setOnClickListener(this);
unTime = findViewById(R.id.untime);
unTime.setOnClickListener(this);
intentFilter = new IntentFilter();
intentFilter.addAction("android.intent.action.TIME_TICK");
myReceiver = new MyReceiver();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.time:
registerReceiver(myReceiver,intentFilter);
break;
case R.id.untime:
unregisterReceiver(myReceiver);
break;
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="Reg Time">
</Button>
<Button
android:id="@+id/untime"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="unReg Time">
</Button>
</LinearLayout>
AndroidManifest.xml
<application
....
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
</receiver>
...
</application>
5.2.2 静态注册实现开机广播
静态广播可以在程序未启动的时候就能接收到广播。
步骤:
1.创建类继承BroadcastReceiver 重写onReceive()方法
2.在AndroidManifest.xml里面进行注册
隐式广播:是指那些没有具体发送给那个应用程序的广播,大多数系统广播属于隐式广播。但少数特殊的系统广播目前仍然允许使用静态方式来接受。
例如:静态注册接受开机广播,弹出Toast,
public class MyReceiver extends BroadcastReceiver {
private static final String TAG = "Tim";
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if ("android.intent.action.BOOT_COMPLETED".equals(action)) {
Toast.makeText(context,"Start",Toast.LENGTH_LONG).show();
Intent intent1 = new Intent(context,MainActivity.class);
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent1);
Log.d(TAG," ----------start----------");
}
}
注意:intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 加上才可以启动应用程序。
AndroidManifest.xml加上权限,action
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
5.3 自定义广播
广播主要分为标准广播和有序广播,下面分别来实践下具体实现。
隐式广播:是指那些没有具体发送给那个应用程序的广播,大多数系统广播属于隐式广播。但少数特殊的系统广播目前仍然允许使用静态方式来接受。
5.3.1 发送标准广播
发送隐式广播(action):接受方必须动态接受(action)。
发送定向广播(action,packageName):接受方可以静态接受。
例如:
发送隐式广播:
发送方:
Intent intent = new Intent();
intent.setAction("my_receiver");
sendBroadcast(intent); //发送隐式广播
接受方:AndroidMainfest.xml不用进行注册
private IntentFilter intentFilter;
private MyReceiver myReceiver;
intentFilter = new IntentFilter();
intentFilter.addAction("my_receiver");
myReceiver = new MyReceiver();
registerReceiver(myReceiver,intentFilter); //注册隐式广播
unregisterReceiver(myReceiver); //取消注册隐式广播
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if ("my_receiver".equals(action)) {
Toast.makeText(context,"my_receiver",Toast.LENGTH_LONG).show();
}else if ("my_receiver1".equals(action)) {
Toast.makeText(context,"<<<<<<<>>>>>",Toast.LENGTH_LONG).show();
}
}
}
发送定向广播:
发送方:设置action 和接受方的packagename
Intent intent = new Intent();
intent.setPackage(getPackageName());
intent.setAction("my_receiver1");
sendBroadcast(intent);
接受方:
AndroidManifest.xml
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="my_receiver1"/>
</intent-filter>
</receiver>
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if ("my_receiver".equals(action)) {
Toast.makeText(context,"my_receiver",Toast.LENGTH_LONG).show();
}
}
}
5.3.2 发送有序广播
发送有序广播的步骤跟上面发送标准广播的步骤一样,只是调用的方法不一样。
有序广播
发送方:
sendOrderedBroadcast(intent,null)方法发送有序广播
参数一:intent的对象
参数二:与权限相关的字符串,一般传入null就行
接受方:
接受方可以设置广播接受的优先级,也可以截断广播,使广播不在向下传递。
1.设置优先级:
android:priority=“1000” 优先级
这个属性只对activity 和 receivers 是有意义的。
priority 必须是整数,默认是0 , 范围是[-1000, 1000]
AndroidMainfest.xml
<receiver
android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="1000">
<action android:name="com.example.broadcasttest.MY_BROADCASTT"/>
</intent-filter>
</receiver>
2.在MyBroadcastReceiver类中可以设置广播,被截断
abortBroadcast();
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if ("order".equals(action)) {
Toast.makeText(context,"order",Toast.LENGTH_LONG).show();
abortBroadcast();
}
}
5.4 使用本地广播
为了解决广播安全性问题,Android引入了一套本地广播机制,使用这个机制发出的广播只能够在应用程序的内部进行传递,并且广播接收器也只能接受来自本应用程序发出的广播。
本地广播使用LocalBroadcastManager,来对广播进行管理,并提供了发送广播和注册广播接收器的方法。
本地广播不在AndroidMainfest.xml里面进行注册,在代码里面注册
因为静态注册主要是在程序为启动时接受,本地广播主要在本apk内部进行传递。
发送:
LocalBroadcastManager mLocalBroadcastManager;
mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
Intent intent = new Intent();
intent.setAction("Local");
intent.putExtra("send","hello local broadcast");
mLocalBroadcastManager.sendBroadcast(intent);
接受:
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("Local");
LocalRecv localRecv = new LocalRecv();
mLocalBroadcastManager.registerReceiver(localRecv,intentFilter);
class LocalRecv extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if ("Local".equals(action)) {
String string = intent.getStringExtra("send");
Toast.makeText(context,string,Toast.LENGTH_LONG).show();
}
}
}
本地广播的优势:
发送的广播不会离开自己的程序,所以数据不会泄露
其它程序无法将广播发送到我们程序的内部,所以不会有安全漏洞隐患
发送本地广播比发送系统全局广播更加高效
小项目:强制下线功能实现。