android | 广播

BroadcastReceiver

广播:Android 组件(安卓有四大组件ActivityContentProviderBroadcastReceiverService`)之间的通信方式。
使用了观察者模式,基于消息的发布/订阅事件模型。(解耦,易扩展)
流程:原文地址

  1. 广播接收者BroadcastReceiver通过Binder机制向AMS(Activity Manager Service)进行注册;
  2. 广播发送者通过binder机制向AMS发送广播;
  3. AMS查找符合相应条件(IntentFilter/Permission等)的BroadcastReceiver,将广播发送到BroadcastReceiver(一般情况下是Activity)相应的消息循环队列中;
  4. 消息循环执行拿到此广播,回调BroadcastReceiver中的onReceive()方法。

查看文档

文档地址:广播接收器
首先是抽象类,其抽象方法只有一个就是onReceive(Context context, Intent intent)方法(当BroadcastReceiver接收Intent广播时调用此方法。context是上下文,intent是广播携带的数据)

分步骤实现

编写对应事件的BroadCastReveicer

继承BroadCastReveicer,复写onReceive方法。

注册到安卓系统

作为四大组件之一,就需要注册。有两种注册方式:

  1. 静态注册(AndroidManifest.xml中)
    <receiver android:name=".myReceiver"
    android:permission="如果设置,具有相应权限的广播发送方发送的广播才能被此broadcastReceiver所接收;">
       <intent-filter>
           //要监听的广播类型
            <action android:name="android.intent.action.ACTION_SCREEN_OFF" />
            <action android:name="android.intent.action.ACTION_SCREEN_ON" />
        </intent-filter>
        <intent-filter>
        <!--下面是检测应用首次启动,就开始广播-->
         <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>

使用Intent对象启动广播,在intent过滤器中过滤,符合标准才调用。

  1. 动态注册(代码中)
    在代码中通过调用ContextregisterReceiver函数,可以在程序中动态注册BroadcastReceiver。

    public class MainActivity extends Activity {
     private MyBroadcastReceiver receiver ;
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
    
         registerMyReceiver();
     }
     private void registerMyReceiver() {
         receiver = new MyBroadcastReceiver();
         IntentFilter filter = new IntentFilter();//创建IntentFilter对象        
         //IntentFilter对象中添加要接收的关屏广播。对应Manifest.xml中的action
         filter.addAction(Intent.ACTION_SCREEN_OFF);
         //IntentFilter对象中添加要接收的点亮屏幕广播。对应Manifest.xml中的action
         filter.addAction(Intent.ACTION_SCREEN_ON);
         registerReceiver(receiver, filter);
     }
    
     @Override
     protected void onDestroy() {
         super.onDestroy();
          if(receiver != null){
             unregisterReceiver(receiver);//Android中所有与观察者模式有关的设计中,一旦涉及到register,必定在相应的时机需要unregister。
         }
     }
    }

差异

看看这两种方式有什么不同:

  1. 静态注册
    静态注册依附于清单文件,只要APP启动过一次,所静态注册的广播就会生效,无论当前的APP处于停止使用还是正在使用状态。
    只要相应的广播事件发生,系统就会遍历所有的清单文件,通知相应的广播接收者接收广播,然后调用广播接收者的onReceiver方法。
    也就是无论你的程序是否关闭,都会接收到广播事件。这很好,像电量监听等。但是,也无疑很耗电、耗CPU等,故而在有些场合就不合适了。
    手机的电量等资源是有限的,有些情况并不需要一直接收广播,故而我们也需要动态注册。

  2. 动态注册
    动态注册方式依赖于所注册的组件,当APP关闭后,组件对象都不在了,动态注册的代码都不存在了,所动态注册监听的action自然不在生效。
    如果一个BroadcastReceiver用于更新UI,那么通常会使用这种方法进行注册,建议在Activity启动时注册,在Activity不可见的时候取消注册。

  3. 静态注册的广播传播速度要远远慢于动态注册的广播。

  4. 动态注册的广播的优先级大于静态注册的广播。

  5. 可同时注册。.

案例

接下来一个简单的案例来理解广播。
先看布局文件,是一个按钮:
activity_main.xml

<Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:text="发送消息给Receiver" />

然后看看自定义的myBroadcast.java文件:

package com.weizu.broadcast;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class myBroadcast extends BroadcastReceiver {
    //系统自调用,需要无参的构造函数
    public myBroadcast() {}

    //接收广播
    @Override
    public void onReceive(Context arg0, Intent arg1) {
        Log.i("onReceive", "调用了");
    }
}

再然后就是在manifest.xml文件中注册一下:

<receiver android:name=".myBroadcast" >
            <intent-filter>
                <action android:name="android.intent.action.EDIT" />
            </intent-filter>
</receiver>

由于是四大组件之一,故而和activity平级放置。

最后就是我们的MainActivity.java文件:

btn = (Button)findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View arg0) {
            //发送广播
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_EDIT);
            MainActivity.this.sendBroadcast(intent);
        }
    });

运行结果:
在出现的按钮上点击,然后用LogCat可以看到输出的日志。

到此,也就简单完成了一个广播案例。


   Reprint policy


《android | 广播》 by 无涯明月 is licensed under a Creative Commons Attribution 4.0 International License
 Previous
android | 广播 android | 广播
直接说案例:布局文件: <EditText android:id="@+id/vaild_code" android:layout_width="fill_parent" android
2019-09-07
Next 
深思与反省 深思与反省
哎,看上篇反省就是上个月的明天,突然自己又很想写一篇来记录此时的感受。 买菜的时候,翻了翻好几个月都不曾碰的微信朋友圈,然后就刷了一个月的动态。感觉很方,落寞感一下子就涌上了心头,看着别个的梦想和生活,谈不上羡慕和佩服,但是想想自己现在
2019-08-28
  TOC