Reputation: 23018
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:
But I still have follow-up questions please:
BOOT_COMPLETED
broadcast still be delivered to the "non-exported" service?RECEIVE_BOOT_COMPLETE
or something else (and does Android-system needs this permission?)Upvotes: 4
Views: 5636
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
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