Android四大组件-BroadcastReceiver

来源:互联网 发布:自己淘宝店铺的二维码 编辑:程序博客网 时间:2024/05/16 19:30

广播: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
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 汽车智能钥匙没电了怎么办 辐射3食物有辐射怎么办 辐射3玩起来很卡怎么办 辐射3多余的瓶盖怎么办 辐射4开锁太快怎么办 极度恐慌3没子弹怎么办 辐射3道德值低怎么办 辐射3任务做完了怎么办 极限竞速6闪退怎么办 两个睾丸都碎了怎么办 快递退回去了钱怎么办 想登录老公微信怎么办 养狗家里味道大怎么办 实在不想养狗了怎么办 培训完不想干了怎么办 干了几天想离职怎么办 药流开始流血了怎么办 药流期间同房了怎么办 想学韩语可是没基础怎么办 鞋子多买了一双怎么办 胳膊抻着了怎么办妙招 胳膊抻筋了 很疼怎么办 干活胳膊抻筋了怎么办 胳膊上的筋扭了怎么办 一岁宝宝脖子歪怎么办 3岁宝宝轻微斜颈怎么办 2岁宝宝轻微斜颈怎么办 肩膀劳损痛的厉害怎么办 颈后面有个囊肿怎么办 扭腰了怎么办有偏方吗 跑步机点加油了怎么办 高二了英语30分怎么办 苍蝇往人身上飞怎么办 25岁了写字好丑怎么办 我字写得超难看怎么办 高三体检有纹身怎么办 快高考了有纹身怎么办 艺考身上有纹身怎么办 初三考试考砸了怎么办 考差了我该怎么办 发票认购簿丢了怎么办