Android四大组件——BroadcastReceiver——动态注册和静态注册

广播的用处:

  1.实现了不同程序之间的数据传输与共享,因为只要是和发送广播的action相同的接受者都能接受这个广播。典型的应用就是android自带的短信,电话等等广播,只要我们实现了他们的action的广播,那么我们就能接收他们的数据了,以便做出一些处理。比如说拦截系统短信,拦截骚扰电话等等。

 2.起到了一个通知的作用,比如在service中要通知主程序,更新主程序的UI等。因为service是没有界面的,所以不能直接获得主程序中的控件,这样我们就只能在主程序中实现一个广播接受者专门用来接受service发过来的数据和通知了。

 

广播的分类:

  • 标准广播:是一种完全异步执行的广播,在广播发出之后,所有的BroadcastReceiver几乎会同一时间收到这条广播消息,因此她们之间没有先后顺序可言。这种广播的效率会比较高,但同时也意味着它是无法被截断的。

 

 

  

  • 有序广播:是一种同步执行的广播,在广播发出之后,同一时刻只会有一个BroadcastReceiver能够收到这条广播消息,当这个BroadcastReceiver中的逻辑执行完毕后,广播才会继续传递。所以此时的BroadcastReceiver是有先后顺序的,优先级高的BroadcastReceiver就可以先收到广播。并且前面的BroadcastReceiver还可以截断正在传递的广播,这样后面的BroadcastReceiver就无法收到广播了。

实战:

广播需要注册,分为静态注册和动态注册两种。

  • 静态注册:在AndroidManifest.xml中注册。
  • 动态注册:在代码中注册。

1.动态注册监听电量变化的广播(注意:电量变化不能静态注册)

 步骤:新建一个类,让它继承BroadcastReceiver,并重写父类的onReceive()方法就行了。这样当有广播到来时,onReceive()方法就会得到执行,具体的逻辑可在该方法中处理。

 

package com.java.androidstudy;

import androidx.appcompat.app.AppCompatActivity;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {
   private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //我们要收听的频道是:电量变化
        IntentFilter  intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);//电量变化,想监听什么广播,就添加相应的action
        //创建接收者
        BatteryLeveReceiver batteryLeveReceiver = new BatteryLeveReceiver();

        //动态注册广播
        this.registerReceiver(batteryLeveReceiver,intentFilter);
    }

    //第一步,创建一个广播接收者,继承自BroadcastReceiver
    private class BatteryLeveReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
            //在这里写接收到广播后的逻辑处理
            String action = intent.getAction();
            Log.d(TAG,"收到了电量变化的广播,action is ==>"+action);
        }
    }
}

 

监听电量变化的广播还需要打开权限:

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

 

 运行后,在模拟器上拖动电量:

 

 观察日志:

 

 在拖动电量变化时,成功监听到了该广播。

现在我们将电量变化显示出来:

修改代码如下:

    //第一步,创建一个广播接收者,继承自BroadcastReceiver
    private class BatteryLeveReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
            //在这里写接收到广播后的逻辑处理
            String action = intent.getAction();
            Log.d(TAG,"收到了电量变化的广播,action is ==>"+action);
            Log.d(TAG,"当前电量:"+intent.getIntExtra(BatteryManager.EXTRA_LEVEL,0));//获取电量,可戳进BatteryManager的源代码看看
        }
    }

拖动电量后观察日志:

 

 OK,已经成功获取了。

动态注册的BroadcastReceiver一定要取消注册才行,这里我们是在onDestroy()方法中通过调用unregisterReceiver()方法来实现的。代码如下:

//取消广播注册,否则会造成内存卡顿
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(batteryLeveReceiver);
}

 2.静态注册广播监听开机启动

动态注册的BroadcastReceiver可以自由控制注册和注销,但必须在程序启动之后才能接收广播,因为注册的逻辑是写在onCreate()中的。

静态注册的BroadcastReceiver可以在程序未启动的情况下也能接收广播。

在Android8.0以后,所有隐式广播都不允许使用静态注册的方式来接收了。隐式广播指的是那些没有指定具体发送给哪个应用程序的广播,大多数系统广播属于隐式广播。少数特殊的系统广播目前仍然允许使用静态注册的方式来接收。如开机广播。

步骤:新建BootCompleteReceiver类,使之继承BroadcastReceiver,代码如下:

 //第一步:新建BootCompleteReceiver类   
public class BootCompleteReceiver extends BroadcastReceiver {
    private static final String TAG="BootCompleteReceiver";
    @Override
    public void onReceive(Context context, Intent intent) {
        //第三步,收到开机广播后做的事情
        String action = intent.getAction();
        Log.d(TAG,"action is =="+action);
        Log.d(TAG,"开机完成");
        Toast.makeText(context,"收到开机完成的广播",Toast.LENGTH_SHORT).show();
        //静态注册,不需要启动程序也可以接收到广播,不需要取消注册。
    }
}

然后,我们需要在AndroidManifest.xml文件中<application>标签内进行开机广播的静态注册。

代码如下:

        <receiver android:name=".BootCompleteReceiver"
            android:enabled="true"
            android:exported="true">
            <!-- 第二步,静态注册action -->
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />  
            </intent-filter>
        </receiver>

此外,我们还需要打开开机广播的权限

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

现在运行程序后重启模拟器,日志截图如下:

 

 可以看到,已经成功获取到了开机的广播信息。

 

posted @ 2022-07-31 10:58  虞美人体重90  阅读(2007)  评论(0编辑  收藏  举报