Android静态注册的屏幕开启和屏幕关闭的广播捕捉不到的原因

今天进行了手机屏幕亮屏、暗屏、屏幕开锁、WIFI和移动网络状态改变、开机等广播的功能实现,其中遇到了一个问题,就是无论如何,屏幕亮屏、暗屏的广播都接收不到。这是因为我在AndroidManifest.xml采用了静态 注册的缘故。事实上,对应屏幕亮屏、暗屏的广播,必须通过代码动态注册 才可以获取到广播,这是系统做出的限制。下面贴出实例代码:

MainActivity.java类:

package com.diyidaima.selfstartaappdemo;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {
    ControllCenterReceiver controllCenterReceiver;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        controllCenterReceiver=new ControllCenterReceiver();
        registerScreenActionReceiver();
    }

    //屏幕亮屏广播和屏幕灭屏广播限制只能有register到代码中的receiver才能接收。
    private void registerScreenActionReceiver(){
        final IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        filter.addAction(Intent.ACTION_SCREEN_ON);
        registerReceiver(controllCenterReceiver, filter);
    }
}

ControllCenterReceiver.java广播实现类:

package com.diyidaima.selfstartaappdemo;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

public class ControllCenterReceiver extends BroadcastReceiver {
    public static String TAG = "ControllCenterReceiver";
    private NotificationManager mManager;
    private NotificationCompat.Builder mBuilder;

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "onReceive");
        String action = intent.getAction();

        if (Intent.ACTION_SCREEN_ON.equals(action)) { // 屏幕亮屏广播
            Log.d(TAG, "screen on");
            showNotification(context, "screen on");
        } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {// 屏幕灭屏广播
            Log.d(TAG, "screen off");
            showNotification(context, "screen off");
        } else if (Intent.ACTION_USER_PRESENT.equals(action)) { // 屏幕解锁广播
            Log.d(TAG, "screen unlock");
            showNotification(context, "screen unlock");
        } else if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
            // 当长按电源键弹出“关机”对话或者锁屏时系统会发出这个广播
            // example:有时候会用到系统对话框,权限可能很高,会覆盖在锁屏界面或者“关机”对话框之上,
            // 所以监听这个广播,当收到时就隐藏自己的对话,如点击pad右下角部分弹出的对话框
            Log.i(TAG, " receive Intent.ACTION_CLOSE_SYSTEM_DIALOGS");
            showNotification(context, "按电源键");
        } else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action) ||
                WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action) ||
                ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
            //监听wifi广播
            Log.d(TAG, "监听wifi广播");
            showNotification(context, "监听wifi广播");
        } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
            //开机广播
            Log.d(TAG, "开机广播");
            showNotification(context, "开机广播");
        }
    }

    private void showNotification(Context context, String beizhu) {
        mManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        mBuilder = new NotificationCompat.Builder(context);
        mBuilder.setContentTitle("设置通知栏标题 " + beizhu)//设置通知栏标题
                .setContentText("设置通知栏显示内容") //设置通知栏显示内容
                .setContentIntent(getDefalutIntent(context, PendingIntent.FLAG_ONE_SHOT)) //设置通知栏点击意图
                .setTicker("设置通知栏显示内容") //通知首次出现在通知栏,带上升动画效果的
                .setWhen(System.currentTimeMillis())//通知产生的时间,会在通知信息里显示,一般是系统获取到的时间
                .setPriority(Notification.PRIORITY_DEFAULT) //设置该通知优先级
                .setAutoCancel(true)//设置这个标志当用户单击面板就可以让通知将自动取消
                .setOngoing(false)//ture,设置他为一个正在进行的通知。他们通常是用来表示一个后台任务,用户积极参与(如播放音乐)或以某种方式正在等待,因此占用设备(如一个文件下载,同步操作,主动网络连接)
                .setDefaults(Notification.DEFAULT_VIBRATE)//向通知添加声音、闪灯和振动效果的最简单、最一致的方式是使用当前的用户默认设置,使用defaults属性,可以组合
                //Notification.DEFAULT_ALL  Notification.DEFAULT_SOUND 添加声音 // requires VIBRATE permission
                .setSmallIcon(R.mipmap.ic_launcher);//设置通知小ICON
        mManager.notify(0, mBuilder.build());
    }

    public PendingIntent getDefalutIntent(Context context, int flags) {
        Intent intent = new Intent(context, MainActivity.class);
        //注意问题:Context中有一个startActivity方法,Activity继承自Context,
        // 重载了startActivity方法。如果使用 Activity的startActivity方法,
        // 不会有任何限制,而如果使用Context的startActivity方法的话,
        // 就需要开启一个新的task,解决办法是,加一个flag,
        // 也就是这句intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);的作用。
        // 如果不添加这句,就会报android.util.AndroidRuntimeException
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        //intent.putExtra("content",""+content);
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, flags);
        return pendingIntent;
    }
}

AndroidManifest.xml文件,android7.0开始,广播需要权限:

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

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

        <receiver
            android:name=".ControllCenterReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter android:priority="1000">
                <!--监听wifi广播-->
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
                <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
                <action android:name="android.net.wifi.STATE_CHANGE" />
            </intent-filter>

            <!--<intent-filter android:priority="1000">-->
                <!--屏幕亮屏广播;限制只能有register到代码中的receiver才能接收-->
                <!--<action android:name="android.intent.action.SCREEN_ON" />-->
            <!--</intent-filter>-->

            <!--<intent-filter android:priority="1000">-->
                <!--屏幕灭屏广播;限制只能有register到代码中的receiver才能接收-->
                <!--<action android:name="android.intent.action.SCREEN_OFF" />-->
            <!--</intent-filter>-->

            <intent-filter android:priority="1000">
                <!--屏幕解锁广播-->
                <action android:name="android.intent.action.USER_PRESENT" />
            </intent-filter>

            <intent-filter android:priority="1000">
                <!--当长按电源键弹出“关机”对话或者锁屏时系统会发出这个广播-->
                <action android:name="android.intent.action.CLOSE_SYSTEM_DIALOGS" />
            </intent-filter>

            <intent-filter android:priority="1000">
                <!--开机接收广播-->
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <action android:name="android.media.AUDIO_BECOMING_NOISY" />
            </intent-filter>

        </receiver>
    </application>

</manifest>

发表回复

后才能评论