广播俩种注册方法
广播的方式一般有两种,在代码中注册和在 AndroidManifest.xml中注册,其中前者也被称为动态注册,后者也被称为静态注册。
动态注册:需要使用广播接收者时,执行注册的代码,不需要时,执行解除注册的代码
public class MainActivity extends Activity { private IntentFilter intentFilter; private NetworkChangeReceiver networkChangeReceiver; @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(); unregisterReceiver(networkChangeReceiver); } class NetworkChangeReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context, "network changes",Toast.LENGTH_SHORT).show(); } }}
静态注册:下面全是
可以使用清单文件注册
案例1:IP拨号器
原理:接收拨打电话的广播,修改广播内携带的电话号码
public class CallReceiver extends BroadcastReceiver { //当广播接收者接收到广播时,此方法会调用 @Override public void onReceive(Context context, Intent intent) { //拿到用户拨打的号码 String number = getResultData(); //修改广播内的号码 setResultData("17951" + number); }}
系统收到短信时会产生一条广播,广播中包含了短信的号码和内容
//在Activity中重写此方法,按返回键退不出去,但是可以菜单键退出,所以还需要开机自启 @Override public void onBackPressed() {// super.onBackPressed(); }
原理:应用在安装卸载更新时,系统会发送广播,广播里会携带应用的包名
<receiver android:name="com.itheima.app.AppReceiver"> <intent-filter > <action android:name="android.intent.action.PACKAGE_ADDED"/> <action android:name="android.intent.action.PACKAGE_REPLACED"/> <action android:name="android.intent.action.PACKAGE_REMOVED"/> <data android:scheme="package"/> </intent-filter> </receiver>
自定义广播
发送自定义广播
//发送自定义广播 Intent intent = new Intent(); //广播中的action也是自定义的 intent.setAction("com.itheima.zdy"); sendBroadcast(intent); 接收自定义广播 //在清单文件注册,匹配自定义的广播,这个广播接收者就能接收到自定义的广播<receiver android:name="com.itheima.receivezdy.ZDYReceiver"> <intent-filter > <action android:name="com.itheima.zdy"/> </intent-filter>
有序广播
发送有序广播:
第一个参数仍然是Intent,第二个参数是一个与权限相关的字符串,这里传入 null就行了
2. sendOrderedBroadcast(intent, null, new MyReceiver(), null, 0, "每人发100斤大米", null);
这里的第三个参数是最终接收者resultReceiver:不需要在清单文件中配置,这个广播接收者只接受该条有序广播,并且是最后一个收到该广播,并且一定可以收到该广播
class MyReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { String text = getResultData(); System.out.println("收到文件:" + text); } }
//接收到自己发送出去的广播,最后接收(即使截断也能收到),因为在其他广播接收者可以修改数据public class ShengZF extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub String text = getResultData(); setResultData("每人发80斤大米"); }}
用广播实现强制下线功能
实现强制下线功能
思路:需要在界面上弹出一个对话框,让用户无法进行任何其他操作,必须要点击对话框中的确定按钮,然后回到登录界面即可。
可是这样就存在着一个问题,因为被通知需要强制下线时可能正处于任何一个界面,难道需要在每个界面上都编写一个弹出对话框的逻辑?
不是的,我们可以借助广播知识,来实现这一功能。
1.强制下线功能需要先关闭掉所有的活动,然后回到登录界面。先创建一个ActivityCollector类用于管理所有的活动
2.创建BaseActivity类作为所有活动的父类
3.创建一个登录界面的布局login.xml
4.编写登录界面的活动,新建LoginActivity继承自BaseActivity
5.登录成功后进入程序主界面,这里不需要在主界面里提供什么功能,只需要加入强制下线功能就可以了,修改activity_main.xml中的代码,就是一个按钮
6.修改MainActivity中的代码按钮的点击事件里面发送了一条广播
7.创建一个广播接收器了,新建ForceOfflineReceiver
8.对AndroidManifest.xml文件进行配置:声明权限、对LoginActivity进行注册,并把它设置为主活动,最后再对 ForceOfflineReceiver 进行注册,
并指定它接收 com.example.broadcastbestpractice.FORCE_OFFLINE这条广播。
这是第6步//在按钮的点击事件里面发送了一条广播,广播的值为com.example.broadcastbestpractice.FORCE_OFFLINE,这条广播就是用于通知程序强制用户下线的。//也就是说强制用户下线的逻辑并不是写在MainActivity里的,而是应该写在接收这条广播的广播接收器里面,这样强制下线的功能就不会依附于任何的界面,不管是在程序的任何地方,//只需要发出这样一条广播,就可以完成强制下线的操作了。public class MainActivity extends Activity{ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button forceOffline = (Button) findViewById(R.id.force_offline); forceOffline.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent("com.example.broadcastbestpractice.FORCE_OFFLINE "); sendBroadcast(intent); } }); }
//第7步public class ForceOfflineReceiver extends BroadcastReceiver { @Override public void onReceive(final Context context, Intent intent) { AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context); dialogBuilder.setTitle("Warning"); dialogBuilder.setMessage("You are forced to be offline. Please tryto login again."); dialogBuilder.setCancelable(false); dialogBuilder.setPositiveButton("OK",new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ActivityCollector.finishAll(); // 销毁所有活动 Intent intent = new Intent(context,LoginActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); // 重新启动LoginActivity } }); AlertDialog alertDialog = dialogBuilder.create(); // 需要设置AlertDialog的类型,保证在广播接收器中可以正常弹出 alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); alertDialog.show(); }}
onReceive()方法里加入了较多的代码,首先是使用AlertDialog.Builder来构建一个对话框,注意这里一定要调用setCancelable()方法将对话框设为不可取消,
否则用户按一下Back键就可以关闭对话框继续使用程序了。然后使用setPositiveButton()方法来给对话框注册确定按钮,当用户点击了确定按钮时,
就调用ActivityCollector的finishAll()方法来销毁掉所有活动,并重新启动LoginActivity这个活动。另外,由于在广播接收器里启动活动的,
因此一定要给Intent加入 FLAG_ACTIVITY_NEW_TASK这个标志。最后,还需要把对话框的类型设为TYPE_SYSTEM_ALERT,不然它将无法在广播接收器里弹出。
对AndroidManifest.xml文件进行配置,这里有几点内容需要注意,
1.由于在ForceOfflineReceiver里弹出了一个系统级别的对话框,因此必须要声明 android.permission.SYSTEM_ALERT_WINDOW权限。
2.对LoginActivity进行注册,并把它设置为主活动。
3.对 ForceOfflineReceiver 进行注册,并指定它接收 com.example.broadcastbestpractice.FORCE_OFFLINE这条广播。