本文主要是介绍四大组件:BroadCastReceiver广播,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
简介
BroadCastReceiver:广播接收者,可以接受手机电量变化、短信、电话、app的安装与卸载等都可以接受到这些广播(这些事系统发出的广播),当然我们还可以自定义广播,这就我们自己写发送广播的代码。
分类:
有序广播和无序广播
有序广播:是可以拦截的,可以设置优先级(数值越大,越先接收广播)
无序广播:不可以被拦截,没有优先级。
有关方法:
sendBroadcast(intent);
发送广播
sendOrderedBroadcast(Intent intent, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)
发送有序广播
abortBroadcast();
取消广播,只有有序广播才可以调用该方法,无序广播调用会报错BroadcastReceiver trying to return result during a non-ordered broadcast
如果是静态广播,那么不需要在onReceive(...)
中判断action
,如果是动态注册,需要判断action
静态广播接收者BroadCastReceiver
注册广播接收者有2种方法,代码中注册(动态注册)和AndroidManifest.xml中注册(静态注册),下面的案例没说明动态注册的都是静态注册。
系统发出的广播,我们只做接收。常见的如下:
- 打电话 Receiver
- SD卡状态 Receiver
- 来短信 Receiver
- app的安装与卸载 Receiver
- 开机启动 Receiver
打电话 Receiver
打电话,若是长途,则广播中给手机号添加ip:123456
@Overridepublic void onReceive(Context context, Intent intent) {//获取保存的ipSharedPreferences sp = context.getSharedPreferences("config", context.MODE_PRIVATE);String ip = sp.getString("ip", "17951");//获取拨进来的号码String number = getResultData();//以0开头,则是长途,则在号码前加ipif (number.startsWith("0")) {setResultData(ip + number);}}
<!--在androidManifest中注册的广播是持久广播,app退出仍然有效。 -->
<!-- 声明receiver 添加action -->
<receiver android:name="com.cqc.ipnumber.OutGoingCallBroadCastReceiver" ><intent-filter><action android:name="android.intent.action.NEW_OUTGOING_CALL" /></intent-filter>
</receiver>
<!-- 添加外拨电话权限 -->
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
SD卡状态 Receiver
根据action判断sd卡是挂载还是卸载。注意卸载sd卡的action是UNMOUNTED,不是REMOVE
@Override
public void onReceive(Context context, Intent intent) {String action = intent.getAction();if (Intent.ACTION_MEDIA_MOUNTED.equals(action)) {// 挂载Log.d(TAG, "sd卡挂载");} else if (Intent.ACTION_MEDIA_UNMOUNTED.equals(action)) {Log.d(TAG, "sd卡卸载");}
}
<!-- 声明receiver --><receiver android:name="com.cqc.sdstatelistener.SdStateReceiver" ><intent-filter><action android:name="android.intent.action.MEDIA_MOUNTED" /><action android:name="android.intent.action.MEDIA_UNMOUNTED" /><!-- sd卡状态比较特殊,除了设置action,还需要data --><data android:scheme="file" /></intent-filter></receiver>
来短信 Receiver
广播接收者:
@Overridepublic void onReceive(Context context, Intent intent) {//转换成数组Object[] objects = (Object[]) intent.getExtras().get("pdus");//遍历数组,湖区sms对象for (Object object : objects) {SmsMessage sms = SmsMessage.createFromPdu((byte[]) object);//获取短信内容和发布者手机号String content = sms.getMessageBody();String originNumber= sms.getOriginatingAddress();Log.d(TAG, "content="+content+"____originNumber"+originNumber);}}
<receiver android:name="com.cac.smsreceiver.SmsReceiver" ><intent-filter><!-- 处于安全性考虑,android没有提示短信监听的action,但仍然可以使用 --><action android:name="android.provider.Telephony.SMS_RECEIVED" /></intent-filter></receiver>
<!-- 短信监听的权限 --><uses-permission android:name="android.permission.RECEIVE_SMS" />
把androidManifest.xml的启动的actiivty的intent_filter注释掉,就没有界面了,但是海驿拿到短信, api4.0后,注释掉intent_filter,就拿不到短信了。
app的安装与卸载 Receiver
@Override
public void onReceive(Context context, Intent intent) {String action = intent.getAction();if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {// 挂载Log.d(TAG, "安装");} else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {Log.d(TAG, "卸载");}
}
<receiver android:name="com.cqc.installreceiver.InstallReceiver"><intent-filter ><action android:name="android.intent.action.PACKAGE_ADDED"/><action android:name="android.intent.action.PACKAGE_REMOVED"/><!-- 安装卸载还需要添加data --><data android:scheme="package"/></intent-filter>
</receiver>
开机启动 Receiver
@Overridepublic void onReceive(Context context, Intent intent) {Log.d(TAG, "intent2");Intent intent2 = new Intent(context, MainActivity.class);intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);context.startActivity(intent2);String action = intent.getAction();if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {Log.d(TAG, "Intent.ACTION_BOOT_COMPLETED");}}
<receiver android:name="com.cqc.bootreceiver.BootReceiver" ><intent-filter><action android:name="android.intent.action.BOOT_COMPLETED"/></intent-filter></receiver>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
自定义广播接收者
自定义广播需要设置action,可以获取intent中的数据。
基本使用
自定义广播,在Button的点击监听中发送广播,在receiver中根据action,从intent中取值。
发送广播:
Intent intent = new Intent();
intent.setAction("MyReceiver");
intent.putExtra("name", "奥巴马");
sendBroadcast(intent);
MyReceiver :
public class MyReceiver extends BroadcastReceiver {private static final String TAG = "MyReceiver";@Overridepublic void onReceive(Context context, Intent intent) {Log.d(TAG, "MyReceiver--name="+intent.getStringExtra("name"));//取消广播abortBroadcast();}
}
在AndroidManifest.xml中配置receiver:
<receiver android:name="com.cqc.custombroadcast.MyReceiver"><intent-filter ><action android:name="MyReceiver"/></intent-filter>
</receiver>
自定义有序广播
demo:国家发布政令后,先到省政府,再到市政府,再到县政府…,这里只设置这3级,有先后顺序。点击Button发送广播,一次向下传递。
点击Button发送广播:
btn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {//发送自定义广播Intent intent = new Intent();intent.setAction("customOrderReceiver");intent.putExtra("commond", "全国各级部门应该加强安全防范措施");
// sendBroadcast(intent);//这是无序广播/*** 这是有序广播,参数分别是:* Intent intent:intent对象* String receiverPermission: 接收者权限* BroadcastReceiver resultReceiver:最后一个接收者,不为null,则最后的receiver会接收2次。* Handler scheduler, null* int initialCode 状态码* String initialData, 传递的数据,intent.putExtra(...)* Bundle initialExtras:null*/sendOrderedBroadcast(intent, null, new CountyReceiver(), null, 1, null, null);}});
省级先接到通知
public class ProviceReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Log.d("tag", "省级部门接到中央命令+content="+intent.getStringExtra("commond"));}
}
然后是市级接到通知
public class CityReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Log.d("tag", "市级部门接到中央命令+content="+intent.getStringExtra("commond"));}
}
最后是县级接到通知
public class CountyReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Log.d("tag", "县级部门接到中央命令+content="+intent.getStringExtra("commond"));}
}
注意:
1 上面的先后级别是根据广播接收者的priority(优先级)决定的。是在配置receiver时设置的。
<receiver android:name="com.cqc.customorderreceiver.ProviceReceiver" ><intent-filter android:priority="3" ><action android:name="customOrderReceiver" /></intent-filter></receiver><receiver android:name="com.cqc.customorderreceiver.CityReceiver" ><intent-filter android:priority="2" ><action android:name="customOrderReceiver" /></intent-filter></receiver><receiver android:name="com.cqc.customorderreceiver.CountyReceiver" ><intent-filter android:priority="1" ><action android:name="customOrderReceiver" /></intent-filter></receiver>
2 调用方法sendOrderedBroadcast(…)发送有序广播的时候若指定了最后接收者( resultReceiver),那么 resultReceiver会收到2次广播。
动态注册广播接收者
与静态相比区别是:
代码上:
1 不需要再AndroidManifest.xml中注册
2 调用registerReceiver(receiver, filter)注册接收者
理解上:
静态注册的广播接收者:当app关闭的时候也是有效的,也可以接受到服务器发出的广播。
动态注册的广播接收者:当app关闭的时候,不会接受到广播。因为我们是在onCreate()中注册的,而不是在AndroidManifest.xml中注册。
下面的是锁屏和开锁的的广播接收者,当我们打开这个app的时候,按住手机电源键锁屏和接收会打印出log,但是当我们关闭app的时候,再按住手机电源键锁屏和接收则不会打印出log
Demo1:
public class MainActivity extends Activity {private MyBroadcastReceiver receiver;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);receiver = new MyBroadcastReceiver();IntentFilter filter = new IntentFilter();filter.addAction("android.intent.action.SCREEN_ON");//添加actionfilter.addAction("android.intent.action.SCREEN_OFF");registerReceiver(receiver, filter);//注册广播接收者}@Overrideprotected void onDestroy() {unregisterReceiver(receiver);//取消广播接收者super.onDestroy();}//创建广播接收者类public class MyBroadcastReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if ("android.intent.action.SCREEN_OFF".equals(action)) {System.out.println("锁屏");} else if("android.intent.action.SCREEN_ON".equals(action)){System.out.println("解锁");} }}
}
代码:https://git.oschina.net/beifang2008/DongTaiBroadCastReceiver
Demo2:
public class MainActivity extends Activity {private MyBroadcastReceiver receiver;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button btn = (Button) findViewById(R.id.btn);btn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent("auto_finish");sendBroadcast(intent); }});receiver = new MyBroadcastReceiver();IntentFilter filter = new IntentFilter();filter.addAction("finish");// 添加actionregisterReceiver(receiver, filter);// 注册广播接收者 }@Overrideprotected void onDestroy() {unregisterReceiver(receiver);// 取消广播接收者super.onDestroy();}// 创建广播接收者类public class MyBroadcastReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if ("finish".equals(action)) {finish();}}}
}
sendBroadcast(intent)与sendStickyBroadcast(intent)的区别?
区别主要是在动态注册广播中才有,在静态注册中是一样的。
sendBroadcast(intent):当发送广播在注册广播前时,接收者是接收不到广播的。
sendStickyBroadcast(intent):当发送广播在注册广播前时,接收者是可以接收到广播的。sendStickyBroadcast发出的最后一个Intent会被保留,下次当Recevier处于活跃的 时候,又会接受到它。
Demo:https://git.oschina.net/beifang2008/DongTaiBroadCastReceiver2
LocalBroadcastManager
Android高效安全的本地广播LocalBroadcast完全解析
LocalBroadcastManager
只可以动态注册广播。
获取LocalBroadcastManager
对象,单利模式
LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(this);
设置InentFilter,intentFilter和intent都必须设置action
IntentFilter filter = new IntentFilter();
filter.addAction(localAction);
注册
broadcastManager.registerReceiver(receiver, filter);
发送Broadcast
Intent intent = new Intent(localAction);
broadcastManager.sendBroadcast(intent);
取消注册
broadcastManager.unregisterReceiver(receiver);
android.support.v4.content.LocalBroadcastManager工具类,可以实现在自己的进程内进行局部广播发送与注册,使用它比直接通过sendBroadcast(Intent)发送系统全局广播有以下几个好处
- 因广播数据在本应用范围内传播,你不用担心隐私数据泄露的问题。
- 不用担心别的应用伪造广播,造成安全隐患。
- 相比在系统内发送全局广播,它更高效。
这篇关于四大组件:BroadCastReceiver广播的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!