• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

Android入门教程-广播机制-Broadcast

android 搞代码 3年前 (2022-03-01) 19次浏览 已收录 0个评论

Android利用能够通过播送从零碎或其余App接管或发送音讯。相似于订阅-公布设计模式。当某些事件产生时,能够收回播送。 零碎在某些状态扭转时会收回播送,例如开机、充电。App也可发送自定义播送。播送可用于利用间的通信,是IPC的一种形式。

播送的品种

播送的品种也能够看成是播送的属性。

  • 规范播送(Normal Broadcasts)
    齐全异步的播送。播送收回后,所有的播送接收器简直同时接管到这条播送。 不同的App能够注册并接到规范播送。例如零碎播送。
  • 有序播送(Ordered Broadcasts)
    同步播送。同一时刻只有一个播送接收器能接管到这条播送。这个接收器解决完后,播送才会持续传递。 有序播送是全局的播送。
  • 本地播送(Local Broaddcasts)
    只在本App发送和接管的播送。注册为本地播送的接收器无奈收到规范播送。
  • 带权限的播送
    发送播送时能够带上相干权限,申请了权限的 App 或播送接收器能力收到相应的带权限的播送。 如果在 manifest 中申请了相应权限,接收器能够不必再申请一次权限即可接到相应播送。

接管播送

创立播送接收器,调用onReceive()办法,须要一个继承 BroadcastReceiver 的类。

注册播送
代码中注册称为动静注册。在AndroidManifest.xml中注册称为动态注册。动静注册的刚波接收器肯定要勾销注册。在onDestroy()办法中调用unregisterReceiver()办法来勾销注册。

不要在onReceive()办法中增加过多的逻辑操作或耗时的操作。因为在播送接收器中不容许开启线程,当onReceive()办法运行较长时间而没完结时,程序会报错。因而播送接收器个别用来关上其余组件,比方创立一条状态栏告诉或启动一个服务。

新建一个MyExampleReceiver继承自BroadcastReceiver

public class MyExampleReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context,"Got it",Toast.LENGTH_SHORT).show();
        //abortBroadcast();
    }
}

abortBroadcast()能够截断有序播送

AndroidManifest.xml中注册播送接收器;android:name里填接收器的名字。 能够设置播送接收器优先级:

<intent-filter android:priority="100">

<receiver android:name=".MyExampleReceiver">
    <intent-filter>
        <action android:name="com.rust.broadcasttest.MY_BROADCAST"/>
    </intent-filter>
</receiver>

让接收器接管到一条"com.rust.broadcasttest.MY_BROADCAST"播送。
发送自定义播送(规范播送)时,要传送这个值。例如:

Intent intent = new Intent("com.rust.broadcasttest.MY_BROADCAST");
sendBroadcast(intent);

发送有序播送,该当调用sendOrderedBroadcast()

Intent intent = new Intent("com.rust.broadcasttest.MY_BROADCAST");
sendOrderedBroadcast(intent,null);

发送播送

App有3种发送播送的形式。发送播送须要应用Intent类。

sendOrderedBroadcast(Intent, String)

发送有序播送。每次只有1个播送接收器能接到播送。 接收器接到有序播送后,能够齐全地截断播送,或者传递一些信息给下一个接收器。 有序播送的程序可受android:priority标签影响。同等级的接收器收到播送的程序是随机的。

sendBroadcast(Intent)

以一个未定义的程序向所有接收器发送播送。也称作一般播送。 这种形式更高效,然而接收器不能给下一个接收器传递音讯。这类播送也无奈截断。

**LocalBroadcastManager.sendBroadcast
播送只能在应用程序外部进行传递,并且播送接收器也只能接管到来自本应用程序收回的播送。 这个办法比全局播送更高效(不须要Interprocess communication,IPC),而且不须要放心其它App会收到你的播送以及其余平安问题。

播送与权限

发送带着权限的播送

当你调用sendBroadcast(Intent, String)sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)时,你能够指定一个权限。
接收器在manifest中申请了相应权限时能力收到这个播送。

例如发送一个带着权限的播送

sendBroadcast(new Intent("com.example.NOTIFY"), Manifest.permission.SEND_SMS);

接管播送的app必须注册相应的权限

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

当然也能够应用自定义。在 manifest 中应用 permission 标签

<permission android:name="custom_permission" />

增加后编译一下。即可调用Manifest.permission.custom_permission

接管带权限的播送

若注册播送接收器时申明了权限,那么只会接管到带着相应权限的播送。

在配置文件中申明权限,程序能力拜访一些要害信息。 例如容许查问零碎网络状态。

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

<!-- 机器开机播送 -->
<uses-permission android:name="android.permission.BOOT_COMPLETED">

如果没有申请权限,程序可能会意外敞开。

应用示例

发送和接管播送。分为发送和接管方2个App。

应用带权限的播送。零碎权限与自定义权限。 应用权限须要在AndroidManifest.xml中申明。如果是自定义权限,须要先增加自定义权限。

<!-- 自定义的权限  给播送用 -->
<permission android:name="com.rust.permission_rust_1" />
<uses-permission android:name="com.rust.permission_rust_1" />

发送播送时带上权限申明。接管方(不管是否己方App)须要在AndroidManifest.xml中申请权限。 注册接收器时也须要申明权限。

发送不带权限的有序播送

Intent intent = new Intent(MSG_PHONE);
sendOrderedBroadcast(intent, null);
Log.d(TAG, "[RustFisher-App1] 发送不带权限的有序播送, " + intent.getAction());

发送方App1代码

private static final String TAG = "rustApp";
    public static final String MSG_PHONE = "msg_phone";
    public static final String PERMISSION_RUST_1 = "com.rust.permission_rust_1";

        // onCreate注册播送接收器
        registerReceiver(mStandardReceiver1, makeIF());
        registerReceiver(mStandardReceiver2, makeIF());
        registerReceiver(mStandardReceiver3, makeIF());

        registerReceiver(mStandardReceiverWithPermission, makeIF(),
                Manifest.permission.permission_rust_1, null);  // 带上权限

        LocalBroadcastManager.getInstance(getApplicationContext())
                .registerReceiver(mLocalReceiver1, makeIF());
        LocalBroadcastManager.getInstance(getApplicationContext())
                .registerReceiver(mLocalReceiver2, makeIF());
        LocalBroadcastManager.getInstance(getApplicationContext())
                .registerReceiver(mLocalReceiver3, makeIF());

        // 解除接收器
        unregisterReceiver(mStandardReceiver1);
        unregisterReceiver(mStandardReceiver2);
        unregisterReceiver(mStandardReceiver3);

        unregisterReceiver(mStandardReceiverWithPermission);

        LocalBroadcastManager.getInstance(getApplicationContext())
                .unregisterReceiver(mLocalReceiver1);
        LocalBroadcastManager.getInstance(getApplicationContext())
                .unregisterReceiver(mLocalReceiver2);
        LocalBroadcastManager.getInstance(getApplicationContext())
                .unregisterReceiver(mLocalReceiver3);

    // 发送规范播送
    private void sendStandardBroadcast() {
        Intent intent = new Intent(MSG_PHONE);
        sendBroadcast(intent);
        Log.d(TAG, "[RustFisher-App1] Dispatcher 发送规范播送");
    }

    // 发送带权限的规范播送
    private void sendStandardBroadcastWithPermission() {
        Intent intent = new Intent(MSG_PHONE);
        sendBroadcast(intent, PERMISSION_RUST_1);
        Log.d(TAG, "[RustFisher-App1] Dispatcher 发送带权限的规范播送");
    }

    // 发送本地播送
    private void sendAppLocalBroadcast() {
        Intent intent = new Intent(MSG_PHONE);
        LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
        Log.d(TAG, "[RustFisher-App1] Dispatcher 发送本地播送");
    }

    private IntentFilter makeIF() {
        IntentFilter intentFilter = new IntentFilter(MSG_PHONE);
        intentFilter.addAction(Intent.ACTION_TIME_TICK);
        intentFilter.addAction(Intent.ACTION_TIME_CHANGED);
        return intentFilter;
    }

    // 规范接收器  用context来注册
    private BroadcastReceiver mStandardReceiver1 = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(TAG, "[RustFisher-App1] 规范接收器1 收到: " + intent.getAction());
        }
    };

    // 规范接收器  用context来注册
    private BroadcastReceiver mStandardReceiver2 = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(TAG, "[RustFisher-App1] 规范接收器2 收到: " + intent.getAction());
            if (intent.getAction().endsWith(MSG_PHONE)) {
                abortBroadcast(); // 截断有序播送
                Log.d(TAG, "[RustFisher-App1] 规范接收器2截断有序播送 " + intent.getAction());
            }
        }
    };

    // 规范接收器  用context来注册
    private BroadcastReceiver mStandardReceiver3 = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(TAG, "[RustFisher-App1] 规范接收器3 收到: " + intent.getAction());
        }
    };

    // 注册的时候给它带权限  规范接收器
    private BroadcastReceiver mStandardReceiverWithPermission = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(TAG, "[RustFisher-App1] 带权限的规范接收器收到: " + intent.getAction());
        }
    };

    /**
 * 用LocalBroadcastManager来注册成为本地接收器
 * 收不到规范播送 - 不论是本app收回的还是别的中央收回来的
 */
    private BroadcastReceiver mLocalReceiver1 = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(TAG, "[RustFisher-App1] 本地接收器1 收到: " + intent.getAction());
        }
    };

    private BroadcastReceiver mLocalReceiver2 = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(TAG, "[RustFisher-App1] 本地接收器2 收到: " + intent.getAction());
        }
    };

    private BroadcastReceiver mLocalReceiver3 = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(TAG, "[RustFisher-App1] 本地接收器3 收到: " + intent.getAction());
        }
    };

接管方App2代码

<!-- 自定义的权限  给播送用 -->
<permission android:name="com.rust.permission_rust_1" />
<uses-permission android:name="com.rust.permission_rust_1" />
public static final String MSG_PHONE = "msg_phone";

    // onCreate里注册接收器
    registerReceiver(mDefaultReceiver, makeIF());
    LocalBroadcastManager.getInstance(getApplicationContext())
            .registerReceiver(mLocalReceiver, makeIF());

    unregisterReceiver(mDefaultReceiver);
    LocalBroadcastManager.getInstance(getApplicationContext())
            .unregisterReceiver(mLocalReceiver);

    private BroadcastReceiver mDefaultReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(TAG, "[App2] standard receive: " + intent.getAction());
        }
    };

    private BroadcastReceiver mLocalReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(TAG, "[App2] local receive: " + intent.getAction());
        }
    };

    private IntentFilter makeIF() {
        IntentFilter intentFilter = new IntentFilter(MSG_PHONE);
        intentFilter.addAction(Intent.ACTION_TIME_TICK);
        intentFilter.addAction(Intent.ACTION_TIME_CHANGED);
        return intentFilter;
    }

应用LocalBroadcastManager收回的本地播送,另一个App是接管不到的。 要收到本地播送,同样须要LocalBroadcastManager来注册接收器。

能够把本地播送看成是一个部分的,App内的播送体系。

试验中咱们留神到,Intent.ACTION_TIME_TICK播送是能够截断的。

监听屏幕亮灭

应用播送监听设施屏幕亮灭状态。这个是零碎收回来的播送。

应用的action是

  • Intent.ACTION_SCREEN_ON 亮屏
  • Intent.ACTION_SCREEN_OFF 灭屏

      private void registerScreenListener() {
          IntentFilter filter = new IntentFilter();
          filter.addAction(Intent.ACTION_SCREEN_ON);
          filter.addAction(Intent.ACTION_SCREEN_OFF);
          registerReceiver(mScreenReceiver, filter);
      }
    
      private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
          @Override
          public void onReceive(Context context, Intent intent) {
              final String action = intent.getAction();
              if (Intent.ACTION_SCREEN_ON.equals(action)) {
                  // 屏幕亮
              } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
                  // 屏幕灭
              }
          }
      };

Broadcast 相干面试题

1. 播送传输的数据是否有限度,是多少,为什么要限度?

  • 播送是通过Intent携带须要传递的数据的
  • Intent是通过Binder机制实现的
  • Binder对数据大小有限度,不同room不一样,个别为1M

2. 播送的分类?

  • 规范播送:通过context. sendBroadcast或者context. sendBroadcastAsUser发送给以后零碎中所有注册的接受者,也就是只有注册了就会接管到。利用在须要告诉各个播送接收者的状况下应用,如开机启动。
  • 有序播送:接收者依照优先级解决播送,并且后面解决播送的接受者能够停止播送的传递,个别通过context. sendOrderedBroadcast或者context.sendOrderedBroadcastAsUser,在须要有特定拦挡的场景下应用,如黑名单短信、电话拦挡。
  • 粘性播送:能够发送给当前注册的接受者,意思是零碎会将后面的粘性播送保留在AMS中,一旦注册了与以保留的粘性播送合乎的播送,在注册完结后会立刻收到播送,个别通过context. sendStickyBroadcast或context.sendStickyOrderedBroadcast来发送,从字面上看,能够看进去粘性播送也分为一般粘性播送和有序粘性播送。
  • 本地播送:收回的播送只能在应用程序外部进行传递,播送接收器也只能承受来自本应用程序的播送。
  • 全局播送:零碎和播送,收回的播送能够被其余任何应用程序接管到,并且也能够承受到其余任何应用程序的播送。

3. 播送的应用场景,应用形式
播送是一种宽泛使用的在应用程序之间传输信息的机制,次要用来监听系统或者利用收回的播送信息,而后依据播送信息作为相应的逻辑解决,也能够用来传输大量、频率低的数据。

在实现开机启动服务和网络状态扭转、电量变动、短信和复电时通过接管零碎的播送让应用程序作出相应的解决。

应用:

//在AndroidManifest中动态注册
<receiver
    android:name=".MyBroadcastReceiver"
    android:enabled="true"
    android:exported="true">
    <intent-filter android:priority="100">
        <action android:name="com.example.hp.broadcasttest.MY_BROADCAST"/>
    </intent-filter>
</receiver>

//动静注册,在代码中注册
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mIntentFilter = new IntentFilter();
    //增加播送想要监听的类型,监听网络状态是否发生变化
    mIntentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
    mNetworkChangeReceiver = new NetworkChangeReceiver();
    //注册播送
    registerReceiver(mNetworkChangeReceiver, mIntentFilter);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    //勾销注册播送接收器
    unregisterReceiver(mNetworkChangeReceiver);
}

//发送播送,同样通过Intent
Intent intent = new Intent("com.example.hp.broadcasttest.MY_BROADCAST");
//发送规范播送
sendBroadcast(intent);

//接管播送
public class MyBroadcastReceiver extends BroadcastReceiver {
    public MyBroadcastReceiver() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO: This method is called when the BroadcastReceiver is receiving
        // an Intent broadcast.
        Toast.makeText(context, "received", Toast.LENGTH_SHORT).show();
        //将这条播送截断
//        abortBroadcast();
    }
}

4. BroadcastReceiver,LocalBroadcastReceiver 区别
播送接收者:

(1)用于利用间的传递音讯
(2)因为跨利用,存在平安问题

本地播送接收者:

(1)播送数据在本利用范畴内流传。  
(2)不必放心别的利用伪造播送。  
(3)比发送全局播送更高效、平安。  
(4)无奈应用动态注册  

5. 在 manifest 和代码中如何注册和应用 BroadcastReceiver
(1)在AndroidManifest中动态注册,而后间接应用。
(2)代码中,通过registerReceiver来注册。
(3)注册发送后,在BroadcastReceiver(自定义一个接收器继承自BroadcastReceiver)的onReceive中接管播送并解决播送。

6. 播送引起 anr 的工夫限度
前台播送:BROADCAST_FG_TIMEOUT = 10s
后盾播送:BROADCAST_BG_TIMEOUT = 60s

Android入门教程视频参考


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:Android入门教程-广播机制-Broadcast

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址