Is rooted device required to start app on boot? - android

I have developed application to start app on boot, but it is working on rooted devices only some of code as below.
permission and receiver in AndroidManifest.xml file is given below.
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<receiver android:enabled="true" android:name="in.com.appname.StartAppAtBootReceiver"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
below are the class to receive on boot.
public class StartAppAtBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent myIntent = new Intent(context, MainActivity.class);
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myIntent);
}
}
my question is that this code will work with non rooted devices?
if yes then what is missing because same app is working with rooted devices.

This must work without root.
Else try to use a simple tutorial like: Android AutoStart App after boot
Differences:
Check which action occurs.
Use startService instead of startActivity
Another tip: Set permissions in top of manifest, and receiver in application-part.

This should work without root.
There are a couple of things to notice:
app must be started at least once before it can receive BOOT_COMPLETED
if app is force closed, it will lose it ability to receive BOOT_COMPLETED until next launch.
Also, permission should be at the root of manifest and not inside application:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.x.y" >
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
.
.
.
make sure you are not running in above situations.

Related

Broadcast Receiver Not Working After Device Reboot in Android

I have already checked all the related questions and have not found any solution for this problem. So this is an absolutely new problem for me.
What I Have
I have an Android app which registers a few broadcast receivers in its manifest. This is what my manifest looks like.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.app.myapp">
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.WRITE_CALL_LOG" />
<uses-permission android:name="com.android.vending.BILLING" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-feature
android:name="android.hardware.telephony"
android:required="false" />
<uses-feature
android:name="android.hardware.screen.portrait"
android:required="false" />
<application
android:name=".base.MyApp"
android:allowBackup="false"
android:icon="#drawable/ic_launcher"
android:label="#string/label_app_name"
android:largeHeap="true"
android:supportsRtl="true"
android:theme="#style/AppTheme"
tools:replace="label, allowBackup">
<receiver android:name=".mics.BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
<receiver android:name=".PhoneCallReceiver">
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
<receiver
android:name=".mics.DeviceAdminReceiver"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
<meta-data
android:name="android.app.device_admin"
android:resource="#xml/device_admin" />
</receiver>
<receiver
android:name="com.clevertap.android.sdk.InstallReferrerBroadcastReceiver"
android:exported="true">
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER" />
</intent-filter>
</receiver>
<meta-data
android:name="com.app.myapp.utils.ImageLoaderModule"
android:value="GlideModule" />
<meta-data
android:name="com.app.myapp.utils.AudioCoverLoaderModule"
android:value="GlideModule" />
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths" />
</provider>
<activity
android:name=".core.activities.SplashActivity"
android:excludeFromRecents="true"
android:label="#string/label_app_name"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
<activity-alias
android:name=".core.activities.SplashActivity-Alias"
android:icon="#drawable/ic_launcher"
android:label="#string/label_app_name"
android:noHistory="true"
android:targetActivity="com.app.myapp.core.activities.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.MONKEY" />
</intent-filter>
</activity-alias>
<activity
android:name=".core.flow.authFlow.activities.AuthFlowActivity"
android:excludeFromRecents="true"
android:label="#string/label_app_name"
android:screenOrientation="portrait" />
<service android:name=".features.fileCloudSync.KillNotificationService" />
</application>
</manifest>
There are 10-15 other activities as well but have been removed for simplicity. And this is the basic boot receiver class. I start a service from here.
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
AlertUtils.showToast(context, "BOOT COMPLETED", Toast.LENGTH_LONG);
}
}
}
and the phone call receiver class looks something like this (it has been simplified as well),
public class PhoneCallReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) {
AlertUtils.showToast(context, "PHONE CALL RECEIVED", Toast.LENGTH_LONG);
// Simplified for brevity
}
}
}
The Problem
All these receivers work fine when I install the app and start it once. But after I reboot my device these receivers don't work at all. Neither the BootCompleteReceiver nor the PhoneCallReceiver gets their onReceive() method called.
My assumption was that these receivers would get registered automatically after reboot, but it just doesn't work. I need the BootCompleteReceiver to work so that I can start an important service in my app.
My Observations
I have tested this thoroughly. After rebooting the device, the receivers work fine in my Nexus 5X (Nougat), Nexus 6P (Nougat), YU Yuphoria (Lollipop) but not in my OnePlus 3 (Nougat) and Mi 4i (Lollipop).
How can the same code work perfectly on a few devices and not work at all on the other devices? I haven't changed anything at all.
What am I doing wrong here? My app is heavily dependent on these broadcasts and starts services based on these. Any help will be highly appreciated.
EDIT 1
To understand the problem better, I just created a very small test project with just a single activity and the exact same BootCompleteReceiver and PhoneCallReceiver.
But weirdly, this project works perfectly on my OnePlus 3 where my actual app's receivers don't work after a reboot. I was initially assuming that the problem is in the OS or the device somehow, but it is not.
So where is the actual problem? Is it in my app (but it works perfectly on other devices) or in the OS and device (the small test project works fine on the same OS and same device)?
It is really confusing to me. I would need some expert help on this.
EDIT 2
I have tried the suggestion given by #shadygoneinsane. Here are my observations.
1) I tried to send the BOOT_COMPLETED broadcast via ADB.
./adb shell am broadcast -a android.intent.action.BOOT_COMPLETED -p com.app.myapp
And I got this stack trace,
Broadcasting: Intent { act=android.intent.action.BOOT_COMPLETED pkg=com.app.myapp }
java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.intent.action.BOOT_COMPLETED from pid=25378, uid=2000
at android.os.Parcel.readException(Parcel.java:1683)
at android.os.Parcel.readException(Parcel.java:1636)
at android.app.ActivityManagerProxy.broadcastIntent(ActivityManagerNative.java:3696)
at com.android.commands.am.Am.sendBroadcast(Am.java:778)
at com.android.commands.am.Am.onRun(Am.java:404)
at com.android.internal.os.BaseCommand.run(BaseCommand.java:51)
at com.android.commands.am.Am.main(Am.java:121)
at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:276)
Maybe because my device is not rooted. I am unable to send this broadcast in any way.
2) I tried with the PROCESS_OUTGOING_CALLS broadcast after that.
./adb shell am broadcast -a android.intent.action.PROCESS_OUTGOING_CALLS -p com.app.myapp
I got this,
Broadcasting: Intent { act=android.intent.action.PROCESS_OUTGOING_CALLS pkg=com.app.myapp }
Broadcast completed: result=0
It seems that the broadcast was successful, but I do not see any Toast or any log. I then opened my dialer to dial a number and I can then see the Toast and the log both.
So it seems that sending the broadcast via ADB didn't work, but actually opening the dialer and dialing a number did.
EDIT 3
As per the suggestion from #ChaitanyaAtkuri, I have also tried adding priority to the intent-filters but that didn't work as well.
I have used priorities like 500, 999 and even the highest integer value, but nothing works. This problem is also occurring in some of my friends apps as well. They work in some devices and doesn't work in others.
EDIT 4
I have finally found out the root cause of the problem happening in my OnePlus 3. My OnePlus 3 recently got updated to Nougat and they introduced a feature similar to Mi devices which prevent certain apps from auto-starting after reboot.
Upon disabling this feature my app started receiving broadcasts after reboot perfectly. But this still doesn't explain two things.
1) My small test project is whitelisted automatically in the list of AutoLaunch apps and that is why it works as expected. But how is this possible? Why the OS considers this small app worthy to be auto-started?
2) There are some apps like LockDown Pro, 500 Firepaper which is blacklisted in the AutoLaunch apps screen but still, it receives broadcasts after reboot in my OnePlus 3 and Mi 4i. How is that possible now? Is it somehow possible to programmatically allow my app to auto launch in these devices (OnePlus and Mi)?
EDIT 5
I have tried the solution proposed by #Rahul Chowdhury and it really seems to work very well. After adding the accessibility service the problem is re-solved.
But if the user revokes the accessibility permission after granting it then is there a way for me to programmatically check if the accessibility permission is available to my app?
Here's a tested and working solution on both the devices that you mentioned, OnePlus and Mi.
As you said the auto-start prevention feature on OnePlus and Mi devices prevent apps from starting up their services automatically on boot complete so as to improve the overall device boot speed and battery performance. However, there's a workaround to get your app working even when this feature is turned on.
I have noticed that if you have an AccessibilityService in your app and it is turned on by the user, then your app passes the filter that these manufacturers apply and the app receives it's boot complete event and any other BroadcastReceiver works as expected.
The possible explanation of this trick can be that since AccessibilityService is a system level service, so by registering your own service you are passing the certain filter applied by these manufacturers and as soon as your custom AccessibilityService gets triggered by the OS, your app becomes active in receiving the eligible BroadcastReceiver that you had registered.
So, here's how to do it,
Start by adding this permission to your AndroidManifest.xml,
<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE"/>
This will allow you to register your app's AccessibilityService with the system.
Now, add a very basic configuration for your AccessibilityService by creating a file for example my_accessibility_service.xml inside XML folder under your res folder in your project.
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service
xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityFeedbackType="feedbackSpoken"
android:description="#string/service_desc"
android:notificationTimeout="100"/>
There's just one more step left to do, define your custom AccessibilityService in your project,
public class MyAccessibilityService extends AccessibilityService {
#Override
public void onAccessibilityEvent(AccessibilityEvent event) { }
#Override
public void onInterrupt() {
}
}
Note, since you're not needing the AccessibilityService for any purpose rather than this workaround, you can leave the overridden methods empty.
Finally, just declare your AccessibilityService in your AndroidManifest.xml,
<service
android:name=".MyAccessibilityService"
android:label="#string/app_name"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService"/>
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="#xml/my_accessibility_service"/>
</service>
That's all. Now within your app, just ask your users to turn on the accessibility service for your app from the settings and leave it on and voila! Your app works fine on all devices even where the OS puts a filter on which apps should auto-start on boot.
EDIT 1
Here's how you can check if accessibility service is turned ON or not for your app,
private static final int ACCESSIBILITY_ENABLED = 1;
public static boolean isAccessibilitySettingsOn(Context context) {
int accessibilityEnabled = 0;
final String service = context.getPackageName() + "/" + MyAccessibilityService.class.getCanonicalName();
try {
accessibilityEnabled = Settings.Secure.getInt(
context.getApplicationContext().getContentResolver(),
android.provider.Settings.Secure.ACCESSIBILITY_ENABLED);
} catch (Settings.SettingNotFoundException e) {
Log.e("AU", "Error finding setting, default accessibility to not found: "
+ e.getMessage());
}
TextUtils.SimpleStringSplitter mStringColonSplitter = new TextUtils.SimpleStringSplitter(':');
if (accessibilityEnabled == ACCESSIBILITY_ENABLED) {
String settingValue = Settings.Secure.getString(
context.getApplicationContext().getContentResolver(),
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
if (settingValue != null) {
mStringColonSplitter.setString(settingValue);
while (mStringColonSplitter.hasNext()) {
String accessibilityService = mStringColonSplitter.next();
if (accessibilityService.equalsIgnoreCase(service)) {
return true;
}
}
}
}
return false;
}
Hope this helps.
Hi I am late to the party but I was following this question from it's start. I know that One-plus and some other OEMs maintain a list of apps which can receive BOOT_COMPLETED broadcast. If your app is not white listed then your app won't be started on boot. Now I've a solution which is very efficient in terms of memory and resources and guaranteed to start your task or service after reboot or hard boot also does not need AccessibilityService as proposed in this answer. Here it goes..
Add the follwing permission in your manifest file
2.If you don't have a dependency on com.google.android.gms:play-services-gcm, add the following to your build.gradle's dependencies section:
compile 'com.firebase:firebase-jobdispatcher:0.5.2'
Otherwise add the following:
compile 'com.firebase:firebase-jobdispatcher-with-gcm-dep:0.5.2'
This is a library from firebase team which depends on google-play-service library to schedule your jobs and from my point of view google-play-service has the permission to start at boot so instead of system ,google-play-service will run your job as soon as device rebooted.
Now this step is easy Just define a JobService class
public class MyJobService extends JobService {
#Override
public boolean onStartJob(JobParameters job) {
Log.v("Running", "====>>>>MyJobService");
return false; // Answers the question: "Is there still work going on?"
}
#Override
public boolean onStopJob(JobParameters job) {
Log.v("Stopping", "====>>>>MyJobService");
return true; // Answers the question: "Should this job be retried?"
}
}
Add your Job Service in manifest file.
Schedule this job anywhere you want for e.g when your app start.
FirebaseJobDispatcher dispatcher =
new FirebaseJobDispatcher(new GooglePlayDriver(getApplicationContext()));
Bundle myExtrasBundle = new Bundle();
myExtrasBundle.putString("some_key", "some_value");
Job myJob = dispatcher.newJobBuilder()
// the JobService that will be called
.setService(MyJobService.class)
// uniquely identifies the job
.setTag("my-unique-tag-test")
// repeat the job
.setRecurring(true)
// persist past a device reboot
.setLifetime(Lifetime.FOREVER)
// start between 0 and 60 seconds from now
.setTrigger(Trigger.executionWindow(0, 60))
// don't overwrite an existing job with the same tag
.setReplaceCurrent(false)
// retry with exponential backoff
.setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
// constraints that need to be satisfied for the job to run
.setExtras(myExtrasBundle)
.build();
dispatcher.mustSchedule(myJob);
6.That's it!! Now you can execute your task or service on device boot no matter you are in white list or not.
There is one point to note that Google Play Service must be installed on device otherwise it won't work.
#Aritra, Try this
<receiver
android:name=".mics.BootReceiver"
android:enabled="true"
android:exported="true" >
<intent-filter android:priority="500" >
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Remove quickBoot intent filter and try running it, as per the documentation we only required BootCompleted to acheive it. May be it is interrupting this.
Also one more important point to Note :
Don't rely completely or test on Mi devices as they have their own OS which halts the basic features of Android, like they stop the Push notifications services and background services just to optimize battery usage. To test this on Mi device, mark your app as "AutoStart" in Security app and then try.
You can ask user for autostart permission, and direct them to the required settings page:
private void autoStart() {
try {
Intent intent = new Intent();
String manufacturer = android.os.Build.MANUFACTURER;
if ("xiaomi".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity"));
} else if ("oppo".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.permission.startup.StartupAppListActivity"));
} else if ("vivo".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.vivo.permissionmanager", "com.vivo.permissionmanager.activity.BgStartUpManagerActivity"));
} else if ("Letv".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.AutobootManageActivity"));
} else if ("Honor".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity"));
} else if ("oneplus".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.oneplus.security", "com.oneplus.security.chainlaunch.view.ChainLaunchAppListAct‌​ivity"));
}
List<ResolveInfo> list = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
if (list.size() > 0) {
startActivity(intent);
}
} catch (Exception e) {
Log.e("exc", String.valueOf(e));
}
}
After doing this, receiver always got triggered on reboot.
The way IntentFilters work is that each <intent-filter></intent-filter> contains one way of firing up the component. If you have multiple ways of firing it up (like two actions that you want to listen to in one BroadcastReceiver), you'll need an independent <intent-filter></intent-filter> definition for each.
Hence, you can try changing:
<receiver android:name=".mics.BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
to:
<receiver android:name=".mics.BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
Read more here: Intents and Intent Filters | Android Developers
EDIT
If it still doesn't work, you can try to test if your manifest declaration is done correctly. Try executing the following command in your terminal, keeping the test device connected to the computer:
adb shell am broadcast -a android.intent.action.BOOT_COMPLETED -n com.app.myapp/.mics.BootReceiver
If this doesn't work, you should recheck the relative package declaration of the receiver in your manifest file.
EDIT 2
It may sound weird but try following these steps:
Uninstall the app from your phone (ensure it is uninstalled for all users)
Reboot your phone
Clean the project
Build and run the project in your device again
I have been struggling with this issue from almost a year. In all my apps, I show a notice to users to disable battery optimization for my app.
After a lot of testing on One Plus devices, I am able to receive boot completed broadcast when battery optimization is turned off for my app. In my opinion, it is much better than the accessibility service discussed above.
The simplest way to ask the user to disable the battery optimization for your app is to show some kind of notice, and open the battery optimization page when the user clicks on it. You can use the below code to do that.
public void openPowerSettings(View v) {
/* Make Sure to add below code to manifest
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
*/
try {
Intent i = new Intent(android.provider.Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
startActivityForResult(i, 1);
} catch (Exception e) {
Log.e (TAG, "Exception: " + e.toString());
}
}
And you can also hide the notice if below function returns true.
public static boolean is_ignoring_battery_optimizations(Context context) {
String PACKAGE_NAME = context.getPackageName();
PowerManager pm = (PowerManager) context.getSystemService(context.POWER_SERVICE);
boolean status = true;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
status = pm.isIgnoringBatteryOptimizations(PACKAGE_NAME);
}
return status;
}
How to start service on device boot(autorun app, etc.)
For first: since version Android 3.1+ you don't receive BOOT_COMPLETE if user never started your app at least once or user "force closed" application.
This was done to prevent malware automatically register service. This security hole was closed in newer versions of Android.
Solution:
Create app with activity. When user run it once app can receive BOOT_COMPLETE broadcast message.
For second: BOOT_COMPLETE is sent before external storage is mounted. If app is installed to external storage it won't receive BOOT_COMPLETE broadcast message.
In this case there is two solution:
Install your app to internal storage
Install another small app in internal storage. This app receives BOOT_COMPLETE and run second app on external storage.
If your app already installed in internal storage then code below can help you understand how to start service on device boot.
In Manifest.xml
Permission:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
Register your BOOT_COMPLETED receiver:
<receiver android:name="org.yourapp.OnBoot">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
Register your service:
<service android:name="org.yourapp.YourCoolService" />
In receiver OnBoot.java:
public class OnBoot extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
// Create Intent
Intent serviceIntent = new Intent(context, YourCoolService.class);
// Start service
context.startService(serviceIntent);
}
}
For HTC you maybe need also add in Manifest this code if device don't catch RECEIVE_BOOT_COMPLETED:
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
Receiver now look like this:
<receiver android:name="org.yourapp.OnBoot">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
How to test BOOT_COMPLETED without restart emulator or real device?
It's easy. Try this:
adb -s device-or-emulator-id shell am broadcast -a android.intent.action.BOOT_COMPLETED
How to get device id? Get list of connected devices with id's:
adb devices
adb in ADT by default you can find in:
adt-installation-dir/sdk/platform-tools
Enjoy! )

Android Receivers not doing as expected

Well honestly, they aren't doing anything at all. Let me start by saying that I know that Android reworked receivers in 3.1, specifically boot control. I know that they made it so that ACTION_BOOT_COMPLETED cannot be used unless the application has been previously launched by the user. However, people have been successful in using them in current application, yet I am never hitting my receivers for my BOOT_COMPLETED or my SHUTDOWN.
Quick Edit - Please look at the bottom of this post for corrected Shutdown Receiver, I have gotten it to work and am now just stuck in my efforts to get BOOT_COMPLETED to work.
My manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.smashingboxes.speedblock"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="12"
android:targetSdkVersion="18" />
<!-- PERMISSIONS -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
...
<!-- RECEIVERS -->
<receiver android:name=".BootReceiver"
android:enabled="true" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name=".ShutdownReceiver" >
<intent-filter>
<action android:name="android.intent.action.SHUTDOWN" />
</intent-filter>
</receiver>
Now my implemented receiver classes are fairly straight forward:
BOOT_COMPLETED Receiver (the one that isn't working)
public class BootReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context c, Intent i) {
Intent starterIntent = new Intent(c, LaunchActivity.class);
// Start the activity (by utilizing the passed context)
starterIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
c.getApplicationContext().startService(starterIntent);
}
}
I have tried different things based on what I have seen as far as solutions, such as altering my launching activity to include
/* May need this, as of 3.1 we can't call BOOT_COMPLETED until the app has been run successfully */
Intent intent = new Intent("com.smashingboxes.speedblock.intent");
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
this.sendBroadcast(intent);
or including this in my boot receiver intent-filter in my manifest
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
Nothing seems to work. When Logs are inserted into my receiver methods they are never hit. Apparently people are still using these two receivers fairly regularly, which is why I am having trouble understanding why neither of them work. Have I missed something with my registration or something?
--EDIT--
I have solved the problem with my shutdown receiver. First, I foolishly forgot the ACTION_ portion of the tag. Secondly, HTC has separate shutdown methods, in my case I needed to add an intent-filter to my Receiver request:
<receiver android:name=".ShutdownReceiver" >
<intent-filter>
<action android:name="android.intent.action.ACTION_SHUTDOWN" />
<action android:name="android.intent.action.QUICKBOOT_POWEROFF" />
</intent-filter>
</receiver>
Now my Shutdown Receiver works, still no luck on the Boot Completed Receiver though.
I found the answer and I think that it is actually important to note, as it seems like an issue others will run into at some point. My issue was that I was launching a "Launcher Activity" called just that, LauncherActivity. Basically, it acted as my gateway to start up services, receivers, and such when the application was launched. It is a very simple Activity class:
public class LaunchActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
/* May need this, as of 3.1 we can't call BOOT_COMPLETED until the app has been run successfully */
Intent intent = new Intent("com.smashingboxes.speedapp.intent");
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
this.sendBroadcast(intent);
}
#Override
protected void onStart(){
super.onStart();
Intent serviceIntent = new Intent(this, MainService.class);
startService(serviceIntent);
// NOTE: It is VERY, VERY important that we DO NOT finish this activity.
// If we do, our BootReceiver will no longer receive its broadcast and
// we won't auto-start on boot
//finish();
}
}
Note that I was calling finish() on the LaunchActivity. The problem with this is that it seemed to tell Android that the application was in the stopped state, meaning that it won't allow the reception of the BOOT_COMPLETED broadcast, even though I had a number of services running in the background. The LauncherActivity MUST stay active throughout the entire life-cycle or the BOOT_COMPLETED receiver becomes useless. Something that I haven't really seen mentioned before, but again something I think is worth noting.

How to start/ launch application at boot time Android

I would like to launch my app when my tablet starts, so that the main activity of my app is the first thing that the user see when they start the tablet.
I've read about LauncherActivity but I don't understand how to use it.
Can anyone help me with suggestions, links or tutorials for this?
Is LauncherActivity the best way or are there alternatives?
These lines of code may be helpful for you...
Step 1: Set the permission in AndroidManifest.xml
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
Step 2: Add this intent filter in receiver
<receiver android:name=".BootReceiver">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
Step 3: Now you can start your application's first activity from onReceive method of Receiver class
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent myIntent = new Intent(context, MainActivity.class);
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myIntent);
}
}
If you want to start the app when the tablets starts, you need to listen to the BOOT_COMPLETED action and react to it. BOOT_COMPLETED is a Broadcast Action that is broadcast once, after the system has finished booting. You can listen to this action by creating a BroadcastReceiver that then starts your launch Activity when it receives an intent with the BOOT_COMPLETED action.
Add this permission to your manifest:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
Create a Custom BroadcastReceiver in your project:
public class MyBroadCastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
Intent i = new Intent(context, MyActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
}
Then modify your manifest file by adding the BroadCastReceiver to the Manifest:
<receiver android:name=".MyBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Answer by #vishesh chandra is correct. But on some device doesn't work because app was installed on external storage by default. Please ensure that you specify
android:installLocation="internalOnly"
otherwise you will not receive any Boot Complete actions if the app is installed in the SD card. Add this into application tag in manifest.xml file and it will work.
Usage:
<application
android:name=".Data.ApplicationData"
android:allowBackup="true"
android:hardwareAccelerated="true"
android:icon="#mipmap/ic_launcher"
android:installLocation="internalOnly"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/Theme.AppCompat.Light.NoActionBar.FullScreen">
<!--activities, services...-->
</application>
I would like to add one point in this question which I was facing for couple of days. I tried all the answers but those were not working for me. If you are using android version 5.1 please change these settings.
If you are using android version 5.1 then you have to dis-select (Restrict to launch) from app settings.
settings> app > your app > Restrict to launch (dis-select)
please see picture.
After trying BootReceiver code, you will see that your app will not start after boot. Android restricts starting activities from the background.
https://developer.android.com/guide/components/activities/background-starts
The working way to start activity after boot is to give SYSTEM_ALERT_WINDOW permission to the app.
In the AndroidManifest.xml
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
In the MainActivity, add this request permission code. This will open a settings window. User must enable the permission for your app.
// To start app after boot
private void startSystemAlertWindowPermission(){
try{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if(! Settings.canDrawOverlays(this)) {
Log.i(TAG, "[startSystemAlertWindowPermission] requesting system alert window permission.");
startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:"+getPackageName())));
}
}
}catch (Exception e){
Log.e(TAG, "[startSystemAlertWindowPermission] error:", e);
}
}
If the user gives permission, your MainActivity will start after boot.
If your app does not open an activity, but just opens a background service, this permission is not needed.

Cannot receive broadcast in ICS

I writing 1 app for Android 4.0, and it's started via broadcastreceiver. My code is below:
In AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
<application android:icon="#drawable/icon" android:label="#string/app_name">
<receiver android:name="com.Android.Exercise.StartUpReceiver"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<!--<action android:name="StartInstrument" />
<action android:name="PrintControlName" /> -->
</intent-filter>
</receiver>
<service android:enabled="true" android:name="StartAUT_Service">
<intent-filter>
<action android:name="com.Android.Exercise.StartAUT_Service" />
</intent-filter>
</service>
</application>
In StartUpReceiver class:
public class StartUpReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Log.i("Broadcast", "onReceive");
Intent i = null;
if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
i = new Intent(context, StartAUT_Service.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
context.startService(i);
}
}
After I rebooted my device, I can not receive broardcast.
Please help me, thank so much
Starting from Android 3.0, application state was introduced.
All applications are now installed with a state set to inactive, making all it's BroadcastReceivers inactive.
To make the state as active, the user must launch the application at least once and the OS will automatically activate the app and all its BroadcastReceivers.
In your case, you need to add an activity, be it a license agreement or a help page. This will create an icon for your app for the user to click and activate the app.
Note that the application's state will be set to back inactive if the user force-closes the application.
I faced a similar problem: Android ICS not receiving data sms
I hope that solves your problem or at least put you on the right track.
regards,
Ahmad
Try
<uses-permission android:name="android.intent.action.BOOT_COMPLETED" />
below Internet's uses permission
You need to do the following to overcome this security feature.
If your API level is below 12, then set the following to your intent before broadcasting it:
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | 32);
Otherwise, add the following flag to include packages which are marked as Stopped too:
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent. FLAG_INCLUDE_STOPPED_PACKAGES);

How to start service project on android ?

i need to write simple android application that run on the background and read any sms message that comes - and do some change on the massage that come from phone number XXXX .
This application dont need any GUI - so i dont need to use any Activity.
I started a new project on Eclipse and there is no option to define that the project will be service - just define it as activity.
How can i start a project to be a service ?
Add to AndroidManifest.xml:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<service android:name=".YourService" />
<receiver android:name="com.your.package.AutoStart">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Create class AutoStart.java:
public class AutoStart extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Intent startServiceIntent = new Intent(context, YourService.class);
context.startService(startServiceIntent);
}
}
The OS will call your AutoStart.onReceive() method when the device is booted. Note that this may be before the SD card is mounted. When you install the apk, the system will look at your manifest and your app will be registered with the system for you to start on boot.
There's info in the developer guide on how to do this. You have to specify that the app is a service in its manifest. From the guide:
To declare your service, add a element as a child of the
element. For example:
<manifest ... >
...
<application ... >
<service android:name=".ExampleService" />
...
</application>
</manifest>
Here's the link:
http://developer.android.com/guide/topics/fundamentals/services.html

Categories

Resources