Android四大组件-BroadcastReceiver

广播:BoradcastReceiver

1 、BoradcastReceiver的作用?

Broadcast receiver 是一个用来响应系统范围内的广播的组件。 很多广播发自于系统本身。—例如, 通知屏幕已经被关闭、电池低电量、照片被拍下的广播。 应用程序也可以发起广播。—例如, 通知其它程序,一些数据被下载到了设备,且可供它们使用。 虽然广播并不提供用户交互界面,它们也可以创建一个状态栏通知 来提醒用户一个广播事件发生了。尽管如此,更多的情形是,一个广播只是进入其它组件的一个“门路”,并试图做一些少量的工作。 例如,它可能发起一个服务,并通过服务执行与这个广播事件相关的工作。

  1. 数据传输与共享,比如系统自带广播,开机广播,电量广播,短信,电话广播等。

  2. 起到通知的作用,比如在收到广播后,开启Service,启动Activity,或者进入网络查询或者更新Ui界面;
    在android中比较常用的情景是Activity与startService()方法的启动通过BroadcastReceiver()来实现


2、生命周期

developer上的描述:
这里写图片描述
翻译:

广播生命周期
一个BroadcastReceiver对象仅适用执行在onReceive的时间上(上下文,意图)。一旦你的代码返回这个函数,系统考虑的对象将完成,不再活跃。
这具有重要的影响,你可以做什么在onReceive(上下文,意图)执行:任何需要异步操作是不可用的,因为你需要从函数中返回处理异步操作,但在这一点上,BroadcastReceiver不再活跃,因此系统在执行异步操作前已经将它杀死。
特别是,你可能不会显示一个对话框或绑定到一个服务从一个BroadcastReceiver中。对于前者,你应该使用NotificationManager API。对于后者,你可以使用上下文。startservice()将命令发送到服务。

3、 广播中为什么不能做耗时操作,或者开子线程进行耗时操作?

在广播中当调用了onReciver()方法并传递它包含消息的intent对象,广播接收者认为当它执行这个方法的时候为活跃的,当onReceive()执行后,它是不活跃的。活跃的广播接收者进程是受保护的,不会被杀死, 但系统可以在任何时候杀死不活跃的进程,特别是内存吃紧的时候。如果在广播中作耗时操作,并且onReceive()方法执行后,开的子线程没有执行完,有可能广播已经被销毁了,并且每次发送的广播都会创建BroadcastReceiver的实例。因此, BroadcastReceiver中不能作耗时操作,如果超过10秒中就是报ANR异常;

如果要做耗时操作的话,应该在广播中用intent开启一个Service,在服务中开启线程,做耗时操作;


4、两种开启广播的方式:

1、静态注册,在清单文件中注册,这种广播开启的方式比较常用。即使应用退出了,广播也能接收到消息。

2、动态注册(与Service的bindService相似): 就是在代码中注册,不用在清单文件中注册但这注册方式启动的广播,要在组件销毁的时候,解除注册,如果不解除退出程序可能报错。


5、有序广播和无序广播

developer描述:
这里写图片描述

翻译:

普通广播(Context.sendBroadcast)是完全异步的。广播的所有接收器都运行在未定义的顺序中,通常在同一时间。这是更有效的,但这意味着接收器不能使用的结果在广播中中止。
有序广播(Context.sendorderedbroadcast)被传递到一个接收器中。由每个接收端执行,它可以向下一个接收器传递一个广播,或者它可以完全中止广播,以便它不会被传递给其他接收器。在可与安卓控制的顺序接收器中,匹配的意图过滤器的优先级属性,与相同优先级的接收器将在任意顺序运行。


普通广播:通过sendBroadcast()方法来发送。通过这种形式发送广播接收的顺序也是不确定的。但效率比较高

有序广播:是通过sendOrderedBroadcast来发送。按优先级的不同,优先Receiver可对数据进行处理,并传给下一个Receiver效率比较低。可以在清单文件中设置优先级从-1000-1000;

      <intent-filter android:priority="1000">
            <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
        </intent-filter>
    </receiver>-->

终止广播:abrotBroadcast()
当android系统接收到短信时,会发送一个广播BroadcastReceiver(),这个广播是有序的形式发送的。
短信拦截器的功能就是把BroadcastReceiver的优先级设置的比较系统高,当收到这条广播时,终止广播。这样就可以拦截短信了


1、静态的方式创建广播,以接收到短信为例:
在xml文件中注册:

  <receiver android:name=".MsgReceiver">
            <intent-filter>
                <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
            </intent-filter>
        </receiver>

添加权限:

  <uses-permission android:name="android.permission.RECEIVE_SMS"/>

在MsgReceiver()中的代码:

public class MsgReceiver extends BroadcastReceiver {
    private static final String TAG = "MsgReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle bundle = intent.getExtras();
        SmsMessage[] smsMessages = null;
        Object[] pdus = null;
        if (bundle != null) {
            pdus = (Object[]) bundle.get("pdus");
        }
        if (pdus !=null){
            smsMessages = new SmsMessage[pdus.length];
            String sender = null;
            String content = null;
            for (int i=0; i<pdus.length; i++){
                smsMessages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
                sender = smsMessages[i].getOriginatingAddress();
                content = smsMessages[i].getMessageBody();
                Log.i(TAG, "SMS:"+sender+content);
            }
        }
    }
}

在activity中什么也不做,发送短信给10086则:
从log中可以看到短信内容为:
这里写图片描述


2、通过动态的方式注册广播,也就是在代码中注册(这种方式的注册广播使用的比较少,因为它需要手机注销广播,如果没有注销广播,退出时发报异常)
在MyReceiver()中代码:

public class MyReceiver extends BroadcastReceiver {
    private static  final  String  TAG="MyReceiver";
    private String msg;
    @Override
    public void onReceive(Context context, Intent intent) {
        //在发送广播时的标识
       if(intent.getAction().equals("a")){
             msg=intent.getStringExtra("name");
        };
        Log.i(TAG, msg);
    }
}

在MainActivity中的注册代码:

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    public static final String TAG_ID="";
    private Button btn_send;

    private MyReceiver receiver;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_send = (Button) findViewById(R.id.btn_send);
        btn_send.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                receiver = new MyReceiver();
                //意图过滤器,过滤Intent;
                IntentFilter filter = new IntentFilter();
                filter.addAction("a");
                //注册广播;
                registerReceiver(receiver, filter);
                //在Intent中携带数据,也可以用Bundle
                Intent intent =new Intent();
                //发送广播时的设置的一个标识,用于标识是从哪里发过来。
                intent.setAction("a");
                //也可以能过Bundle打包传递数据;
                intent.putExtra("name", "csdn");
                //发送广播
                sendBroadcast(intent);
                Log.i(TAG, "发送广播");
            }
        });

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //解除注册;
        if(receiver!=null) {
            unregisterReceiver(receiver);
        }
    }

}

通过这种方式开启的广播在退出应用时,一定要注销广播。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值