I want my service to be started when android is rebooted. I used BroadcastReceiver to do so.
public class autostart extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
MyService1 mYourService = new MyService1();
MainActivity.instance_main.showToast("BroadCast Received...................");
Intent mServiceIntent = new Intent(MainActivity.instance_main, mYourService.getClass());
if (!MainActivity.instance_main.isMyServiceRunning(mYourService.getClass())) {
MainActivity.instance_main.startService(mServiceIntent);
MainActivity.instance_main.showToast("Restarted...................");
}
else {
MainActivity.instance_main.showToast("already running..................");
}
}
}
Receiver in Android Manifest
<receiver android:name=".autostart" android:enabled="true" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
Permissions defined
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
Battery optimization ignore permission also requested in OnCreate()
Intent intent=new Intent();
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:"+MainActivity.instance_main.getPackageName()));
MainActivity.instance_main.startActivity(intent);
But it won't work. Service won't start on reboot. Kindly Suggest me solution.
WE need to register the receiver. Add the following code to OnCreate()
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver mService=new Autostart();
registerReceiver(mService,filter);
However after reboot it wont automatically hit.
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);
}
}
}
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;
}
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;
}
}
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());
}
}
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
public class ScreenReceiver extends BroadcastReceiver {
private boolean screenOff;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
screenOff = true;
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
screenOff = false;
}
}
<receiver
android:name=".ScreenReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
<action android:name="android.intent.action.DREAMING_STARTED" />
<action android:name="android.intent.action.DREAMING_STOPPED" />
<action android:name="android.intent.action.CLOSE_SYSTEM_DIALOGS" />
<action android:name="android.intent.action.SCREEN_ON" />
<action android:name="android.intent.action.SCREEN_OFF" />
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
<action android:name="android." />
</intent-filter>
</receiver>
Not getting any callback on naught and oreo devices,tried on marshmallow devices its working fine .but on oreo devices its not working and also for battery connected and network change receiver not working .
You can not register broadcast receiver in manifest.xml from Oreo.
You can see
Android 8.0 Behavior Changes
Apps cannot use their manifests to register for most implicit
broadcasts (that is, broadcasts that are not targeted specifically at
the app).
Solution
Register your receiver in your related Activity instead. Like this.
public class MainActivity extends AppCompatActivity {
BroadcastReceiver receiver;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction("android.intent.action.LOCKED_BOOT_COMPLETED");
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// todo
}
};
registerReceiver(receiver, filter);
}
#Override
protected void onDestroy() {
super.onDestroy();
if (receiver != null)
unregisterReceiver(receiver);
}
}
You can add action as string same as manifest, if you don't find relevant constant string.
I needed to restore alarm after reboot for this I added this broadcast receiver:
public class ClsRestartAlarm extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
Logging.logMessage("Broadcast");
Intent i = new Intent(context, BootService.class);
context.startService(i);
}
}
}
and registered in manifest like this:
<receiver android:name=".classes.ClsRestartAlarm"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
and as result of broadcast I'm doing this:
public class BootService extends IntentService {
public BootService() {
super("boot service");
}
#Override
protected void onHandleIntent(Intent intent) {
AlarmManagerUtils.setStartAlarm();
AlarmManagerUtils.setEndAlarm();
}
}
I guess I'm not receiving BOOT_COMPLETE broadcast in ClsRestartAlarm class, because after restart alarm was not set and I was unable to get notification(the starting alarm start a job scheduler for sending notification and end alarm cancels job scheduler)also I have BOOT_COMPLETE permission like this:
<uses-permission android:name="ANDROID.PERMISSION.RECEIVE_BOOT_COMPLETED"/>
Use WakefulBroadcastReceiver instead. This is my workable solution:
public class BRAutoStart extends WakefulBroadcastReceiver {
private final String BOOT_COMPLETED_ACTION = "android.intent.action.BOOT_COMPLETED";
#Override
public void onReceive(Context ctx, Intent intent) {
_A.APPCTX = ctx.getApplicationContext();
if(intent.getAction().equals(BOOT_COMPLETED_ACTION)){
//code
}
}
}
<receiver android:name=".BRAutoStart">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
I declared in AndroidManifest permission and receiver
<uses-permission android:name="android.permission.REAL_GET_TASKS"/>
<receiver android:name=".UninstallIntentReceiver">
<intent-filter android:priority="0">
<action android:name="android.intent.action.QUERY_PACKAGE_RESTART" />
<data android:scheme="package" />
</intent-filter>
</receiver>
And here is my java class receiver
public class UninstallIntentReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String[] packageNames = intent.getStringArrayExtra("android.intent.extra.PACKAGES");
if(packageNames!=null){
for(String packageName: packageNames){
Log.d("User selected: ",packageName);
}
}
}
When I open settings of other apps it works well - I get notification
(I can see in logs package name of chosen application), but
when I open settings my own application, I don't receive anything