21

I have an application that starts an Intent after the boot that works from Android 6 to Android 9 API level 28.

But this code does not work on Android 10 API level 29, Broadcast simply does not receive any events and does not run onReceive on MyClassBroadcastReceiver after the boot. Is there any extra permission on Android 10 or configuration that needs to be done?

Dry part of the example: Manifest:

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.softniels.autostartonboot">

<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>
    <service
        android:name="com.softniels.autostartonboot.ForegroundService"
        android:label="My Service">
        <intent-filter>
            <action android:name="com.softniels.autostartonboot.ForegroundService" />
        </intent-filter>
    </service>

    <receiver
        android:name=".StartMyServiceAtBootReceiver"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <action android:name="android.intent.action.QUICKBOOT_POWERON" />
        </intent-filter>
    </receiver>

</application>

Here the part that doesn't run on Android 10.

public class StartMyServiceAtBootReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
            Log.i("onReceive", "call onReceive ACTION_BOOT_COMPLETED");
            Intent i = new Intent(context, MainActivity.class);
            i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(i);
        }
    }
}
Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
Marcos Nielsen
  • 311
  • 1
  • 2
  • 3

4 Answers4

20

I know that this may be old but I have faced the same problem and according to this: https://developer.android.com/guide/components/activities/background-starts

The easiest solution I came up with was simply adding

    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

And setting up the receiver:

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

To the manifest.

Receiver code:

@Override
public void onReceive(Context context, Intent intent) {
    if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
//            Intent n =  context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
 //            n.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | 
 //    Intent.FLAG_ACTIVITY_CLEAR_TASK);
 //            context.startActivity(n);

        Intent myIntent = new Intent(context, MainActivity.class);
        myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(myIntent);
    }
}

Both options work. The only downside I see is that it takes rather a while for app to load (can be up to 10 seconds from my testings)

Leaving this here for other people if they encounter this as well. This only applies to android 10 and up. There is a need to request "Display over other apps" permission

This requires drawing overlay, which can be done with:

if (!Settings.canDrawOverlays(getApplicationContext())) {
            Intent myIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
            Uri uri = Uri.fromParts("package", getPackageName(), null);

            myIntent.setData(uri);
            startActivityForResult(myIntent, REQUEST_OVERLAY_PERMISSIONS);
            return;
        }
Reno
  • 33,594
  • 11
  • 89
  • 102
Dan Baruch
  • 1,063
  • 10
  • 19
  • 2
    This worked for me, too, but only after adding `if (!Settings.canDrawOverlays(getApplicationContext())) { startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION)); }` to `MainActivity.onCreate()`, starting the app once manually and granting the permission. (See [android.permission.SYSTEM_ALERT_WINDOW](https://developer.android.com/reference/android/Manifest.permission#SYSTEM_ALERT_WINDOW).) – legolas108 Sep 16 '20 at 21:09
  • Does it working in android 10 i also facing this problem please any solution for this – Prototype Sep 18 '20 at 20:17
  • @legolas108 yes, I have forgotten to add that requiring the permission is needed. I will add it. – Dan Baruch Sep 22 '20 at 09:38
  • 1
    @prototype86 yes, this works specifically for Android 10 – Dan Baruch Sep 22 '20 at 09:38
  • Hello @Dan Baruch, i had tried the same one and same implemented i did but still it does not working, it does not start when device boot – Navin Oct 22 '20 at 04:17
  • @Navin did you make sure you have the required permissions? There's no reason for this not to work. – Dan Baruch Oct 22 '20 at 06:18
  • @Dan Baruch i had given all the permission still when i reboot the device the broadcast does not trigger on boot completed it's for android 10 and i had added permission to enable overlay app, still does not work my device is opp f11 pro – Navin Oct 22 '20 at 06:34
  • @Navin either post code or maybe make sure you build your receiver properly, perhaps there's an error there? – Dan Baruch Oct 22 '20 at 06:37
  • @Dan Baruch give me some time i will share my code with you, so you can review – Navin Oct 22 '20 at 06:43
  • Hello @Dan Baruch please find here is the example code i had made, can you please check and let me know what is the issue i am facing https://github.com/navinpanchal3373/SampleBootCompleted – Navin Oct 22 '20 at 08:54
  • 1
    Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/223444/discussion-between-dan-baruch-and-navin). – Dan Baruch Oct 22 '20 at 09:08
  • @Navin someone had the same issue and in hes phone he had to add another setting. Here is the link, see if it helps in any way https://stackoverflow.com/questions/64642362/android-10-0-application-startup-on-boot?noredirect=1#comment114326168_64642362 – Dan Baruch Nov 03 '20 at 08:13
  • How to implement it on flutter? – Miftakhul Arzak Jan 27 '22 at 04:25
  • @MiftakhulArzak no clue how to use on flutter, sorry. – Dan Baruch Jan 27 '22 at 10:55
  • @DanBaruch Thanks, your code works on flutter. https://stackoverflow.com/q/70795926/11445944 – Miftakhul Arzak Feb 04 '22 at 01:50
  • I tried to follow the instruction but it doesnit work for me in Google TV with Android TV 11. – Tobia Mar 28 '23 at 09:20
  • This was tested on normal Android, I have no clue about Android TV and it's capabilities and permission etc – Dan Baruch Mar 29 '23 at 08:53
1

Guess I found a 'solution' for me.

    public class StartMyServiceAtBootReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
                Log.e(TAG, "launching from special > API 28 (" + Build.VERSION.SDK_INT + ")"); // You have to schedule a Service
                JobServiceScheduler jobServiceScheduler = new JobServiceScheduler(context);
                boolean result = jobServiceScheduler.scheduleMainService(20L); // Time you will wait to launch
            } else {
                Log.e(TAG, "launching from normal < API 29"); // You can still launch an Activity 
                try {
                    Intent intentMain = new Intent(context, YourActivity.class);
                    intentMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    if (Build.VERSION.SDK_INT < 28) {
                        context.startService(intentMain);
                    } else {
                        context.startForegroundService(intentMain);
                    }
                } catch (ActivityNotFoundException ex) {
                    Log.e(TAG, "ActivityNotFoundException" + ex.getLocalizedMessage());
                }
            }
    }

    boolean scheduleMainService(Long segundos) {
        ComponentName serviceComponent = new ComponentName(context, YourService.class);
        JobInfo.Builder builder = getCommonBuilder(serviceComponent, YOUR_SERVICE_JOB_ID);
        builder.setMinimumLatency(TimeUnit.SECONDS.toMillis(segundos / 2)); // wait at least
        builder.setOverrideDeadline(TimeUnit.SECONDS.toMillis(segundos)); // maximum delay
        PersistableBundle extras = new PersistableBundle();
        extras.putLong("time", segundos);
        builder.setExtras(extras);

        JobScheduler jobScheduler = getJobScheduler(context);
        if (jobScheduler != null) {
            jobScheduler.schedule(builder.build());
            return true;
        } else {
            return false;
        }
    }
Carlos.V
  • 409
  • 6
  • 13
1

context.startActivity() is not launching, I solved it the following way:

  private void restartApp( Context mContext) {
    try {
        long restartTime = 1000*5;
        Intent intents = mContext.getPackageManager().getLaunchIntentForPackage(mContext.getPackageName());
        PendingIntent restartIntent = PendingIntent.getActivity(mContext, 0, intents, PendingIntent.FLAG_ONE_SHOT);
        AlarmManager mgr = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            mgr.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + restartTime, restartIntent);

        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            mgr.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + restartTime, restartIntent);
        }
    } catch (Exception e) {
        Log.e(TAG, e.getMessage());
    }
}
Roberto Caboni
  • 7,252
  • 10
  • 25
  • 39
jerome
  • 11
  • 1
1

I solved it with this permission in the manifest:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> 

And in the main activity :

    if (!Settings.canDrawOverlays(getApplicationContext())) {
        startActivity(Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION));
    }

The correct import for Settings is:android.provider

The first time the app boots the permission will be prompted for controlling which apps can draw on top of other apps, the next device will start the application will boot up using the typical broadcast receiver.

Here is the doc

enter image description here