How to subscribe to BOOT_COMPLETED event? - android

I want to subscribe to the BOOT_COMPLETED intent action, which signals the restart of the mobile phone. Once I subscribe I want to schedule some alarms. I have a BroadcastReceiver that listens to the BOOT_COMPLETED action and it gets hit/called if I use android SDK 25. How can I make the code in BroadcastReceiver execute from Android SDK 26 (Oreo) and above ?
When I run the code on sdk 26 I get the error:
system_process W/BroadcastQueue: Background execution not allowed: receiving Intent { act=android.intent.action.BOOT_COMPLETED flg=0x400010 }
I have created a Github repo https://github.com/Ferencz8/BootIntent on a simpler case, which shows exactly how on sdk 25 things work and on 26 they don't.
Here is the AndroidManifest.xml part:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<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/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".BootReceiver"
android:exported="false">
<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"/>
</intent-filter>
</receiver>
</application>
And the BroadcastReceiver:
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
Log.d(BootReceiver.class.getSimpleName(), "In Boot Receiver");
Intent mainActivityIntent = new Intent(context, MainActivity.class);
context.startActivity(mainActivityIntent);
}
}
I have tried in the OnReceive method from the BroadcastReceiver to start a ForegroundService like, but with no luck:
#Override
public void onReceive(final Context context,final Intent intent) {
intent.setClass(context, AlarmBootService.class);
if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(intent);
}
else{
context.startService(intent);
}
}
I have also tried adding other intent actions besides the BOOT_COMPLETED:
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
<action android:name="android.intent.action.REBOOT"/>
In order to simulate the BOOT_COMPLETED action I used the command:
adb shell am broadcast -a android.intent.action.BOOT_COMPLETED
Also, this is my first question so if you have any feedback on how to describe/articulate better my question please do tell :).

Related

Android 10.0 Application startup on BOOT

We have an android application which we intend to start/launch during phone boot.
With some code tries in Android 10, we realized that the launching of app on boot, is not possible after Android 8.0. Previously in Android 6, it was possible.
Even in physical device /phone / emulator Android 10 , we gave permission in AutoStart list our application.
<< Objective: Any way (workaround) to launch app on boot even on latest versions , i.e. Android 8 onwards ? >>
Tries that we made in Android 10: following are 3 sections of code - AndroidManifest.xml, MyActivity.java, MyBroadcastReceiver.java
1)AndroidManifest.xml
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /><uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<activity android:name=".MainActivity" android:launchMode="singleTop" android:theme="#style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<receiver android:name=".MyBroadcastReceiver" android:enabled="true" android:exported="true" android:permission="android.permission.RECEIVE_BOOT_COMPLETED" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
2)MyActivity.java
public class MainActivity extends FlutterActivity {
#java.lang.Override
protected void onCreate(android.os.Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// "Display pop up window"
if (!Settings.canDrawOverlays(getApplicationContext())) {
startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION));
}
Log.d(TAG, "-------- onCreate -------"); // this is printed
}
}
3)MyBroadcastReceiver.java
public class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
Intent i = new Intent(context, MainActivity.class);
i.setAction(Intent.ACTION_MAIN);
i.addCategory(Intent.CATEGORY_LAUNCHER);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(i);
Log.d(TAG, "------ tried to launch MainActivity -------"); // this is printed
}
}
}
Starting the app on boot can be annoying to the user. You can start a Foreground Service instead. The BOOT_COMPLETE intent can be in many different form depending on your device. I have tried to capture all of them here.
In your Manifest:
<receiver android:name=".receiver.BootReceiver" // YOUR RECEIVER HERE
android:enabled="true"
android:exported="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.ACTION_BOOT_COMPLETED" />
<action android:name="android.intent.action.REBOOT" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
<action android:name="android.intent.action.ACTION_SHUTDOWN" />
</intent-filter>
</receiver>
And in the receiver:
class BootReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// START FOREGROUND SERVICE HERE
}
}
If your app can get "SYSTEM_ALERT_WINDOW" permission (Draw Over Apps) the app wont get terminated after auto boot on Android 10 onwards.
So you need to display this settings activity and ask the user to enable it:
if (!Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, 0);
}
This is mentioned in the docs last bullet.

How to create an application that starts the service after boot up sequences are finished?

I want to create an app that starts the service after rebooted, but I do not want to show the UIā€“just like the service run in the background silently. I can create it,but after rebooted the application crashes. Because, MainActivity had not launched and I don't want to launch any activity. How do I solve this problem?
My manifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.galleryapp">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.CAMERA" />
<application
android:name=".App"
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/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".CameraEventReceiver"
android:enabled="false">
<intent-filter>
<action android:name="com.android.camera.NEW_PICTURE" />
</intent-filter>
</receiver>
<receiver android:name="com.galleryapp.RebootDeviceReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service
android:name=".BackgroundService"
android:exported="true" />
</application>
And my receiver class:
public class RebootDeviceReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent serviceIntent = new Intent(context, BackgroundService.class);
context.startService(serviceIntent);
}
}
You need to write a BroadcastReceiver and register it in your Manifest file.
<receiver android:name="your.package.BootCompletedReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
From your BroadcastReceiver you can then start a service. For example, in my code I'm using a JobIntentService.
public class BootCompletedReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent msgIntent = new Intent(context, MyJobIntentService.class);
msgIntent.setAction(MyJobIntentService.ACTION_RESCHEDULE);
MyJobIntentService.enqueueWork(context, msgIntent);
}
}
If you want your service to run for a longer amount of time, you need to run it as a foreground service, at least for newer Android versions.

Service does not start when the phone is started

I'm pretty new to android programming. I'm trying to start a service when the phone is started but it does not work. I've already seen other question done by other users but no one worked till now. This is my broadcast receiver.
public class StartBoot extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
Intent intent1 = new Intent(context,MyService.class);
context.startService(intent1);
}
}
}
and this is my manifest
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<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/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".StartBoot">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"></service>
</application>
In the log i read this
W/BroadcastQueue: Permission Denial: receiving Intent { act=android.intent.action.BOOT_COMPLETED flg=0x9000010 (has extras) } to com.google.android.apps.docs/.app.NotificationChannelReceiver requires android.permission.RECEIVE_BOOT_COMPLETED due to sender null (uid 1000)
Thank you in advance for the answers
Remove
<category android:name="android.intent.category.DEFAULT"/>
from the <intent-filter> inside <receiver> tag. This category is only needed for <intent-filter> inside of <activity> declaration. For a <receiver> you only need the ACTION.
The error message you posted has nothing to do with your application, it is complaining about another application.

My app can't receive BOOT_COMPLETED broadcast

I am working on an app which needs receive BOOT_COMPLETED broadcast when the device boots.
According to the documents in Android Developers, I already know that since android 3.1, apps that never run after installing or force killed by user will not receive the boot broadcast when device boots, so with the rules, how can I receive boot broadcast? By the way, I have already tried open my app when boot is finished, but it is still not working.
Here's the code:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.guoyonghui.todo"
android:installLocation="auto">
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
android:name=".BaseApplication"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".tasks.TasksActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".taskdetail.TaskDetailActivity"/>
<activity android:name=".addedittask.AddEditTaskActivity"/>
<activity android:name=".statistics.StatisticsActivity"/>
<receiver android:name=".alarm.AlarmReceiver">
<intent-filter>
<action android:name="com.guoyonghui.todo.alarm.ACTION_TASK_ALARM"/>
</intent-filter>
</receiver>
<receiver
android:name=".alarm.BootReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
</application>
</manifest>
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Toast.makeText(context, action, Toast.LENGTH_SHORT).show();
Log.d("AlarmReceiver", action);
if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
TasksRepository tasksRepository = TasksRepository.getInstance(TasksLocalDataSource.getInstance(context));
List<Task> tasks = tasksRepository.loadTasks();
for (Task task : tasks) {
if (task.isActive()) {
AlarmReceiver.setAlarm(context, task);
}
}
}
}
}
You don't want to use the Default category in this case. According to the documentation of this category, it is used for the following purpose:
Set if the activity should be an option for the default action (center press) to perform on a piece of data. Setting this will hide from the user any activities without it set when performing an action on some data. Note that this is normally -not- set in the Intent when initiating an action -- it is for use in intent filters specified in packages. (Emphasis mine)
See the list of categories and what they're for here:
https://developer.android.com/reference/android/content/Intent.html

Start an Activity on Phone Boot in Android

I want to start my application automatically when the phone boots.
I declared a BroadcastReceiver in the manifest file.
<receiver android:name=".Autostart">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
I made a java file for the receiver.
Autostart.java
public class Autostart extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
Intent pushIntent = new Intent(context, MushTouchActivity.class);
pushIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(pushIntent);
}
}
}
But, the application does not launch when I switch my phone on. Can anyone tell me what I am missing here ?
try your if statement like this:
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
Intent i = new Intent(context, MushTouchActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
In case you are on Android 3.1 or newer:
Make sure that you started your application at least once manually (e.g. by opening it from the app drawer). Otherwise your app is marked as stopped by the system:
Applications are in a stopped state when they are first installed but are not yet launched
Stopped apps do not receive any broadcast intents, including BOOT_COMPLETED.
See Android 3.1. Platform - Launch controls on stopped applications for more information.
The best answer would be to show a Notification and ask the user to launch the app from that notification and use a pending intent for that activity in the notification.
Tested on Android 10
1. Create A Broadcast Listener
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() == "android.intent.action.ACTION_SHUTDOWN") {
// Your tasks for shut down
} else {
// Your tasks for Boot up
}
}
}
2. Config Manifest
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:theme="#style/AppTheme">
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.ACTION_BOOT_COMPLETED" />
<action android:name="android.intent.action.REBOOT" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
<action android:name="android.intent.action.ACTION_SHUTDOWN" />
</intent-filter>
</receiver>
</application>
If you search for a sample application code for working with services in background and control actions on screen off/on then visit this repo:
https://github.com/varunon9/DynamicWallpaper
you can update this repo source code with step 1 and 2 for control boot and shutdown events in addition to screen on/off.

Categories

Resources