You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

目标SDK26的自动回复应用:重启锁屏后SMS广播接收器失效求助

解决重启后锁屏状态下SMS广播接收器失效的问题

嘿,针对你遇到的这个重启后锁屏(Direct Boot模式)下两个SMS广播接收器都不工作的问题,结合SDK26的Android特性,我整理了几个关键修复点,应该能帮你搞定:

1. 先搞懂动态注册接收器的坑

你通过registerPhoneStateReceiver()动态注册的DynamicPhoneStateReceiver,只有在应用进程运行起来之后才会生效。设备重启后,锁屏状态下应用还没启动,这个动态接收器完全处于“未激活”状态,自然收不到任何广播。

怎么破?

  • 把BOOT_COMPLETED广播的接收逻辑移到**静态注册的PhoneStateReceiver**里——静态接收器是可以在Direct Boot模式下被系统唤醒的,不受应用是否启动的限制。
  • 等静态接收器收到BOOT_COMPLETED后,启动一个标记了directBootAware=true的后台服务,在服务里面完成动态接收器的注册操作。

2. 完善静态接收器的配置和权限

调整AndroidManifest.xml

给静态接收器加上BOOT_COMPLETED的intent-filter,同时确保所有要在Direct Boot下工作的组件都正确标记directBootAware="true":

<receiver android:name="com.lemi.callsautoresponder.callreceiver.PhoneStateReceiver" 
          android:directBootAware="true" 
          android:enabled="true" 
          android:exported="true">
    <!-- 保留原有SMS相关的action,新增BOOT_COMPLETED -->
    <intent-filter android:priority="2147483647">
        <action android:name="android.intent.action.PHONE_STATE"/>
        <action android:name="android.provider.Telephony.SMS_DELIVER"/>
        <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
    <!-- 保留其他原有的intent-filter -->
</receiver>

<!-- 新增一个支持Direct Boot的服务,用来注册动态接收器 -->
<service android:name=".DirectBootInitService"
         android:directBootAware="true"
         android:exported="false"/>

补加BOOT_COMPLETED权限

别忘了在AndroidManifest里加上RECEIVE_BOOT_COMPLETED权限,不然收不到开机广播:

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

3. 实现Direct Boot初始化服务

创建DirectBootInitService类,在服务启动的时候完成动态接收器的注册:

public class DirectBootInitService extends Service {
    private static final String TAG = "DirectBootInitService";
    private DynamicPhoneStateReceiver _phoneReceiver;

    @Override
    public void onCreate() {
        super.onCreate();
        // 在这里注册动态接收器
        registerDynamicReceivers();
    }

    private void registerDynamicReceivers() {
        Log.i(TAG, "在Direct Boot模式下注册动态接收器");
        _phoneReceiver = new DynamicPhoneStateReceiver();
        
        // 注册电话状态变化的广播
        IntentFilter intentFilter1 = new IntentFilter();
        intentFilter1.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
        intentFilter1.setPriority(0x7fffffff);
        registerReceiver(_phoneReceiver, intentFilter1);

        // 注册SMS_RECEIVED广播,带上权限验证
        IntentFilter intentFilter2 = new IntentFilter(Telephony.SMS_RECEIVED);
        intentFilter2.setPriority(0x7fffffff);
        registerReceiver(_phoneReceiver, intentFilter2, Manifest.permission.BROADCAST_SMS, null);

        // 注册GSM_SMS_RECEIVED广播
        IntentFilter intentFilter3 = new IntentFilter(Telephony.GSM_SMS_RECEIVED);
        intentFilter3.setPriority(0x7fffffff);
        registerReceiver(_phoneReceiver, intentFilter3, Manifest.permission.BROADCAST_SMS, null);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // 让服务保持存活(如果怕被系统杀死,可以改成前台服务)
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // 注销接收器,避免内存泄漏
        if (_phoneReceiver != null) {
            unregisterReceiver(_phoneReceiver);
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

4. 修改静态接收器的onReceive方法

在PhoneStateReceiver里处理BOOT_COMPLETED广播,启动我们刚才创建的初始化服务:

public class PhoneStateReceiver extends BroadcastReceiver {
    private static final String TAG = "PhoneStateReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
            Log.i(TAG, "收到开机广播,启动DirectBoot初始化服务");
            // 获取Direct Boot模式下的上下文,确保服务能在锁屏状态启动
            Context directBootContext = context.createDeviceProtectedStorageContext();
            Intent serviceIntent = new Intent(directBootContext, DirectBootInitService.class);
            directBootContext.startForegroundService(serviceIntent);
        } else if (Telephony.SMS_DELIVER.equals(action) || Telephony.SMS_RECEIVED.equals(action)) {
            Log.i(TAG, "静态接收器收到SMS广播");
            // 在这里处理SMS逻辑,或者转发给动态接收器处理
        }
    }
}

几个关键细节要注意

  • Direct Boot上下文:必须用createDeviceProtectedStorageContext()获取设备保护存储的上下文,这样服务才能在锁屏状态下正常启动,不受用户数据锁的限制。
  • SMS广播的区别:SMS_DELIVER是系统发给默认短信应用的显式广播,静态注册就能在Direct Boot下接收;而SMS_RECEIVED是隐式广播,Android O及以上版本静态注册收不到,必须动态注册。
  • 服务存活问题:如果你的应用在后台容易被系统回收,可以把DirectBootInitService改成前台服务(弹出一个通知),避免被系统杀死。

内容的提问来源于stack exchange,提问作者M.Gin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:42:24