RECEIVE_BOOT_COMPLETED 和 "Exported receiver does not require permission"

RECEIVE_BOOT_COMPLETED and "Exported receiver does not require permission"

我的问题不是重复的:我已经在 SO 和网络上进行了搜索,但还没有找到明确的答案。

在与蓝牙相关的应用程序中,我希望在设备启动时启动后台 Service,然后连接到蓝牙信标(如果可用)和 post Android 通知在某些事件中向用户发送。

所以我在 AndroidManifest.xml 中添加了以下几行:

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

    <service 
        android:name="ScanService"
        android:icon="@drawable/ic_launcher">
        <intent-filter>
            <category android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </service>

但是 Eclipse 显示警告 Exported receiver does not require permission 这可能意味着,任何应用程序都可以 运行 我的服务。当然我不想要那个。

我只希望 Android OS(在启动时)和我的 MainActivity(充当后台服务的设置 GUI 前端)能够(重新)启动 ScanService .

对于这个问题有 2 个常见的建议:

  1. 首先是将 android:exported="false" 添加到 intent 过滤器。
  2. 其次是将 android:permission 添加到 intent 过滤器。

但我还有后续问题请教:

  1. BOOT_COMPLETED 广播仍会传送到 "non-exported" 服务吗?
  2. 这里要指定什么权限,真的是RECEIVE_BOOT_COMPLETE还是别的什么(Android系统需要这个权限吗?)

1. BOOT_COMPLETED 是一个 应用程序间 ,由 OS 发送的全系统广播,并且确实会被过滤此广播的所有应用程序组件听到。 未导出仅表示其他应用程序无法使用该组件;广播动作一定会被接收者听到。

2. BOOT_COMPLETED 是您需要在这里使用的广播。设置 android:exported="false" 并在清单中添加该权限。

编辑:

BOOT_COMPLETED 是一个 广播动作 。要在启动时拦截它,您需要使用 BroadcastReceiver,然后您可以启动 Service。在您的清单中,添加

<receiver 

    android:name=".BootCompletedReceiver" 
    android:enabled="true" 
    android:exported="false">

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

</receiver>

并创建 class

public class BootCompletedReceiver extends BroadcastReceiver {   

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

        Intent i = new Intent(context, ScanService.class);
        context.startService(i);

    }
}

试试这个。这会起作用。

如果出现以下情况,请记住一些事项: Android 接收器 & RECEIVE_BOOT_COMPLETED & BOOT_COMPLETED 无法启动您的服务

在明显的东西之后:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"
and:
            <receiver 
                   android:name="com.twiggwidgets.service.MyScheduleReceiver"
                   android:enabled="true"
                   android:exported="true"
            >
                <intent-filter>
                     <action android:name="android.intent.action.BOOT_COMPLETED" />
 <action android:name="android.intent.action.QUICKBOOT_POWERON" />
                     <category android:name="android.intent.category.DEFAULT" />
                </intent-filter>
            </receiver>

还在拔头发吗?

之后Android3.1 “系统将 FLAG_EXCLUDE_STOPPED_PACKAGES 添加到所有广播意图。” 这意味着您在 3.1 之后,所有应用程序都在启动时停止。 为什么 ?。出于安全原因。

规则 可以关闭标志 "FLAG_EXCLUDE_STOPPED_PACKAGES" .

(1) 您的应用需要 phone 存储,而不是 sdcard 否则标志设置。 BOOT_COMPLETE 在安装外部存储之前发送。如果应用程序安装到外部存储,它将不会收到 BOOT_COMPLETE 广播消息。

(2) 如果用户在设置中按下 "Force close" 或 "unresponsive app" 按钮,则设置标志。

(3) 如果应用程序从未 运行,则设置标志(从不与当前启动状态相关;O)从不意味着在本次启动中或您使标志无效在上次启动状态).

如果您遵守规则,您的 Reciver 将 运行 在启动时(未设置标志)。

信息

您可以在代码中注册接收方(这对启动没有帮助)。

    IntentFilter filter = new IntentFilter("com.twiggwidgets.service.MyScheduleReceiver");

    MyScheduleReceiver myReceiver = new MyScheduleReceiver();
    registerReceiver(myReceiver, filter);

//receiver's (are supposed to) run momentarily, but you knew that.

测试提示

Open console/terminal and navigating to /platform-tools (it should be in your path ;O)).
Type adb shell or on linux/mac ./adb shell
In the shell type "am broadcast -a android.intent.action.BOOT_COMPLETED"

参见 android link : http://developer.android.com/about/versions/android-3.1.html#launchcontrols