BroadcastReceiver

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

翻译地址

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值