Broadcast Receiver Not Working After Device Reboot in Android

Broadcast Receiver Not Working After Device Reboot in Android

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.

BroadcastReceiver is not working after reboot

I just found the solution!

AndroidManifest.xml

<receiver
android:name="com.example.a52780.nontifications.AlarmReceiver"
android:enabled="true"
android:exported="false"
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" />
</intent-filter>
</receiver>

<service
android:name="com.example.a52780.nontifications.BootService"
android:enabled="true"
android:exported="false"/>

Also I added BootService.java

private void setAlarm(Intent intent) {
int notificationId = intent.getIntExtra("notificationId", 0);
String text = intent.getStringExtra("text");
Intent mainIntent = new Intent(this, MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, mainIntent, 0);
NotificationManager myNotificationManager =
(NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
Notification.Builder builder = new Notification.Builder(this);
builder.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle("Wake up!")
.setContentText(text)
.setWhen(System.currentTimeMillis())
.setContentIntent(contentIntent);
myNotificationManager.notify(notificationId, builder.build());
}

@Override
protected void onHandleIntent(@Nullable Intent intent) {
setAlarm(intent);
Intent service = new Intent(this, BootService.class);
stopService(service);
}

AlarmReceiver.java

private static final String BOOT_COMPLETED =
"android.intent.action.BOOT_COMPLETED";
private static final String QUICKBOOT_POWERON =
"android.intent.action.QUICKBOOT_POWERON";

@Override
public void onReceive(Context context, Intent intent) {

// Get id & message from Intent
int notificationId = intent.getIntExtra("notificationId", 0);
String message = intent.getStringExtra("text");

String action = intent.getAction();
if (BOOT_COMPLETED.equals(action) ||
QUICKBOOT_POWERON.equals(action)) {

Intent service = new Intent(context, BootService.class);

intent.putExtra("notificationId", notificationId);
intent.putExtra("text", message);

context.startService(service);
}
}

I changed code in MainActivity that calls intent as well.
Old:

Intent intent = new Intent(MainActivity.this, AlarmReceiver.class);
intent.putExtra("notificationId", notificationId);
intent.putExtra("text", text);
intent.putExtra("alarmStartTime", alarmStartTime);
PendingIntent alarmIntent = PendingIntent.getBroadcast(MainActivity.this, notificationId, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarm = (AlarmManager) getSystemService(ALARM_SERVICE);

Idk why, but it works after adding

intent.setAction("android.intent.action.BOOT_COMPLETED");
intent.setAction("android.intent.action.QUICKBOOT_POWERON");

Android After Reboot Broadcast Receiver is not running

try to put this line in your receiver's intent-filter.

<action android:name="android.intent.action.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE" />

If your application is installed on the SD card, you should register this to get the android.intent.action.BOOT_COMPLETED event.

Updated: Since your app is using alarm service, it should not be installed on external storage. Reference: http://developer.android.com/guide/topics/data/install-location.html



Related Topics



Leave a reply



Submit