Android开发Android开发经验谈Android技术知识

AndroidAZ系列:四大组件之Broadcast(All,F

2019-11-06  本文已影响0人  道阻且长_行则将至

Git仓库地址

配套四维导图地址

AndroidAZ系列有以下目的:

  1. Android程序猿的面试(初级,中级,高级,资深),拿到满意的offer。
  2. Android程序猿学习进阶。

标记说明:因为笔者是列出所有的Android知识点,因此面试不需要看那么多内容,如果是面试的知识点。笔者会加上标记Face,而如果不是面试的知识点,笔者会加上No标记,它是要学的东西;然后笔者将Android面试者或者面试者分为4个等级,初级A1,中级A2,高级A3,资深A4,如果这个知识点是所有等级的范围,那么笔者将会以all标记上。因此进阶路线就是A1->A2->A3->A4。也是面试者挑选的复习范围,假如你是中级程序员,那么你面试要看的内容就是包含A2&Face的标记。

1.广播是什么

在Android中,Broadcast是一种广泛运用的在应用程序之间传输信息的机制。

2.广播的种类

2.1 无序广播(普通广播)

普通广播是完全异步的,通过ContextSendBroadcast()函数来发送,消息传递的效率比较高,但所有的receivers(接收器)的执行顺序不确定,缺点是:接收者不能将处理结果传递给下一个接收者,并且无法终止广播Intent的传播,直到没有与之匹配的的广播接收器为止。

使用方法:

首先继承BroadcastReceiver,然后需要重写onReceiver()方法,这样我们就实现了一个接收器。

public class MyBroadcastReceiver extends BroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "hello", Toast.LENGTH_SHORT).show();
    }
}

2.2 有序广播

有序广播是一种同步执行的广播,在广播发出后,同一时刻只会有一个广播接收器能够收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传递. 有先后顺序,前面的广播能够截断正在传递的广播.

有序广播通过Context.sendOrderdBroadcast()来发送,所有的广播按照优先级顺序依次进行,广播接收器的 优先级通过receiver的intent-filter中的priority属性来设置,数组越大优先级越高(最大为最大数),当广播接收器结收到广播后可以使用setResult()函数来将结果传递给下一个接收器接收,然后通过getResult来获取上 一个接收器的返回的结果,并可以用abortBroadcast()函数来让系统丢弃该广播,该广播不在传递到别的广播接收器接收。

首先我们注册两个广播接收器

public class MyBroadcastReceiver extends BroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent) {
        int i=1;
        Toast.makeText(context, i+"", Toast.LENGTH_SHORT).show();
        Bundle bundle=new Bundle();
        bundle.putInt("I",i);
        setResult(1,i+"",bundle);
    }
}
public class MyBroadcastReceiver2 extends BroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle resultExtras = getResultExtras(true);
        int i = resultExtras.getInt("I");
        Toast.makeText(context, i+1+"", Toast.LENGTH_SHORT).show();
    }
}

并在androidManifest中注册并设置两个广播接收器的优先级

<receiver android:name=".MyBroadcastReceiver">
    <intent-filter android:priority="10">
        <action android:name="hello"></action>
    </intent-filter>
</receiver>
<receiver android:name=".MyBroadcastReceiver2">
    <intent-filter android:priority="1">
        <action android:name="hello"></action>
    </intent-filter>
</receiver>

然后发送一条有序广播,第二个参数是权限相关的字符串,可以传入null。

sendOrderedBroadcast(new Intent("hello"),null);

这时Toast分别弹出的是1和2,说明我们获取到了上一个广播接收器的结果,当然我们也能通过给优先级较高的接收器设置截断广播

abortBroadcast();

这样,之后的广播接收器都不会再接收到广播了。

2.3 本地广播

前面的两种广播都是全局广播,这样的广播可以被任意应用程序接收,并且我们也能接收到来自其他应用程序的广播,这样很容易引起安全问题,android为了解决这个问题引入了本地广播。,使用这个机制发送的广播只能在本应用程序内部进行传递,并且广播接收器也只能接收本应用程序的广播,这样所有的安全问题就不存在了。

首先先获取本地广播实例,并发送一条异步广播

localBroadcastManager=LocalBroadcastManager.getInstance(this);
localBroadcastManager.sendBroadcast(new Intent("hello1"));

然后通过本地广播接收者接收本地广播

private BroadcastReceiver register=new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "hello1", Toast.LENGTH_SHORT).show();
    }
};

localBroadcastManager.registerReceiver(register,new IntentFilter("hello1"));

最后在onDestory中注销本地广播接收者,避免oom。

@Override
protected void onDestroy() {
    super.onDestroy();
    unregisterReceiver(register);
}

2.4 黏性广播(Android5.0 Api21失效)

sticky广播通过Context。sendStickyBroadcast()函数来发送,用此函数发送的广播会一直滞留,当有与之匹配的 广播接收器接被注册后,该广播接收器就会接收到广播,当然sticky广播需要下面权限。

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

sticky只保留最后一条广播,并且一直保留下去,这样即使有广播接收器处理了该广播,当有再与之匹配的广播接收器接收时,此广播任会被接收,如果你只想处理一次广播,可以通过removeStickyBroadcast()函数实现。

3.广播接收器

3.1 静态注册

四大组件都需要在Androidmanifest中进行注册

<receiver android:name=".MyBroadcastReceiver">
    <intent-filter>
        <action android:name="hello"></action>
    </intent-filter>
</receiver>

3.2 动态注册

registerReceiver(new MyBroadcastReceiver(),new IntentFilter("hello"));

如果是动态注册的,别忘了在onDestory()中注销广播

@Override
protected void onDestroy() {
    super.onDestroy();
    unregisterReceiver(new MyBroadcastReceiver());
}

现在我们能给发送一条广播了

sendBroadcast(new Intent("hello"));

当我们发送一条广播是会弹出一条Toast,说明广播接收器接收到了。

3.3 静态注册和动态注册的区别

3.4 系统发送的广播有哪些

常见系统广播

打电话

 <intent-filter >
                <action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
 </intent-filter>

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

接电话

<intent-filter >
                <action android:name="android.intent.action.PHONE_STATE"/>
 </intent-filter>

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

开机

<intent-filter >
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>

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

安装包相关

<intent-filter >
                <action android:name="android.intent.action.PACKAGE_ADDED"/>
                <action android:name="android.intent.action.PACKAGE_REMOVED"/>
                //注意这个是必须的
                <data android:scheme="package"/>
</intent-filter>

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

接收短信

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

<uses-permission android:name="android.permission.RECEIVE_SMS"/>
public class BootReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        Object[] object = (Object[]) intent.getExtras().get("pdus");
        for (Object obj : object) {
            SmsMessage ss = SmsMessage.createFromPdu((byte[]) obj);
            String messageBody = ss.getMessageBody();
            String originatingAddress = ss.getDisplayOriginatingAddress();

            System.out.println(messageBody+":"+originatingAddress);
        }
    }
}

屏幕的锁屏和解锁(只能动态注册)

receiver = new BootReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.SCREEN_OFF");
filter.addAction("android.intent.action.SCREEN_ON");
registerReceiver(receiver, filter);

unregisterReceiver(receiver);

下面5个系统广播只能动态注册而不支持静态注册

android.intent.action.SCREEN_ON
android.intent.action.SCREEN_OFF
android.intent.action.BATTERY_CHANGED
android.intent.action.CONFIGURATION_CHANGED
android.intent.action.TIME_TICK

4.源码角度分析广播机制

参考链接

上一篇 下一篇

猜你喜欢

热点阅读