广播和Service唤醒被杀死的android app

本文深入探讨了Android系统中广播唤醒与服务唤醒机制的区别、原理及应用,包括静态广播、自定义广播、广播唤醒的缺陷、Service唤醒的可靠性等核心内容。详细解释了如何在不同场景下使用广播和Service来唤醒处于休眠状态的应用程序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 静态广播唤醒

广播的exported属性和enabled属性

  1. exported默认为true表示这个广播可以接收来自其他app发送的广播,只要条件满足,exported设置成false表示只能是这个app内发送的广播才能接收,即使是receiver的进程和发送广播的进程不是同一个,但是只要都是属于一个app的就可以正常接收,有时候会遇到发送者和接收者不在一个进程,广播没办法正常接收,这是因为receiver所在的进程是死的,如果通过某种方式把receiver所在的进程唤醒,那么即使exported为false也能正常接收
  2. enabled为true表示广播可用,为false表示禁用广播,禁用后广播将无法接收

静态的系统广播

静态的系统广播,例如:开机广播,用户开屏广播,USB插入和拔出广播等这类广播在app运行期间可以用静态注册的广播正常接收,但是在app被杀死后就无法收到了,android系统做了屏蔽,把被杀死的app的系统静态广播都过滤了,所以想让app被杀死后仍然通过静态注册的广播接收系统广播是做不到的

自定义广播

我们一般发广播都是局限在app内部,所以通常都是这么发的:

Intent intent = new Intent();
intent.setAction("my.broadcast.test");
sendBroadcast(intent);

或者这么发:

Intent intent = new Intent(context, TestBroadcastReceiver.class);
sendBroadcast(intent);

上面这两种广播的发送方式在app被杀死后都无法收到广播

但是采用下面这种方式发送广播即使app被杀死后,静态广播也能正常收到:
发送广播方的app,包名:com.syncpush.demo

Intent intent = new Intent();
            Context c = null;
            try {
                c = createPackageContext("com.example.broadcasttest", Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
            }
//            intent.setPackage(getPackageName());
//            intent.setComponent(pkgName, className);
//            intent.setComponent(pkgNameContext, className);
            intent.setClassName(c, "com.example.broadcasttest.TestBroadcastReceiver");
//            intent.setClassName("com.example.broadcasttest", "com.example.broadcasttest.TestBroadcastReceiver");
            intent.setAction("my.broadcast.test");
            intent.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
            sendBroadcast(intent);

intent.setClassName(“com.example.broadcasttest”, “com.example.broadcasttest.TestBroadcastReceiver”)声明接收的广播或者用intent.setClassName(c, “com.example.broadcasttest.TestBroadcastReceiver”),但是这个Context是接收广播方app的Context,所以通过createPackageContext(“com.example.broadcasttest”, Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY)根据包名来获取到app的Context

接收广播方的app,包名com.example.broadcasttest

public class TestBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Toast.makeText(context, "action:" + action, Toast.LENGTH_LONG).show();
        Log.i("TestBroadcastReceiver", "action:" + action);
    }
}

// 配置文件
<receiver android:name="com.example.broadcasttest.TestBroadcastReceiver"
            android:exported="true"
            android:enabled="true">
            <intent-filter>
                <action android:name="android.intent.action.USER_PRESENT" /> <!-- 手机开屏广播 -->
            </intent-filter>

            <intent-filter>
                <action android:name="my.broadcast.test" /> <!-- 自定义广播 -->
            </intent-filter>
        </receiver>

接收放广播的配置要把exported设置成true,否则就无法收到app以外的广播发送,只能收到app内部的广播发送

广播唤醒的缺陷

以上通过广播唤醒在一些手机上可以正常唤醒app,例如小米3;但是在魅族手机上就没办法唤醒了,需要到安全中心把app的自启动权限开启后才能正常唤醒,由此可见,一些手机厂商可能对于静态广播的接收做了一些优化导致静态广播还是没办法被接收,所以会唤醒失败

关于intent.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)

这个网上说是设置了就能保证即使app被杀死后,也能正常接收广播,但是我在小米手机上测了下,没有用,即使没设置,但是采用intent.setClassName()后,app杀死后也能正常接收广播,后来怀疑是不是默认就是Intent.FLAG_INCLUDE_STOPPED_PACKAGES,于是就intent.setFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES),意思是app被杀死后就不接收广播,但是广播照样能正常接收,所以跟intent.setFlags()貌似没关系,但是小米手机系统是定制的,我不敢保证他们是不是对这方面做了修改,目前没有在原生的android系统上试过intent.setFlags()的有效性

2. Service唤醒

service唤醒我认为是最可靠的,在有些软件或者手机上(华为)有禁止app唤醒的选项,如果用户把这个开关打开,那么service唤醒也会失效,除了这个,目前都可以正常通过service唤醒

所谓service唤醒无非就是通过Intent来startService,但是需要指定packageName,否则会在你当前的app进程启动新的service,而不会启动另一个app里面的service,示例代码如下:

Intent serviceIntent = new Intent();
        serviceIntent.setComponent(new ComponentName(componentPckName, serviceName));
        serviceIntent.setPackage(context.getPackageName());
        serviceIntent.setAction("action");
        context.startService(serviceIntent);
Android 中,如果应用程序被杀死,定时任务将停止。但是,你可以使用 Android 的 AlarmManager 类来实现即使在应用程序被杀死时也能够调度定时任务的功能。 使用 AlarmManager,你可以指定一个时间,以及要执行的任务。当指定的时间到达时,系统会向你的应用程序发送一个广播,以便启动指定的任务。在接收到广播时,你的应用程序可以执行需要执行的操作,如发送通知或启动服务。 以下是一个简单的示例代码,演示如何使用AlarmManager来运行定时任务: ``` AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(this, YourBroadcastReceiver.class); PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0); // 设置每 10 分钟执行一次任务 alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 10 * 60 * 1000, pendingIntent); ``` 在这个示例中,我们使用AlarmManager的setRepeating()方法来设置一个重复的定时任务。该方法采用四个参数: - 第一个参数指定闹钟类型,这里使用RTC_WAKEUP表示在指定的时间唤醒设备。 - 第二个参数指定任务应该在何时开始执行,这里我们使用System.currentTimeMillis()来指定当前时间。 - 第三个参数是指定任务将在多长时间内执行一次,这里我们设置为每10分钟执行一次。 - 最后一个参数是一个PendingIntent,它指定要执行的任务。 当你的应用程序被杀死时,Android 系统会保持 AlarmManager 的定时任务运行,直到指定的时间到达。一旦指定的时间到达,系统会启动你的应用程序并发送一个广播,以便你的应用程序可以执行指定的任务。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值