Ŀ¼
但是只有广播接收者可以使用java代码的方法来动态注册。
BroadcastReceiver是用于接收广播的组件用于组件与组件之间进行通信,可以跨应用程序传递.如操作系统电池电量低会发送一个广播,这样我们的程序里面可以去监听这个广播,可以关 闭程序里面比较耗电的功能,提示用户注意保存进度什么的,还如其它安装新应用等,还有普通应 用程序,例如启动特定线程,文件下载完毕等。
广播的发送的一般应用场合:发送频率低的情况可以使用,数据量小的情况可以使用。
在onReceive方法内,我们可以获取随广播而来的Intent中的数据,这非常重要,就像无线电一样,包含很多有用的信息。 在创建完我们的BroadcastReceiver之后,还不能够使它进入工作状态,我们需要为它注册一个指定的广播地址。没有注册广播地址的BroadcastReceiver就像一个缺少选台按钮的收音机,虽然功能俱备,但也无法收到电台的信号。所以创建类后就要对BroadcastReceiver进行注册。
public class MyBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //对接收到的广播进行处理,intent里面包含数据 } }
- 1
- 2
- 3
- 4
- 5
- 6
静态注册是在AndroidManifest.xml文件中配置的
<receiver android:name="com.hua.bcreceiver.MyBroadcastReceiver" > <intent-filter> <action android:name="android.intent.action.MY_BROADCAST" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver>
- 1
- 2
- 3
- 4
- 5
- 6
所以,记得在 特定的地方执行解除注册操作。
MyBroadcastReceiver mbcr = new MyBroadcastReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(MyBroadcastReceiver.MY_BC_FIRST); registerReceiver(mbcr, filter);// 注册 (2)解除注册代码,一般在页面销毁时操作 @Override protected void onDestroy() { unregisterReceiver(mbcr); mbcr = null; super.onDestroy(); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
动作意图action,那么,就可以接收到系统发过来的广播信息,比如手机接收到短信,手机底层是会发送一条广播,查看手机系统内是否有符合条件的广播接收者,如果有就会向它发送信息。。。
静态注册的广播的程序运行一次后,以后能一直保持广播接收的状态,只要有对应的广播就能接收它的广播信息。而动态注册的广播需要程序在运行中才能接收广播。
在静态代码块中定义:
<intent-filter android:priority="999">
- 1
使用动态java代码设置:
filter.setPriority(999);
那么priority的最大值是多少呢?
所有我们要知道优先级1000并不是最高的优先级,不信的话你可以试试看效果。
普通广播对于多个接收者来说是完全异步的,通常每个接收者都无需等待即可以接收到广播,接收者相互之间不会有影响。对于这种广播,接收者无法终止广播,即无法阻止其他接收者的 接收动作。
主要代码:
Intent intent = new Intent(“myBroadcastReceiver”);
intent.putExtra(“msg”, “这是MainActivity页面发送的广播―-》》”);
sendBroadcast(intent);
只发送到优先级较高的接收者那里,然后由优先级高的接受者再传播到优先级低的接收者那里,优先级高的接收者有能力终止这个广播。可以在广播注册时使用intent-filter里面的android: priority=”xxx”去解决或在java代码中用setPriority(xxx)来设置。
主要代码:
Intent intent = new Intent(“myBroadcastReceiver”);
intent.putExtra(“msg”, “这是MainActivity页面发送的广播―-》》”);
sendOrderedBroadcast(intent,null);//如果是该自定义的广播接收者发送广播,第二个参数一般为null
无序广播是不可被截断的,每一个广播接收者都可以收到这个无序广播发送的广播信息;而无序广播时候根据优先级数的大小来判断谁先接收到广播信息,并且可以选择是否截断这个广播信息,如果在某个广播接收者截断信息,在它的优先级之下的广播接收者都接收不到广播信息。
有序广播才能拦截。
主要展示一下使用步骤和过程的代码!
这里的程序实在两个程序中的,但是也可以写在多个程序中,或单个程序中。程序的效果是一样的。因为BroadcastReceiver任何时候都可以接收广播消息,而发送广播消息,只要有上下文的地方都可以。
静态广播接收者的接收测试
package com.lwz.receiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; import android.widget.Toast; /** * 广播接收者的使用 * 这里使用的是静态注册的方法,等待接收广播 */ public class MyBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Log.e("Receiver", "这是静态的广播接受者(优先级500)---》" + intent.getStringExtra("msg")); Toast.makeText(context, "这是使用静态的方法来创建的广播(优先级500)接受者收到消息", Toast.LENGTH_SHORT).show(); abortBroadcast(); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
package com.lwz.receiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; import android.widget.Toast; /** * 广播接收者的使用 * 这里使用的是静态注册的方法,等待接收广播 */ public class MyBroadcastReceiver2 extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Log.e("Receiver", "这是静态的广播接受者(优先级999)---》" + intent.getStringExtra("msg")); Toast.makeText(context, "这是使用静态的方法来创建的广播接受者(优先级999)收到消息", Toast.LENGTH_SHORT).show(); //截断广播 abortBroadcast(); //报错 BroadcastReceiver trying to return result during a non-ordered broadcast //好像是要有序广播才能截断 } }
- 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
<receiver android:name=".MyBroadcastReceiver"> <intent-filter android:priority="500"> <action android:name="myBroadcastReceiver" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver> <receiver android:name=".MyBroadcastReceiver2"> <intent-filter android:priority="999"> <action android:name="myBroadcastReceiver" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
注意这里的广播接收者1和2,基本数据是相同的,但是优先级不同。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="广播的发送" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="sendToSXL" android:text="给静态注册的广播发送信息" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="sendToJava" android:text="给动态注册的广播发送信息" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="sendOrderToXML" android:text="给静态注册的广播接收者发送有序广播信息" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="sendOrderToJava" android:text="给动态注册的广播接收者发送有序广播信息" /> </LinearLayout>
- 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
根据上面按钮的命名,应该知道这些按钮要发送的广播类型!
package com.lwz.receiver; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; /** * 本类用来发送广播 */ public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } //给静态广播发送信息 public void sendToSXL(View view) { //发送广播使用sendBroadcast,需要指定Intent的action来说明发送什么样的广播。 //Intent里面的参数是action,要和静态注册的广播的actin对应 Intent intent = new Intent("myBroadcastReceiver"); intent.putExtra("msg", "这是MainActivity页面发送的广播----》》"); sendBroadcast(intent); } //给动态广播发送信息 public void sendToJava(View view) { //发送广播使用sendBroadcast,需要指定Intent的action来说明发送什么样的广播。 //Intent里面的参数是action,要和动态注册的广播的actin对应 Intent intent = new Intent("javaReceiver"); intent.putExtra("msg", "这是MainActivity页面发送的广播----》》"); sendBroadcast(intent); } //给静态注册的广播发送有序广播信息 public void sendOrderToXML(View view) { //发送有序广播使用sendOrderedBroadcast,需要指定Intent的action来说明发送什么样的广播。 //Intent里面的参数是action,要和静态注册的广播的actin对应 Intent intent = new Intent("myBroadcastReceiver"); intent.putExtra("msg", "这是MainActivity页面发送的广播----》》"); sendOrderedBroadcast(intent,null); } //给静态注册的广播发送有序广播信息 public void sendOrderToJava(View view) { //发送广播使用sendOrderedBroadcast,需要指定Intent的action来说明发送什么样的广播。 //Intent里面的参数是action,要和静态注册的广播的actin对应 Intent intent = new Intent("javaReceiver"); intent.putExtra("msg", "这是MainActivity页面发送的广播----》》"); sendOrderedBroadcast(intent,null); } }
- 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
动态广播接收者的测试
package com.lwz.receiver2; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; import android.widget.Toast; /** * 这里使用动态的方法来创建一个广播接受者 * 动态的广播接收者必须在程序启动后才能接收广播,静态的广播不需要启动就可以接收! */ public class BroadcastReceiveForjava extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Log.e("Receiver", "这是使用动态的方法来创建的广播接受者1)----》" + intent.getStringExtra("msg")); Toast.makeText(context, "这是使用动态的方法来创建的广播接受者1收到消息", Toast.LENGTH_SHORT).show(); abortBroadcast(); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
package com.lwz.receiver2;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
/**
* 这里使用动态的方法来创建一个广播接受者
* 动态的广播接收者必须在程序启动后才能接收广播,静态的广播不需要启动就可以接收!
*/
public class BroadcastReceiveForjava2 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.e(“Receiver”, “这是使用动态的方法来创建的广播接受者2―-》” + intent.getStringExtra(“msg”));
Toast.makeText(context, “这是使用动态的方法来创建的广播接受者2收到消息”, Toast.LENGTH_SHORT).show();
abortBroadcast();
}
}
package com.lwz.receiver2; import android.content.IntentFilter; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; /** * 这里使用动态的方法来创建一个广播接受者 * 动态的广播接收者必须在程序启动后才能接收广播,静态的广播不需要启动就可以接收! * 动态广播的类创建之后要去使用代码注册才能生效 * 另外动态注册后要在某一个时间去解除绑定,否者会报错! */ public class MainActivity extends AppCompatActivity { //定义广播接收者 BroadcastReceiveForjava receiver; BroadcastReceiveForjava2 receiver2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //创建广播接收者对象 receiver = new BroadcastReceiveForjava(); receiver2 = new BroadcastReceiveForjava2(); //注册广播接收者,需要一个意图对象,也需要action参数,这里是定义Action参数 IntentFilter filter = new IntentFilter("javaReceiver"); IntentFilter filter2 = new IntentFilter("javaReceiver"); //动态设置广播的优先级 filter.setPriority(999); filter2.setPriority(10); //注册广播, // 动态广播拦截?先注册者先收到消息??? registerReceiver(receiver2, filter); registerReceiver(receiver, filter); } @Override protected void onDestroy() { //在适当的时候要解除广播接收者的绑定 unregisterReceiver(receiver); unregisterReceiver(receiver2); super.onDestroy(); } }
- 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
无序广播不能截断,有序广播能被高优先级的广播接收者截断。不管是对静态的广播接收者还是对动态的广播接收者都是一样的。
package com.lwz.phoneData; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.telephony.SmsMessage; import android.util.Log; import android.widget.Toast; import java.text.SimpleDateFormat; import java.util.Date; /** * 创建一个短信拦截广播接收者 */ public class SMSBroadcastReceiver extends BroadcastReceiver { private static final String action = "android.provider.Telephony.SMS_RECEIVED"; @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(action)) { Object[] pduses = (Object[]) intent.getExtras().get("pdus"); String mobile = ""; String content = ""; String time = ""; System.out.println(pduses.length); for (Object pdus : pduses) { byte[] pdusmessage = (byte[]) pdus; SmsMessage sms = SmsMessage.createFromPdu(pdusmessage); mobile = sms.getOriginatingAddress();// 发送短信的手机号码 content = sms.getMessageBody(); // 短信内容 Date date = new Date(sms.getTimestampMillis());// 发送日 期 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); time = format.format(date); // 得到发送时间 } Toast.makeText(context, context.getResources().getString(R.string.app_name), Toast.LENGTH_LONG).show(); String show = "发送者:" + mobile + " 内容:" + content + " 时间:" + time; Toast.makeText(context, show, Toast.LENGTH_LONG).show(); } Log.e("TAG","拦截短信"); 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
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
<receiver android:name=".SMSBroadcastReceiver"> <intent-filter android:priority="1001"> <action android:name="android.provider.Telephony.SMS_RECEIVED" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver> 这里action的属性值必须正确,否则不能监听到这个广播! 这里还要添加手机权限: <uses-permission android:name="android.permission.RECEIVE_SMS" />
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
1.Intent.ACTION_AIRPLANE_M;
2.Intent.ACTION_BATTERY_CH;
3.Intent.ACTION_AIRPLANE_MODE_CHANGED;
4.Intent.ACTION_BATTERY_CHANGED;
5.Intent.ACTION_BATTERY_LOW;
6 .Intent.ACTION_BATTERY_OKAY;
7.Intent.ACTION_BOOT_COMPLETED;
8.Intent.ACTION_CAMERA_BUTTON;
9.Intent.ACTION_CLOSE_SYSTEM_DIALOGS;
10.Intent.ACTION_CONFIGURATION_CHANGED;
11.Intent.ACTION_DATE_CHANGED;
12.Intent.ACTION_DEVICE_STORAGE_LOW;
13.Intent.ACTION_DEVICE_STORAGE_OK;
14.Intent.ACTION_DOCK_EVENT;
frameworks\base\services\java\com\android\server\DockObserver.java
15.Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE;
16.Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
17.Intent.ACTION_GTALK_SERVICE_CONNECTED;
18.Intent.ACTION_GTALK_SERVICE_DISCONNECTED;
19.Intent.ACTION_HEADSET_PLUG;
20.Intent.ACTION_INPUT_METHOD_CHANGED;
21.Intent.ACTION_LOCALE_CHANGED;
22.Intent.ACTION_MANAGE_PACKAGE_STORAGE;
23. Intent.ACTION_MEDIA_BAD_REMOVAL;
24.Intent.ACTION_MEDIA_BUTTON;
25. Intent.ACTION_MEDIA_CHECKING;
26.Intent.ACTION_MEDIA_EJECT;
27.Intent.ACTION_MEDIA_MOUNTED;
28.Intent.ACTION_MEDIA_NOFS;
29. Intent.ACTION_MEDIA_REMOVED;
30.Intent.ACTION_MEDIA_SCANNER_FINISHED;
31.Intent.ACTION_MEDIA_SCANNER_SCAN_FILE;
32.Intent.ACTION_MEDIA_SCANNER_STARTED;
33. Intent.ACTION_MEDIA_SHARED;
34.Intent.ACTION_MEDIA_UNMOUNTABLE;
35.Intent.ACTION_MEDIA_UNMOUNTED
36.Intent.ACTION_NEW_OUTGOING_CALL;
37. Intent.ACTION_PACKAGE_ADDED;
38.Intent.ACTION_PACKAGE_CHANGED;
39.Intent.ACTION_PACKAGE_DATA_CLEARED;
40.Intent.ACTION_PACKAGE_INSTALL;
41.Intent.ACTION_PACKAGE_REMOVED;
42.Intent.ACTION_PACKAGE_REPLACED;
43.Intent.ACTION_PACKAGE_RESTARTED;
44.Intent.ACTION_POWER_CONNECTED;
45.Intent.ACTION_POWER_DISCONNECTED;
46.Intent.ACTION_PROVIDER_CHANGED;
47.Intent.ACTION_REBOOT;
48.Intent.ACTION_SCREEN_OFF;
49. Intent.ACTION_SCREEN_ON;
50.Intent.ACTION_SHUTDOWN;
51. Intent.ACTION_TIMEZONE_CHANGED;
52.Intent.ACTION_TIME_CHANGED;
53.Intent.ACTION_TIME_TICK;
54. Intent.ACTION_UID_REMOVED;
55. Intent.ACTION_UMS_CONNECTED;
设备已进入USB大容量储存状态时发出的广播?
56.Intent.ACTION_UMS_DISCONNECTED;
57.Intent.ACTION_USER_PRESENT;
58.Intent.ACTION_WALLPAPER_CHANGED;
发送频率低的可以使用 数据量小在可使用 intent携带的数据不能太大 广播的操作一定要在5秒钟内完成(10秒不能完成,ANR),如果耗时时间太长,开启服务。
两种发送方法
两者及其接收广播的区别:
(1)动态注册广播不是常驻型广播,也就是说广播跟随Activity的生命周期。注意在Activity结束前,移除广播接收器。 静态注册是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。
(注:静态注册的广播,即使Activity销毁了,仍然可以收到广播。更牛掰的是即使杀死进程,仍然可以收到广播,关于这点不同的手机测试的结果是不同的,为了验证这个问题,我用的是google的nexus手机测试的。
在Android中,有一些action是不支持静态注册的:
android.intent.action.SCREEN_ON
android.intent.action.SCREEN_OFF
android.intent.action.BATTERY_CHANGED
android.intent.action.CONFIGURATION_CHANGED
android.intent.action.TIME_TICK)
(2)当广播为有序广播时:优先级高的先接收(不分静态和动态)。同优先级的广播接收器,动态优先于静态
(3)同优先级的同类广播接收器,静态:先扫描的优先于后扫描的,动态:先注册的优先于后注册的。
(4)当广播为默认广播时:无视优先级,动态广播接收器优先于静态广播接收器。同优先级的同类广播接收器,静态:先扫描的优先于后扫描的,动态:先注册的优先于后册的。
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/markdown_views-ea0013b516.css"> </div>