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

Android 8及以上开机后Broadcast Receiver失效及通话广播问题求助

兄弟,这个问题我太熟了——Android 8.0(API 26)引入的后台执行限制就是元凶!

为什么旧版正常,Android 8+就不行了?

从Android O开始,谷歌为了砍后台耗电,对隐式广播下了狠手。NEW_OUTGOING_CALL刚好属于被限制的隐式广播范畴,不在系统允许的例外列表里。这就导致:

  • 你在Manifest里注册的静态BroadcastReceiver,只有当应用处于前台状态或者持有前台服务时,才能收到广播
  • 设备重启后,应用没启动,静态接收器直接躺平,完全收不到任何广播
  • 应用启动后能工作几小时,只是因为那段时间应用进程还活着,系统暂时放行,等进程被回收就彻底失效了
怎么解决?给你三个靠谱方案

方案1:改用动态注册BroadcastReceiver

把接收器从Manifest里移出来,在应用启动时(比如主Activity的onCreate,或者Application的onCreate)动态注册。只要应用进程活着,就能正常监听。

示例代码:

// 定义接收器
private BroadcastReceiver outgoingCallReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        // 这里处理你的通话记录逻辑
        String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
        // 比如存到数据库或者上传服务器...
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    
    // 动态注册
    IntentFilter filter = new IntentFilter(Intent.ACTION_NEW_OUTGOING_CALL);
    registerReceiver(outgoingCallReceiver, filter);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    // 一定要注销,不然会内存泄漏!
    unregisterReceiver(outgoingCallReceiver);
}

缺点:如果应用进程被系统杀死,接收器就失效了,适合对后台持续监听要求不高的场景。

方案2:用前台服务保活+动态注册

如果需要后台持续监听,就得搞个前台服务——前台服务的进程优先级高,系统不会轻易杀它。

步骤很简单:

  1. 写个前台服务,在服务里动态注册接收器
  2. 服务启动时显示一个低优先级通知(Android O+强制要求)
  3. 让服务能在应用启动时自动启动(比如用户打开APP后启动,或者通过BOOT_COMPLETED广播,但Android O+需要先唤醒应用一次)

示例服务代码片段:

public class CallMonitorService extends Service {
    private BroadcastReceiver callReceiver;

    @Override
    public void onCreate() {
        super.onCreate();
        // 注册接收器
        callReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                // 处理通话逻辑
            }
        };
        IntentFilter filter = new IntentFilter(Intent.ACTION_NEW_OUTGOING_CALL);
        registerReceiver(callReceiver, filter);
        
        // Android O+必须启动前台服务,显示通知
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // 创建通知渠道
            NotificationChannel channel = new NotificationChannel("call_monitor", "通话监控", NotificationManager.IMPORTANCE_LOW);
            NotificationManager manager = getSystemService(NotificationManager.class);
            manager.createNotificationChannel(channel);
            
            // 构建通知
            Notification notification = new NotificationCompat.Builder(this, "call_monitor")
                    .setContentTitle("通话监控中")
                    .setSmallIcon(R.drawable.ic_notify)
                    .build();
            startForeground(1, notification);
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_STICKY; // 服务被杀死后,系统会尝试重启
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(callReceiver);
    }

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

然后在Manifest里注册服务(Android 12+要加前台服务类型):

<service android:name=".CallMonitorService"
         android:foregroundServiceType="phoneCall" />

缺点:会在通知栏显示一个常驻通知,要提前跟用户说明用途,避免被当成流氓APP。

方案3:AccessibilityService(适合特殊场景)

如果用户能接受开启辅助权限,用辅助功能服务也是个好办法——AccessibilityService的进程优先级极高,几乎不会被系统杀死。不过这个需要用户手动去设置里开启权限,适合对后台监听要求极高的场景。

最后提醒
  • 动态注册的接收器一定要在合适的时机注销,别搞内存泄漏
  • 前台服务的通知尽量做的低调点,比如用低重要性,避免打扰用户
  • Android 12+以上,前台服务必须指定对应的foregroundServiceType,不然会报错

内容的提问来源于stack exchange,提问作者Varun

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:16:17