Alexander Farber
Alexander Farber

Reputation: 23018

RECEIVE_BOOT_COMPLETED and "Exported receiver does not require permission"

My question is not a duplicate: I have searched SO and on the web and haven't found a definite answer yet.

In a bluetooth-related app I would like a background Service to be started on device boot and then connect to a bluetooth beacon (if available) and post Android notifications to the user on certain events.

So I have added following lines to 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>

However Eclipse displays the warning Exported receiver does not require permission which probably means, that any app could run my service. And of course I don't want that.

I want only the Android OS (at the boot time) and my MainActivity (acting as settings GUI-frontend to the background service) being able to do (re)start the ScanService.

There are 2 common suggestions for this problem:

  1. First is to add android:exported="false" to the intent filter.
  2. Second is to add android:permission to the intent filter.

But I still have follow-up questions please:

  1. Will BOOT_COMPLETED broadcast still be delivered to the "non-exported" service?
  2. What permission to specify here, is it really RECEIVE_BOOT_COMPLETE or something else (and does Android-system needs this permission?)

Upvotes: 4

Views: 5636

Answers (2)

Jon Goodwin
Jon Goodwin

Reputation: 9153

Some things to bear in mind if: Android receiver & RECEIVE_BOOT_COMPLETED & BOOT_COMPLETED failure to start your service

After the obvious stuff:

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

Still pulling your hair out ?

After Android 3.1 " the system adds FLAG_EXCLUDE_STOPPED_PACKAGES to all broadcast intents." This means you, after 3.1, all apps are stopped on boot. Why ?. For security reasons.

There are RULES to turn the flag off "FLAG_EXCLUDE_STOPPED_PACKAGES" .

(1) Your app needs to needs in phone storage, NOT sdcard otherwise the flag set. BOOT_COMPLETE is sent before external storage is mounted. if app is installed to external storage it won't receive BOOT_COMPLETE broadcast message.

(2) If the user presses "Force close" from settings OR "unresponsive app" button, the flag is set.

(3) If the application has never been run, the flag is set (never is relative to current boot state ;O) NEVER means in THIS boot OR you invalidated the flag in the last boot state).

Your Reciver will run on boot up (flag not set), if you follow the rules.

info

You can register you receiver your in code (it won't help for boot-up).

    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.

Tip for testing

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"

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

Upvotes: 1

Yash Sampat
Yash Sampat

Reputation: 30611

1. BOOT_COMPLETED is an inter-app, system-wide broadcast sent by the OS, and will indeed be heard by all app components that filter this broadcast. Not exported merely means that other apps cannot make use of that component; the broadcast action will certainly be heard by the receiver.

2. BOOT_COMPLETED is very much the broadcast you need to use here. Set android:exported="false" and add that permission in the manifest.

EDIT:

BOOT_COMPLETED is a broadcast action. To intercept it on boot, you need to use a BroadcastReceiver, and there you can start the Service. In your manifest, add

<receiver 

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

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

</receiver>

And create the class

public class BootCompletedReceiver extends BroadcastReceiver {   

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

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

    }
}

Try this. This will work.

Upvotes: 9

Related Questions