This is a table on all android boot where on receive event trigger your application:
| State | Security Status | getMySharedPreferences Result | Download/ Folder Access |
| 1. SIM PIN | OS Kernel is paused | Receiver won't run. | Blocked. |
| 2. Pattern/PIN | Direct Boot Mode | Success! (With your new code) | Fail. (Shared Storage is still encrypted) |
| 3. No Security | Full Boot | Success! | Success! |
| 4. SIM + Pattern | Double Lock | Receiver won't run. | Blocked. |
Base of state of boot above, here is onReceive() skeleton code
public class MyBootReceiver extends BroadcastReceiver {
// simple state to prevent double running
private static boolean isRunning = false;
@Override
public void onReceive(Context context, Intent intent) {
// state of boot device
String action = intent.getAction();
if (action == null) return;
switch (action) {
case Intent.ACTION_LOCKED_BOOT_COMPLETED:
// STAGE 1: Phone just turned on, PIN screen is visible.
// DO: Check SharedPreferences (Device Protected) only.
break;
case Intent.ACTION_USER_UNLOCKED:
// STAGE 2: User just entered PIN.
// DO: Access Contacts and Folders now.
break;
case Intent.ACTION_BOOT_COMPLETED:
// STAGE 3: System is fully initialized. if (isRunning) return; // Prevent double execution
isRunning = true; // DO: Final cleanup or scheduling.
break;
case "android.intent.action.ALARM_MATCHED": // Your custom alarm action
// DO: The actual backup if triggered by AlarmManager.
break;
}
Permission and service for on boot receiver in android manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
...
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
...
...
<application
...
<receiver
android:name=".MyBootReceiver"
android:enabled="true"
android:exported="true"
android:directBootAware="true"
>
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED"/>
<action android:name="android.intent.action.USER_UNLOCKED" />
</intent-filter>
</receiver>
...
Recommended boot receiver (gemini ai)
public class MyBootReceiver extends BroadcastReceiver {
// simple state to prevent double running
private static boolean isRunning = false;
@Override
public void onReceive(Context context, Intent intent) {
// state of boot device
String action = intent.getAction();
if (action == null) return;
switch (action) {
case Intent.ACTION_LOCKED_BOOT_COMPLETED:
// Phone is locked. Use Device Protected Storage to schedule the next alarm.
// Do NOT try to read contacts or write files here.
break;
case Intent.ACTION_USER_UNLOCKED:
case Intent.ACTION_BOOT_COMPLETED:
// FULL BOOT / UNLOCKED. if (isRunning) return; // Prevent double execution
isRunning = true; // This is where you run your overdue check logic.
break;
case "android.intent.action.ALARM_MATCHED":
// DO something, it is the time
break;
}
}