Android:仅当我立即启动应用程序时,启动完成才有效

Android: Boot Complete only works if I launch App Immediately

我正在尝试重置我的应用程序中的警报并使用接收器来获取 onBootCompleted。为了查看是否收到了意图,我正在使用吐司。仅当我立即打开应用程序时才会出现吐司。否则,吐司不会出现。我查看了以前的问题,但几乎所有问题都涉及我没有使用的服务。我不确定这是否是问题的一部分。

Android 清单

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="internalOnly"
package="package.name" >

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

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:configChanges="orientation|screenSize|keyboardHidden"
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:launchMode="singleTop" >
        <meta-data android:name="android.app.searchable"
            android:resource="@xml/searchable" />

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

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>

        <intent-filter>
            <action android:name="android.intent.action.SEARCH" />
        </intent-filter>
</activity>
    <receiver android:name=".AlarmReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.ALARM_SERVICE" />
        </intent-filter>
    </receiver>
    <receiver android:name=".AlarmReset"android:enabled="true" android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>

</application>

接收者Class

public class AlarmReset extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent)
{

    Toast.makeText(context, "Hello! Got message",
            Toast.LENGTH_LONG).show();
//reset alarms etc. No service set.
}

我也试过将清单接收器写成

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

我在网上找到的要点是包括权限(我这样做了)和注意日志记录。

我不明白的是,为什么我立即(在几秒钟内,否则吐司不会出现)启动我的 activity 但不成功。我正在考虑测试一些可能性,比如通过代码启动 activity 本身,或者像大多数其他人一样使用服务。我目前正在实际 phone.

上测试 Android 4.4

安装应用程序时,它处于停止状态。 None 其组件(例如您的 BOOT_COMPLETED 接收器)将被激活,直到用户启动应用程序将其移出此状态。这就是为什么您的应用只有启动一次才能运行。

请注意,从“设置”中强制停止应用程序也会使其进入此停止状态。

有关详细信息,请参阅 this page(在页面中搜索 "launch controls")。

从 Android 3.1 开始,所有应用程序在安装后都处于 "stopped" 状态。(这与用户强制停止应用程序后应用程序最终处于的状态相同来自“设置”应用程序。)

处于 "stopped" 状态时,应用程序不会出于任何原因 运行,除非手动启动 activity。 (意味着不会调用 BroadcastReceviers(ACTION_PACKAGE_INSTALLED、BOOT_COMPLETED 等),无论他们注册的事件是什么,直到用户 运行 手动应用程序。)

但是你可以为前任启动一个服务

1) 在你的元素中:

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

2) 在您的元素中(确保为您的 BroadcastReceiver 使用完全限定的 [或相对] class 名称):

<receiver android:name="com.example.MyBroadcastReceiver">  
    <intent-filter>  
        <action android:name="android.intent.action.BOOT_COMPLETED" />  
    </intent-filter>  
</receiver>

在MyBroadcastReceiver.java中:

package com.example;

public class MyBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Intent startServiceIntent = new Intent(context, MyService.class);
        context.startService(startServiceIntent);
    }
}

我觉得有必要澄清问题和解决方案,因为问题不清楚(由于保密问题)。

我的问题的基本解决方案是启动服务。

问题:我试图通过 AlarmManager 在 class、AlarmReset 中发出警报。这本身可能是个问题,但除此之外,我还试图访问在 MainActivity 中实例化的对象,这进一步加剧了我的困境。当我足够快地打开 MainActivity 时它起作用的原因,我怀疑是因为我能够实例化对象并设置 class 直接访问的先决条件。我觉得 toast 没有出现和这个问题类似。

解决方案:我设置了一项服务 class,我将 AlarmReset 指向该服务。这就是我将 AlarmReset class 更改为:

public class AlarmReset extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent)
{

    Toast.makeText(context, "Hello! Got message",
            Toast.LENGTH_LONG).show();
//Pretty sure the Toast doesn't appear still. 
    Intent service = new Intent(context, Service.class);
    context.startService(service);
}

那我服务class

public class Service extends IntentService {
private DataBaseManager database;

public Service()
{
    super("Service");
}
@Override
protected void onHandleIntent(Intent intent)
{
    database = new DataBaseManager(this);
    Toast.makeText(this, "Hi",
            Toast.LENGTH_LONG).show();

    Toast.makeText(this, "Hello! Got message",
            Toast.LENGTH_LONG).show();
//rest of code
}

同样,文本不会出现,除非我立即打开应用程序(我怀疑这与线程有关)。

在这里,我确保在使用它们之前实例化我的对象(或在崩溃后这样做)。

其他人可能会遇到的一些问题(正如我所读到的)如下: 正在内部存储中安装

  • android:installLocation="internalOnly"

并获得启动权限

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

人们提出但不是很重要的一些问题是:

  • 使用 android:enabled 和 android:exported。默认值很好
  • 写完整的接收者姓名。对我来说没有必要
  • <action android:name="android.intent.action.QUICKBOOT_POWERON" />好像没做什么。