BroadcastReceiver

来源:互联网 发布:get it beauty self 编辑:程序博客网 时间:2024/06/03 15:00

创建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.javapublic 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 .javapublic 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中声明的广播的作用范围

翻译地址

http://codetheory.in/android-broadcast-receivers/

1 0