9

There are quite a few examples of using BOOT_COMPLETED to start an application when the device boots.. I have attempted to use these example against my Flutter application. Having it start the App. This is for a simply signage app that shows images. Basically similar to a picture frame.

In the example code below, the application is compiling, however, when I reboot a simulator, for example, the code does not appear to have any effect.

My guess is that I am not calling the right code to actually start the application.. I am not a Android developer, so am having issues figuring what is exactly going on. Manifest follows..

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="au.net.digitall.cmplayer">

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<application
    android:name="io.flutter.app.FlutterApplication"
    android:label="cm_player"
    android:icon="@mipmap/ic_launcher"
    tools:ignore="GoogleAppIndexingWarning">
    <activity
        android:name=".MainActivity"
        android:launchMode="singleTop"
        android:theme="@style/cmTheme2"
        android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
        android:hardwareAccelerated="true"
        android:windowSoftInputMode="adjustResize">
        
        <meta-data
            android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
            android:value="true" />
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>

    <receiver
        android:enabled="true"
        android:name=".StartCmPlayerServiceAtBootReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
</application>

Then the StartCmPlayerServiceAtBootReceiver class to start the APP..

package au.net.digitall.cmplayer;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;


public class StartCmPlayerServiceAtBootReceiver extends BroadcastReceiver {

    private static final String TAG = StartCmPlayerServiceAtBootReceiver.class.getSimpleName();

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i(TAG, "BOOT detected");
        if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
            Intent serviceIntent = new Intent(context, MainActivity.class);
            context.startService(serviceIntent);
        }
    }
}

This all compiles and runs, but nothing happens on reboot. Appreciate the help..

Miftakhul Arzak
  • 1,166
  • 1
  • 12
  • 31
James Gardiner
  • 382
  • 2
  • 8
  • You would need to launch your `MainActivity` once after installation, to bring your app out of the _stopped_ state. I'm not sure if that's what you meant "compiles and runs". Beyond that, you're likely to get an Exception in the `BroadcastReceiver`, as starting an `Activity` on that `Context` would require that you add the `Intent.FLAG_ACTIVITY_NEW_TASK` on the `Intent`: https://stackoverflow.com/a/18002674. – Mike M. Dec 11 '18 at 00:51

3 Answers3

5

Thank to very much to Mike M. His suggestion and pointing at the other android based discussion gave me enough info to archive autostart on boot. The code change to the above example follows..

In the StartCmPlayerServiceAtBootReceiver class, Change to

public void onReceive(Context context, Intent intent) {
    if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
        Intent mIntent = new Intent(context, MainActivity.class);
        mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(mIntent);
    }
}

Thanks again, and I hope other flutter devs find this useful.

James Gardiner
  • 382
  • 2
  • 8
0
  1. Create receiver class on kotlin path project_name/android/app/src/main/kotlin/com/example/app/
package com.example.app

import android.content.BroadcastReceiver
import android.content.Context;
import android.content.Intent;

class BootReceiver: BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if (intent.action == Intent.ACTION_BOOT_COMPLETED) {
            val i = Intent(context, MainActivity::class.java)
            i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            context.startActivity(i)
        }
    }
}
  1. Add permission on your manifest
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
  1. Add receiver tag inside application tag on your manifest
<receiver
            android:enabled="true"
            android:exported="true"
            android:name="com.example.app.BootReceiver"
            android:permission="android.permission.RECEIVE_BOOT_COMPLETED">

            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <action android:name="android.intent.action.QUICKBOOT_POWERON" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>

  </receiver>
  1. Add code to open your app after booting was completed on your MainActivity.kt, you can find it on project_name/android/app/src/main/kotlin/com/example/app/
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        var REQUEST_OVERLAY_PERMISSIONS = 100
        if (!Settings.canDrawOverlays(getApplicationContext())) {
            val myIntent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION)
            val uri: Uri = Uri.fromParts("package", getPackageName(), null)
            myIntent.setData(uri)
            startActivityForResult(myIntent, REQUEST_OVERLAY_PERMISSIONS)
            return
        }
    }

don't forget to import this code below on your MainActivity.kt because you need Bundle and Settings package

import android.os.Bundle
import android.provider.Settings

Works on my flutter app, tested on android 11.

Miftakhul Arzak
  • 1,166
  • 1
  • 12
  • 31
0

@Miftakhul Arzak Your answer works perfectly fine for android even on chinese OEM's like Oppo and Vivo even at Android 13.. Thanks for it , it was a live-saver..

If anyone is working on java and wants to do the above code in java ::

AndroidManifest.xml ::-

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

<receiver
 android:enabled="true"
 android:exported="true"
 android:name=".autostart"           
 android:permission="android.permission.RECEIVE_BOOT_COMPLETED">

  <intent-filter>
    <action android:name="android.intent.action.BOOT_COMPLETED" />
    <action android:name="android.intent.action.QUICKBOOT_POWERON" />
    <category android:name="android.intent.category.DEFAULT"/>
  </intent-filter>

</receiver>

MainActivity.java ::-

if(!Settings.canDrawOverlays(getApplicationContext())){
 Intent i=new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
 Uri uri=Uri.fromParts("package",getPackageName(),null);
 i.setData(uri);
 startActivityForResult(i,7);
}

BroadCast Receiver ::-

public class autostart extends BroadcastReceiver {
 @Override
 public void onReceive(Context context, Intent intent) {
  if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
   Intent mIntent = new Intent(context, MainActivity.class);
   mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   context.startActivity(mIntent);
  }
 }
}

THE ONLY THING YOU WILL NEED IS THE AUTO-LAUNCH PERMISSION..