简体   繁体   English

BOOT_COMPLETED 无法正常工作

[英]BOOT_COMPLETED not working Android

First of all, i know there has been hundreds of this kind of question asked, but i've been checking them all for a while and still couldn't find any solution.首先,我知道已经问了数百个这样的问题,但是我已经检查了一段时间,仍然找不到任何解决方案。

I've seen this answer said BOOT_COMPLETED not send to application unless user launch your application first, after Android version 3.1 But i still see some applications are doing that, there must be a way.我已经看到这个答案说 BOOT_COMPLETED 不会发送到应用程序,除非用户首先启动您的应用程序,在 Android 版本 3.1 之后但我仍然看到一些应用程序正在这样做,必须有办法。 I really need to handle it, otherwise i'm also against to do something without user's interaction.我真的需要处理它,否则我也反对在没有用户交互的情况下做某事。

So here's my AndroidManifest:所以这是我的 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>

Thanks in advance.提前致谢。

Edit: There is no much thing to see in my broadcastreceiver but to whom required here it is:编辑:在我的广播接收器中没有什么可看的,但这里需要的是:

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
    }
}
}

This below thing worked for me下面这件事对我有用

AndroidManifest.xml 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" >
    </service>

BootCompletedReceiver.class 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);
}
}

This is an old and basic question but a lot of Android developers now still confused about this trouble, because THEY DON'T TAKE TIME TO READ THE DOCS CAREFULLY这是一个古老而基本的问题,但许多 Android 开发人员现在仍然对这个问题感到困惑,因为他们没有花时间仔细阅读文档

I saw someone shared some links and said that:我看到有人分享了一些链接并说: "This won't work anymore" “这已经不行了” , it's totally wrong and misunderstood . ,这是完全错误误解的。

About this concern: "I've seen this answer said BOOT_COMPLETED is not sent to the application unless the user launches your application first, after Android version 3.1" , please read these lines (from official docs: https://developer.android.com/about/versions/android-3.1.html#launchcontrols ) to understand correctly:关于这个问题: “我已经看到这个答案说 BOOT_COMPLETED 不会发送到应用程序,除非用户在 Android 版本 3.1 之后首先启动您的应用程序” ,请阅读这些行(来自官方文档: https://developer.android. com/about/versions/android-3.1.html#launchcontrols )正确理解:

  • Note that an application's stopped state is not the same as an Activity's stopped state .请注意,应用程序的停止状态Activity 的停止状态不同。 The system manages those two stopped states separately.系统分别管理这两个停止状态。

  • Applications are in a stopped state when they are first installed but are not yet launched and when they are manually stopped by the user (in Manage Applications ).应用程序在首次安装但尚未启动以及由用户手动停止时(在Manage Applications中)处于停止状态。 (They mean force stop an app) (他们的意思是强制停止应用程序)

在此处输入图像描述

  1. That means a user should launch app at least once after installation to activate the application, then the app can receive implicit broadcasts from OS as normal.这意味着用户应该在安装后至少启动一次应用程序以激活应用程序,然后应用程序可以正常接收来自操作系统的隐式广播。 ( Just only one time launching ever ! ) 只有一次发射!

  2. "Does any app that gets installed and never open even only one time ever ?" “是否有任何应用程序被安装并且从未打开过一次?” , yep, it 's spam and scam apps, this technique helps user to prevent that! ,是的,它是垃圾邮件和诈骗应用程序,这种技术可以帮助用户防止这种情况!

FURTHERMORE, UNTIL NOW (Android Oreo 8.0) , when Android limits registering implicit broadcasts at Manifest ( https://developer.android.com/about/versions/oreo/background.html#broadcasts ), several broadcasts are still currently exempted from these limitations.此外,直到现在(Android Oreo 8.0) ,当 Android 限制在 Manifest( https://developer.android.com/about/versions/oreo/background.html#broadcasts )上注册隐式广播时,目前仍有几个广播不受这些广播的约束限制。 And BOOT_COMPLETED is the first one they mention ! BOOT_COMPLETED是他们提到的第一个 ( https://developer.android.com/guide/components/broadcast-exceptions.html ) https://developer.android.com/guide/components/broadcast-exceptions.html

By the way, this is the best solution I found for this question:顺便说一句,这是我为这个问题找到的最佳解决方案:

<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>

Finally, please read the document carefully and Think twice code once :3!最后,请仔细阅读文档并三思而后行代码一次:3!

some new tablets and android devices have security application by default.一些新的平板电脑和安卓设备默认具有安全应用程序。 some times these apps lock your auto-start mode.有时这些应用程序会锁定您的自动启动模式。 an example of this secure app is MyAsus manager.这个安全应用程序的一个例子是 MyAsus 管理器。 so you can add "allow auto start" to your apps因此您可以将“允许自动启动”添加到您的应用程序

And for Htc devices add com.htc.intent.action.QUICKBOOT_POWERON对于 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>

For others that are still having an issue with this like I did, if you're debugging on a device that has a boot lock (pin, pattern, or otherwise), OS versions >= 7.0 need to subscribe to the android.intent.action.LOCKED_BOOT_COMPLETED as illustrated below:对于其他仍然像我一样遇到此问题的人,如果您在具有启动锁(pin、模式或其他)的设备上进行调试,则操作系统版本 >= 7.0 需要订阅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>

You can find the documentation at the following link: https://developer.android.com/training/articles/direct-boot您可以在以下链接中找到文档: https ://developer.android.com/training/articles/direct-boot

The problem is with the device.问题出在设备上。 some devices only allow internal apps to receive this action(example: Android 5.1).某些设备只允许内部应用程序接收此操作(例如:Android 5.1)。

you can add this to your intent filter as work around您可以将其添加到您的意图过滤器中作为解决方法

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

This is triggered after the user unlocks the device.这是在用户解锁设备后触发的。

The problem I experienced was that BOOT_COMPLETED and QUICKBOOT_POWERON together does not always triggered my intent when I switched the power off from my Android 6.0.1 panel.我遇到的问题是,当我从 Android 6.0.1 面板关闭电源时, BOOT_COMPLETEDQUICKBOOT_POWERON并不总是触发我的意图。 I have been searching the Internet for quite a long time and found the solution by adding QUICKBOOT_POWEROFF to the manifest file.我在网上搜索了很长时间,通过在清单文件中添加QUICKBOOT_POWEROFF找到了解决方案。

See also:也可以看看:

HTC's "fast boot" is not broadcasting BOOT_COMPLETED intent nor wiping intents from alarm manager HTC 的“快速启动”没有广播 BOOT_COMPLETED 意图,也没有从警报管理器中擦除意图

If you reached this answer and none of the other answers seem to work, double-check the action string in the manifest.如果您达到了这个答案并且其他答案似乎都不起作用,请仔细检查清单中的操作字符串。 AndroidStudio does not show any error if you write an incorrect string in the action tag.如果您在action标签中写入了错误的字符串,AndroidStudio 不会显示任何错误。 Do not confuse the name of the constant in code, which is ACTION_BOOT_COMPLETED , with the value of said constant, which is the one that goes in the manifest, and is equal to android.intent.action.BOOT_COMPLETED不要混淆代码中常量的名称,即ACTION_BOOT_COMPLETED与所述常量的,即清单中的常量,等于android.intent.action.BOOT_COMPLETED

TL;DR Check that you have this in the manifest: TL;DR 检查清单中是否有此内容:

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

And not this:而不是这个:

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

For workaround you need to create a NotificationListener service对于解决方法,您需要创建 NotificationListener 服务

if the Device is >= Build.VERSION_CODES.JELLY_BEAN_MR2 and having a battery optimization option as in Huawei devices, then you have to ask for NotificationListener permission and create a NotificationListener service as in below code, then you will get the BOOT_COMPLETED in your receiver如果设备 >= Build.VERSION_CODES.JELLY_BEAN_MR2 并且具有华为设备中的电池优化选项,那么您必须请求 NotificationListener 权限并按照以下代码创建 NotificationListener 服务,然后您将在接收器中获得 BOOT_COMPLETED

Manifest Receiver :清单接收者:

    <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 create a NotificationListener service : 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 check if the NotificationListener is granted or not : 2 检查 NotificationListener 是否被授予:

static boolean CheckNotificationLisPermission(Context context)
    {

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

    }

3 if not then ask for NotificationListener permission : 3 如果没有,则请求 NotificationListener 权限:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM