如何修复Android中的BOOT_COMPLETED无法工作

72

我知道已经有数百个这样的问题被问过了,但我一直在查看它们,却仍然找不到任何解决方案。

我看到这个回答“Android应用程序关闭后无法接收到BOOT_COMPLETED广播”说,在Android 3.1版本之后,除非用户先启动你的应用程序,否则不会向应用程序发送BOOT_COMPLETED广播,但我仍然看到一些应用程序正在执行此操作,所以肯定有一种方法。我真的需要处理它,否则我也反对不经过用户交互就做任何事情。

这是我的AndroidManifest:

<manifest ... >

<!-- to be activated service on boot is completed -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- Keeps the processor from sleeping when a message is received. -->
<uses-permission android:name="android.permission.WAKE_LOCK" />

<application ... >
    <!-- to receive data when boot completed -->
    <receiver
        android:name="myPackage.BootReceiver"
        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>
</application>
</manifest>

编辑:我的广播接收器没什么好看的,但是如果有需要的话,这里是它:

package myPackage
public class BootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
    Utils.LogI("BootReceiver", "BootReceiver received!");
    if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
        // Do my stuff
    }
}
}

你用什么设备进行测试?如果是HTC - http://stackoverflow.com/questions/10411731/how-to-get-boot-complete-intent-in-htc-when-i-use-poweroff-for-reboot - JiTHiN
9个回答

91
这个下面的东西对我有用

AndroidManifest.xml

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

<application>    

    <receiver android:name=".BootCompletedReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <action android:name="android.intent.action.QUICKBOOT_POWERON" />
        </intent-filter>
    </receiver>

    <service android:name="NotifyingDailyService" />

BootCompletedReceiver.class

public class BootCompletedReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent arg1) {
        // TODO Auto-generated method stub
        Log.w("boot_broadcast_poc", "starting service...");
        context.startService(new Intent(context, NotifyingDailyService.class));
    }
}

Service.class

public class NotifyingDailyService extends Service {

    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public int onStartCommand(Intent pIntent, int flags, int startId) {
        // TODO Auto-generated method stub
        Toast.makeText(this, "NotifyingDailyService", Toast.LENGTH_LONG).show();
        Log.i("com.example.bootbroadcastpoc","NotifyingDailyService");
    
        return super.onStartCommand(pIntent, flags, startId);
    }
}

2
@KarueBensonKarue 你需要在安装应用后至少打开一次它。否则,你可能会意外地“强制停止”它,从而阻止接收广播。 - stdout
3
这个不再适用了 https://dev59.com/rWQm5IYBdhLWcg3w8Sne#19856367 (3.1+) - Androiderson
3
我查看了你提供的链接,也许你对它有误解。那是一个应用程序的停止状态,而不是活动状态。当应用程序首次安装但尚未启动以及由用户手动停止(在“管理应用程序”中)时,应用程序处于停止状态。这意味着用户应该在安装后至少启动一次应用程序来激活它,然后该应用程序才能像正常情况下一样接收所有隐式广播。 - Phong Nguyen
3
当您使用目标Android SDK 27及以上版本构建Android时,它将无法正常工作。 - sonida
1
在 intent-filter 中添加 <category android:name="android.intent.category.DEFAULT" /> 后,对我起作用了。 - William Magno

59

虽然这是一个老旧而基础的问题,但许多Android开发人员仍然困惑于此,因为他们没有仔细阅读文档

我看到有人分享了一些链接,并说:“这不再起作用了”,这完全错误误解

关于这个问题:“我看到这个答案说BOOT_COMPLETED除非用户首先启动您的应用程序,在Android版本3.1之后才会发送给应用程序”,请阅读以下这些行(来自官方文档:https://developer.android.com/about/versions/android-3.1.html#launchcontrols)以正确理解:

  • 请注意,应用程序的停止状态Activity的停止状态不同。系统分别管理这两种已停止状态。

  • 当应用程序首次安装但尚未启动以及由用户手动停止(在管理应用程序中)时,应用程序处于停止状态。 (他们指的是强制停止应用)

enter image description here

  1. 这意味着用户应该在安装后至少启动一次应用程序以激活应用程序,然后应用程序可以像通常一样接收来自操作系统的隐式广播。(仅需启动一次即可!

  2. “如果有任何一个应用程序被安装但从来没有打开过哪怕只有一次?”是的,那是垃圾邮件和欺诈应用程序,这种技术可以帮助用户防止这种情况发生!

此外,在现在(Android Oreo 8.0)之前,当Android在清单中限制注册隐式广播时(https://developer.android.com/about/versions/oreo/background.html#broadcasts),仍然有几个广播当前免于这些限制。 并且BOOT_COMPLETED是他们提到的第一个https://developer.android.com/guide/components/broadcast-exceptions.html

顺便说一下,这是我为这个问题找到的最好的解决方案:

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

<receiver android:name=".BootReceiver" android:enabled="true" android:exported="true">
            <intent-filter>
                <category android:name="android.intent.category.DEFAULT"/>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
                <action android:name="android.intent.action.QUICKBOOT_POWERON"/>
                <!--For HTC devices-->
                <action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
            </intent-filter>
        </receiver>

最后,请仔细阅读文档并三思而后行编写代码 :3!


1
但是,OnePlus设备上的BOOT完成操作无法正常工作,您有任何替代方法吗? - Feroz Siddiqui
2
我已经在Orio中进行了测试,但不起作用。非常有信息量,谢谢。 - Naga
1
在小米和一加手机上测试了,发现它无法正常工作,已经进行了双重检查。 - Feroz Siddiqui
2
这与电池优化有关。如果您将应用程序从电池优化中移除,它将正常运行。 - Feroz Siddiqui
1
这应该是被接受的答案。它在我的三星M20和运行Android 10的模拟器上都有效。 - SATYAJEET RANJAN
显示剩余6条评论

10

一些新的平板电脑和Android设备默认带有安全应用程序。有时,这些应用会阻止您的自启动模式。这些安全应用的一个例子是MyAsus管理器。在这种情况下,用户需要在应用程序管理器中添加“允许自启动”以便所有想要接收此BOOT_COMPLETED的应用程序。


可以通过编程实现这个吗? - leodev
3
华为手机也发生了同样的情况,即 BOOT_COMPLETED 没有触发。若要让其触发,您作为用户应前往“设置”->“应用”->“应用启动”->关闭所需应用程序。 - Aleksandr Urzhumtcev

9
对于Htc设备,需要添加com.htc.intent.action.QUICKBOOT_POWERON
    <receiver android:enabled="true" android:name=".receivers.BootUpReceiver">
        <intent-filter>
            <category android:name="android.intent.category.DEFAULT" />
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
            <action android:name="android.intent.action.QUICKBOOT_POWERON"/>
            <action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
         </intent-filter>
    </receiver>

8

对于仍然遇到此问题的其他人,如果您正在调试具有启动锁定(PIN、模式或其他)的设备,则需要订阅android.intent.action.LOCKED_BOOT_COMPLETED,如下所示:

<receiver
    android:directBootAware="true"
    android:name=".BootCompletedReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT" />
        <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
        <action android:name="android.intent.action.QUICKBOOT_POWERON" />
    </intent-filter>
</receiver>

您可以在以下链接找到文档:https://developer.android.com/training/articles/direct-boot


6

问题出在设备上。有些设备只允许内部应用程序接收此操作(例如:Android 5.1)。

您可以将此操作添加到您的意图过滤器中以解决问题。

操作 android:name="android.intent.action.USER_PRESENT"

这将在用户解锁设备后触发。


1

0

如果你看到这篇答案,而其他答案似乎都不起作用,请仔细检查清单中的操作字符串。如果在action标签中写入了错误的字符串,AndroidStudio不会显示任何错误。不要将代码中的常量名称ACTION_BOOT_COMPLETED与该常量的混淆,该值是在清单中使用的,等于android.intent.action.BOOT_COMPLETED

简而言之,请检查您的清单是否包含以下内容:

<intent-filter>  
    <action android:name="android.intent.action.BOOT_COMPLETED" />  
</intent-filter>  

而不是这个:

<intent-filter>  
    <action android:name="android.intent.action.ACTION_BOOT_COMPLETED" />  
</intent-filter>  

-2

针对此问题,您需要创建一个NotificationListener服务的解决方法。

如果设备版本是 >= Build.VERSION_CODES.JELLY_BEAN_MR2,并且具有像华为设备中的电池优化选项,则必须请求NotificationListener权限并按照以下代码创建NotificationListener服务,然后您将在接收器中获得BOOT_COMPLETED。

清单接收器:

    <receiver
                android:name=".TestRes"
                android:enabled="true"
                android:exported="true">
                <intent-filter android:priority="1">
                    <category android:name="android.intent.category.DEFAULT"/>
                    <action android:name="android.intent.action.BOOT_COMPLETED"/>
                    <action android:name="android.intent.action.QUICKBOOT_POWERON"/>
                    <action android:name="android.intent.action.USER_PRESENT"/>
                    <action android:name="android.intent.action.REBOOT"/>
                </intent-filter>
 </receiver>

1 创建一个 NotificationListener 服务:

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public class DevAppNotificationListener extends NotificationListenerService {

    @Override
    public void onNotificationPosted(StatusBarNotification sbn) {
//        super.onNotificationPosted(sbn);
    }

    @Override
    public void onNotificationRemoved(StatusBarNotification sbn) {
   //     super.onNotificationRemoved(sbn);
    }


}

2 检查 NotificationListener 是否已授权:

static boolean CheckNotificationLisPermission(Context context)
    {

        return NotificationManagerCompat.getEnabledListenerPackages (context).contains(context.getApplicationContext().getPackageName());

    }

如果没有,则请求NotificationListener权限:

 Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
            context.startActivityForResult(intent, callBackResultIntent);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接