class AlarmReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Toast.makeText(context,"Ready to wake up?", Toast.LENGTH_LONG).show()
val myIntent = Intent(context,AlarmActivity::class.java)
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(myIntent)
}
}
Manifest:
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.QuickNap">
<activity android:name=".AlarmActivity"
android:screenOrientation="portrait"
android:theme="#style/Theme.NoActioBar"
android:windowSoftInputMode="adjustResize"></activity>
<!-- <receiver-->
<!-- android:name=".AlarmReceiver"-->
<!-- android:process=":remote" />-->
<receiver android:name=".AlarmReceiver"
android:enabled="true"
android:exported="true"
android:process=":remote">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="android.intent.action.REBOOT"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<activity
android:name=".MainActivity"
android:screenOrientation="portrait"
android:theme="#style/Theme.NoActioBar"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
MainActivity:
onTimer = true;
moonImage.setColorFilter(null)
val mIntent = Intent(this, AlarmReceiver::class.java)
val mPendingIntent = PendingIntent.getBroadcast(this, 0, mIntent, PendingIntent.FLAG_UPDATE_CURRENT)
val calendar = Calendar.getInstance()
calendar.add(Calendar.SECOND, minuteSet)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,calendar.timeInMillis,mPendingIntent)
}
else
{
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.timeInMillis, mPendingIntent)
}
hi, i am trying to create a alarm android app using kotlin .
so i created a Reciever, in that reciever i am switching on a activity and in that activity i am playing Sound.
this code works fine as intended on emulator. but on device (Redmi Note 7 pro, MIUI OS). it only works when screen is on and if the app is open.
any idea on how to make sure it switches the screen on when this receiver is invoked?
also i am new to android development, so ELI5. ty
There are plenty of reasons why you cannot bring the app to the foreground. Let's break it down and solve it accordingly:
1- Stock OS Restrictions: : Android is known for the increasing restriction on background tasks. MIUI even surpassed that with more restriction due to their "Battery Optimization" algorithm. First of all, make sure you inform the user that the app CANNOT run in the background or be brought to the foreground if the MIUI Battery Optimization is enabled. Therefore, give the user the ability to go to the Battery Saver option in app's options by giving him a one-click intent. Sadly, there is no programmatic work-around. You can see here a list of manufacturers that enforce their battery saving policies: Don't kill my app!
Xiaomi is not the only manufacturer you have to worry about.
2- Android 10 (API 29) Restrictions: Starting from this particular API, apps can NO LONGER jump to the foreground from the background. Google started putting a lot of restrictions on a lot of permissions and features. Please read more here about which conditions have to be met in order to be able to launch the app that is running in the background: Restrictions on starting activities - API 29
What can you do: You can mess around with different flags and categories as well as parameters to add to the manifest. For example, if you haven't added this permission, make sure you do now:
QUOTED FROM THE LINK ABOVE:
...
The app should be granted the SYSTEM_ALERT_WINDOW permission by the user.
...
You can also try to add different flags and categories, this MAY WELL NOT work, but you can still try and fiddle especially with these two lines:
intent.addCategory(Intent.CATEGORY_LAUNCHER) //You can always add and remove categories
intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
Your best solution yet: You can always inspect an open-source project and see how they dealt with this particular issue. One of my favorites has to be this one: AlarmClock FOSS on GitHub by yuriykulikov
Best of luck.
Go to Settings/Apps/manage apps and select your application then select battery saver and make sure it is on "No restrictions" so your app can run in the background without any restrictions.
If it worked, you should teach the user to do that. write an intent to open the settings and so on.
Related
I have a simple React Native app, with a single activity MainActivity. The app is meant to be used for an online orders system, so it's meant to be "on" all the time. When the app receives a notification I want to open the app if killed, and bring to the foreground if in background. I have made this work in the past with the example code below but it doesn't work anymore, I don't know if it's an Android API change or what. Please also note I'm not an Android developer so bear that in mind.
I'm using OneSignal and here is my notification received handler:
public class SignalReceiver implements OneSignal.OSRemoteNotificationReceivedHandler {
#Override
public void remoteNotificationReceived(Context context, OSNotificationReceivedEvent notification) {
Intent intent = new Intent(context, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
context.startActivity(intent);
Log.d("ONESIGNAL", "OPENED??");
}
}
and this is my AndroidManifest.xml excerpt. The only relevant part should be the <meta-data> tag as that was added as per OneSignal documentation, but pasting other parts in case relevant:
<application
android:name=".MainApplication"
android:label="#string/app_name"
android:icon="#mipmap/ic_launcher"
android:roundIcon="#mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:launchMode="singleTop"
android:windowSoftInputMode="adjustResize"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="com.onesignal.NotificationServiceExtension"
android:value="com.packagename.SignalReceiver"
/>
</application>
The log message display in Logcat in Android Studio so the code is running all fine. I also get a notification 30 seconds after the log shows, so that is also very odd!
I have noticed com.onesignal.NotificationServiceExtension doesn't actually exist if I try to import in code, but I don't know if it's meant to.
Can someone see any problem with my code, and if yes how can I get it to bring the app to foreground?
Edit
I've tried this code in Android versions 11 and 12 on Samsung devices. Standard devices, not kiosk or managed.
I also just noticed if the app has been closed for a few minutes (over 5 minutes) then the app does indeed open up. But not if it's been used recently.
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.ChainLaunchAppListActivity"));
}
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! )
I bet it's repeated question but I need to ask it again. Service cannot start even I've put following code
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver android:name=".MyBroadcastreceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<activity
android:name="com.im.HomeActivity"
android:clearTaskOnLaunch="true"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.im.ListActivity"
android:label="#string/title_activity_list" >
</activity>
<service
android:name="com.im.SyncService"
android:process=":remote" >
</service>
</application>
and
public class MyBroadcastreceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent arg1) {
Intent intent = new Intent(context, SyncService.class);
context.startService(intent);
Log.i("Autostart", "started");
}
}
Help me, please.
Is your BraodcastReciever getting invoked?
if not then the reason could be following:
Starting with 3.1 when applications are installed they are in a
“stopped” state so they will not be able to run until the user
explicitly launches them. Pressing Force Stop will return them to this
state.
once the user runs the app for the first time (and does not Force Stop
it), everything behaves as before — a reboot will cause BOOT_COMPLETED
broadcasts to be received and so on. However, if the user installs the
app, until and unless they run the app manually, no broadcasts will be
received.
So in your case you will have to create launcher activity and make sure you start that launcher activity at least once then you will start receive boot event broadcast.
Source
Starting from Android 3.1, a user must start the application at least once before your application can receive android.intent.action.BOOT_COMPLETED events.
Also android:allowBackup="true" is set in your manifest file, make sure the App is not installed on the SD card. If you are saving to external storage, you will need to setandroid.intent.action.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE instead.
On some phones(like HTC) there is a Fast Boot option, If it is activated, The BOOT_COMPLETE will not be invoked.
Another approach would be to use Intent.ACTION_SCREEN_ON and check if service is running, if it isn't, then start the service. More info available here
I have a basic Android application that is supposed to reboot the phone continuously a set number of times. In order to do this, I need the application to be started upon phone startup. In order to that, I essentially followed the instructions found here, adding the permissions to the manifest and creating a BroadcastReceiver class that starts the activity. Here is some of my relevant code:
public class StartMyServiceAtBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
System.out.println("StartMyServiceAtBootReceiver called.");
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
// Intent activityIntent = new Intent("com.example.rebooter.MainActivity");
Intent activityIntent = new Intent(context,MainActivity.class);
activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(activityIntent);
}
}
}
From the manifest file:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.rebooter"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main" >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</activity>
<service
android:name=".RebootManager"
android:label="Reboot Manager" >
<action android:name="com.example.rebooter.RebootManager" />
</service>
<receiver android:name=".StartMyServiceAtBootReceiver"
android:enabled="true"
android:exported="true"
android:label="StartMyServiceAtBootReceiver" >
<action android:name="android.intent.action.BOOT_COMPLETED" />
</receiver>
</application>
In the Eclipse emulator, the application appears to be working properly. That is, though my emulator isn't rooted and the phone doesn't execute the reboot commands correctly, I do see that, upon startup, the correct activity is started.
Now, when I'm trying it on a particular system running Android 4.0.4, everything in the application is working properly EXCEPT boot upon startup. Any ideas?
I tried to eliminate the possibility of any hardware problems (since I'm not using a commercially-released phone) by installing another application that boots upon startup and confirming that it does indeed boot upon startup, and it does indeed show up under running apps as a cached process after startup.
I would appreciate any help. Let me know if you need any additional information.
There are a number of issues here.
First, you neglected to post StartMyServiceAtBootReceiver, the component you are expecting to get control at boot time, so we cannot comment on whether there are any particular problems with it.
Second, unless something has explicitly executed one of your components (e.g., the user launched MainActivity from the home screen), StartMyServiceAtBootReceiver will never be invoked, on Android 3.1+. Make sure you run your activity before trying a reboot, and see if that helps.
Third, you implemented a constructor on StartupManager, which is a bad idea. Please move this logic to onCreate().
Fourth, your code will likely crash in that constructor, as getApplication() will not return a valid value at this point in the code, particularly since you failed to chain to the superclass' constructor. Again, moving this code to onCreate() will help here.
Fifth, starting an activity from onCreate() of a service (let alone its constructor) is very unusual and may not be appreciated by the user. Moreover, if that service is not doing anything else, you could just as easily start that activity from StartMyServiceAtBootReceiver and skip StartupManager entirely.
Sixth, you have <intent-filter> elements on your services, as if you are expecting third party developers to invoke those services. If that is the case, fine. If not, please remove the <intent-filter> elements and use explicit Intents within the rest of your app code to refer to them (e.g., new Intent(this, StartupManager.class)), for better security. Or, add android:exported="false" to those services, though that is automatic if you remove the <intent-filter> elements.
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);