创建BroadcastReceiver
package com.hang.androidtestdemo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class MyReceiver extends BroadcastReceiver {
public static final String TAG = MyReceiver.class.getSimpleName();
public static final String ACTION = MyReceiver.class.getName();
public MyReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
// This method is called when this BroadcastReceiver receives an Intent broadcast.
Log.d(TAG, "name: " + intent.getStringExtra("name"));
System.out.println();
}
}
- extends BroadcastReceiver interface
- implement onReceive()
注册BroadCastReciver
1在Manifest中进行注册
<receiver
android:name="com.hang.androidtestdemo.MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.hang.androidtestdemo.MyReceiver" />
</intent-filter>
</receiver>
2在java中注册
@Override
protected void onResume() {
super.onResume();
IntentFilter intentFilter = new IntentFilter(MyReceiver.ACTION);
registerReceiver(myReceiver, intentFilter);
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(myReceiver);
}
为了减少手机系统的负载,一般会在onResume中进行注册,在onPause中进行取消
选择注册BroadcastReceiver方法
不论APP是否在前台运行,你都想监听系统事件,一定要在Manifest中进行注册;如果仅仅在APP某一个页面,对某些事件感兴趣的时候,在java代码中注册是一个不错的选择——节省系统开销。
注意:系统为了延长手机电池寿命,节省系统开销,在Manifest中注册的TIME_TICK广播监听无效。
发送广播的方法
- 通过Action间接启动
Intent intent = new Intent(MyReceiver.ACTION);
intent.putExtra("name", "guchuanhang2");
sendBroadcast(intent);
通过Intent的action指向Broadcast注册的Action
- 通过BroadcastReceiver组件名称直接启动
这里面要注意以下,BroadcastReceiver组件必须要在Manifest中进行声明
Intent intent = new Intent(this,MyReceiver.class);
intent.putExtra("name", "guchuanhang3");
sendBroadcast(intent);
有序广播
可以指定广播接收顺序的广播,高优先级先接受,同优先级不确定,没有指定priority的默认为0.高优先级的BroadcastReceiver接收到广播后,可以对接收到的参数进行修改,写一个优先级接收到的就是修改后的参数。
sendOrderedBroadcast(Intent intent, String receiverPermission,
BroadcastReceiver resultReceiver, Handler scheduler,
int initialCode, String initialData, Bundle initialExtras)
参数太复杂了,让我们通过一个例子,来一个感性的认识吧。
- 创建两个不同优先级的BroadcastReceiver
package com.hang.androidtestdemo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
// MyReceiver.java
public class MyReceiver extends BroadcastReceiver {
public static final String ACTION = MyReceiver.class.getName();
public static final String TAG = MyReceiver.class.getSimpleName();
public MyReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
//通过 getResultExtras(true)接收传递过来的参数,没有则会创建一个对象
Bundle results = getResultExtras(true);
String hierarchy = results.getString("hierarchy");
results.putString("hierarchy", hierarchy + "->" + TAG);
Log.d(TAG, TAG);
}
}
package com.hang.androidtestdemo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
// MySecondReceiver .java
public class MySecondReceiver extends BroadcastReceiver {
private String TAG = MyReceiver.class.getSimpleName();
public MySecondReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
Bundle results = getResultExtras(true);
String hierarchy = results.getString("hierarchy");
results.putString("hierarchy", hierarchy + "->" + "MySecondReceiver");
Log.d(TAG, "MySecondReceiver");
}
}
MySecondReceiver的优先级比MyReceiver的优先级要高
<receiver
android:name="com.hang.androidtestdemo.MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="1">
<action android:name="com.hang.androidtestdemo.MyReceiver" />
</intent-filter>
</receiver>
<receiver
android:name="com.hang.androidtestdemo.MySecondReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="2">
<action android:name="com.hang.androidtestdemo.MyReceiver" />
</intent-filter>
</receiver>
MainActivity主代码:
package com.hang.androidtestdemo;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends Activity {
public static final String TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
IntentFilter filter = new IntentFilter(MyReceiver.ACTION);
//default priority 0
//filter.setPriority(0);
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//通过这种方式,获取传递过来的参数,没有会创建一个对象
Bundle results = getResultExtras(true);
String hierarchy = results.getString("hierarchy");
results.putString("hierarchy", hierarchy + "->" + TAG);
Log.d(MyReceiver.TAG, "Anonymous class broadcast receiver");
}
}, filter);
Intent intent = new Intent(MyReceiver.ACTION);
sendOrderedBroadcast(intent, null, new BroadcastReceiver() {
//this will receiver last
@Override
public void onReceive(Context context, Intent intent) {
Bundle results = getResultExtras(true);
String hierarchy = results.getString("hierarchy");
System.out.println(hierarchy);
Log.d(MyReceiver.TAG, "Final Receiver");
Log.d(MyReceiver.TAG, "hierarchy: "+hierarchy);
}
}, null, Activity.RESULT_OK, null, null);
}
}
本地广播
为了APP数据的安全性,尽可能的使用本地广播
package com.hang.androidtestdemo;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected void onResume() {
super.onResume();
// Generally in your onResume()
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, new IntentFilter("my-custom-event"));
// Send
Intent intent = new Intent("my-custom-event");
intent.putExtra("foo", "bar");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String message = intent.getStringExtra("foo");
Log.d("LocalBroadcastManager", "foo : " + message);
System.out.println();
}
};
@Override
protected void onPause() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
super.onPause();
}
}
相对于全局广播,
在发送广播的方法修改为:
LocalBroadcastManager.getInstance(this).sendBroadcast
接收广播的方法修改为:
LocalBroadcastManager.getInstance(this).registerReceiver
反注册广播的方法修改为:
LocalBroadcastManager.getInstance(this).unregisterReceiver
通过java代码控制Manifest中声明的BroadcastReceiver
默认情况下,Manifest中声明的BroadcastReceiver会一直有效。
可是在APP Manifest声明一个监听系统广播的BroadcastReceiver &&在onReceive中打印日志,为什么在我的APP退出后,系统广播有变化没有打印日志呢?
是Manifest中声明的BroadcastReceiver的生命周期,仅限于APP运行?
对于这个问题,我认为是安卓系统广播,都采用的默认设置
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
也就是排除了停止的APP接收。
验证这个问题,可以做两个小Demo:
Demo1 在Manifest中声明BroadcastReceiver
Demo2发送广播(当然是Demo1中监听的action).
1.在Demo1&&Demo2都运行的时候,Demo1可以接收到
2.在Demo1关闭,Demo2发送默认广播,Demo1无法接收
2.在Demo1关闭,Demo2发送广播(设置
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES))
Demo1可以接收
转入正题,如何控制Manifest中声明的 BroadcastReceiver的作用域?
1.启动
ComponentName componentName = new ComponentName(this, MyReceiver.class);
PackageManager packageManager = getPackageManager();
packageManager.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
PackageManager.DONT_KILL_APP);
2.关闭
ComponentName componentName = new ComponentName(this, MyReceiver.class);
PackageManager packageManager = getPackageManager();
packageManager.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
APP使用广播的建议&&注意事项
- 尽可能使用本地广播——LocalBroadcastManager
- 即使在同一个APP内,Manifest中声明的BroadcastReceiver 不能 收到LocalBroadcastManager发送的广播
- 尽可能通过java代码注册广播,而不是通过Manifest进行声明
- 通过java代码控制Manifest中声明的广播的作用范围