zl程序教程

您现在的位置是:首页 >  APP

当前栏目

Android入门第48天-静态BroadCast之接受开机广播

2023-04-18 14:29:21 时间

简介

我们在之前的BroadCast章节中写了动态BroadCast。但我们提过一笔BroadCast也有静态之分,而静态的BroadCast主要用于监听一些如:开机广播、SIM卡拨出插入等广播。这些广播都为静态注册广播事件。因此我们今天就以一个App监听Android开机广播为例子说明静态广播的使用方法以及如何收听开机广播。

课程目标

  1. 进一步使用Android Stduio如何模拟开机、关机;
  2. 了解AVD的冷启动、快速启动模式;
  3. 静态广播的写法;
  4. 开机广播的处理以及相应的权限-permission;

网上几乎所有的例子都没有讲清这个开机广播,Android的开机广播事件叫“android.intent.action.BOOT_COMPLETED”,为了Receive它你必须在全局的AndroidManifest里加入至少以下两个Permission。

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

同时,你不能只是简单按下Android Studio模拟器里的这个按钮

开始课程

设计一个静态Receiver

我们设计一个自己的Receiver。

        <receiver
            android:name="org.mk.android.demoreceivebootcomplete.BootCompleteReceiver"
            android:enabled="true"
            android:exported="true"
            android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>

 把这段xml放置于AndroidManifest.xml文件中并且设置相应的uses:permission,全设完后的AndroidManifest.xml文件如下

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.READ_CONTACTS"/>
    <uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.DemoReceiveBootComplete"
        tools:targetApi="31">
        <receiver
            android:name="org.mk.android.demoreceivebootcomplete.BootCompleteReceiver"
            android:enabled="true"
            android:exported="true"
            android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>

        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <meta-data
                android:name="android.app.lib_name"
                android:value="" />
        </activity>
    </application>

</manifest>

此处和网上到处乱抄甚至机器翻译的混乱的知识库有3处区别:

  • 区别1:我们在uses:permission还要加入android.permission.WAKE_LOCK;
  • 区别2:在receiver中需要指定全包路径而不是.BootCompleteReceiver这样的简写;
  • 区别3:在receiver标签内还需要设android:permission;

下面来书写BootCompleteReceiver类

BootCompleteReceiver类

package org.mk.android.demoreceivebootcomplete;

import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.util.Log;
import android.view.WindowManager;

public class BootCompleteReceiver extends BroadcastReceiver {
    public final static String TAG="mytag";
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i(TAG,">>>>>>receive broadcast"+intent.getAction());

    }
}

非常简单,只要监听到了手机开机,它就会打印一条LOG。

activiti_main.xml

Android Studio在new->empty activity时默认的hello world

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity.java

Android Studio在new->empty activity时默认的hello world

package org.mk.android.demoreceivebootcomplete;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

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

如何运行看效果

网上又是一堆错的。

第一步操作:设置AVD高级模式

按照下图:

第二步操作:设置app开机模式为Cold boot模式

然后在下拉出的“Show Advanced Settings”里

把默认启动方式如果是“Quick boot”,那么请把它改成“Cold boot”。因为Quick boot是自动记录上一次手机的运行状态,它不能模拟真机的开关机。这个BOOT_COMPLETE事件就是在真正的关机开机时才发生的,举例来说,我长按着Android手机的顶部按钮10秒后卡断电源这样的关机后再开机才能触发这个BOOT_COMPLETE事件,而且只能触发一次。

 如果只是短按一下手机顶部按钮->黑屏->再短按一下手机顶部按钮->亮屏,这种叫Quick boot,这种是不能触发BOOT_COMPLETE事件的。

因此网上的教程都没有说透这一个点,导致我们的初学者不知道配了多少个uses:permission、试了无数次就是无法触发这个BOOT_COMPLETE事件并浪费了大量的时间只为了触发一下这个事件的效果。

第三步操作:在AVD“已启动”模式下进行强制关机开机

你可以先把应用连同AVD先启动起来如下图,以下这样的状态就是AVD已启动模式。

用鼠标长按“开关”按钮直到出现以下第二个界面

点Restart按钮,出现以下界面

然后你要等一会,大概在15-30秒不等,然后你会得到这样的界面

最后在这个过渡界面再过2-3秒后,Android充分开机后你就可以收到以下这条消息了。

这就是Android真正的“开机收到开机广播”,网上教程统统没说清。每次你要触发这个“开机”事件,你可以每次在AVD已启动情况下点【Restart】按钮,这样才能每次触发和验证你要在开机事件被你安装在手机的APP监听到时才要去做的一些事

请自己动一下手吧。