Start Android Activity or Service from the background

Volodymyr Kozhemiakin
Make Android
Published in
3 min readJul 10, 2023

This story is about starting Android Activity or Service from the background of System application. The service can be useful for doing some work or collecting data in the background without UI. Or Activity of other app can be launched from the background BroadcastReceiver.

Photo by Jenny Ueberberg on Unsplash

Let’s consider application that starts Service after boot completed. The application has BroadcastReceiver and background Service without Activity. AndroidManifest.xml contains android.permission.RECEIVE_BOOT_COMPLETED permission and intent filter in receiver with android.intent.action.BOOT_COMPLETED action.

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

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

<application
android:allowBackup="true"
android:persistent="true">

<service
android:name=".MyService"
android:enabled="true"
android:exported="true" />

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

</manifest>

The StartupReceiver is waiting for android.intent.action.BOOT_COMPLETED action from the system and starts MyService. Example of StartupReceiver:

class StartupReceiver : BroadcastReceiver() {

override fun onReceive(context: Context, intent: Intent) {
Log.d(TAG, "onReceive::")
val serviceIntent = Intent(context, MyService::class.java)
context.startService(serviceIntent)
}
}

MyService is doing some work and print log in a loop with time delay. The method onStartCommand(Intent, int, int) returns START_STICKY to re-create the service if this process is killed. Example of MyService:

class MyService : LifecycleService() {

override fun onCreate() {
super.onCreate()
Log.d(TAG, "onCreate::")

lifecycleScope.launch {
while (true) {
Log.d(TAG, "I'm alive...")
delay(DELAY_TIME)
}
}
}

override fun onDestroy() {
Log.i(TAG, "onDestroy::")
super.onDestroy()
}

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
super.onStartCommand(intent, flags, startId)
Log.i(TAG, "onStartCommand::")
return START_STICKY
}

override fun onBind(intent: Intent): IBinder? {
super.onBind(intent)
Log.i(TAG, "onBind::")
return null
}
}

On practices, the service was terminated after some time by the system. For example, it takes 1 min 15 sec and it depends on device. Documentation explains that app has several minutes in which it is still allowed to use service and after this period of time the app is considered to be idle. So, the system stops the app’s background services, just as if the app had called the services Service.stopSelf() methods.

To make the background service work over a long period, we have 2 options:

  1. Push apk to privileged partition /system/priv-app/. For this we need a userdebug build type of firmware.
  2. Use android:sharedUserId="android.uid.system" in AndroidManifest.xmland sign apk by platform key.

These methods were previously described in the “Granting signature and signatureOrSystem permissions of OEM applicationarticle.

However, the system may still terminate service in exceptional cases or when resource constraints become severe, even for privileged system apps.

If we need service to run reliably over a long period, we can consider implementing strategies such as using a Foreground Service. Also, a System Service can be implemented if it is possible to use AOSP.

The Activity of other app can be launched from the BroadcastReceiver that listening for <action android:name="background.starts.receiver"/> action.

class StartupReceiver : BroadcastReceiver() {

override fun onReceive(context: Context, intent: Intent) {
Log.d(TAG, "onReceive::")
Intent().also { intents ->
intents.component = ComponentName(
"com.example.myapplication",
"com.example.myapplication.MainActivity"
)
intents.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(intents)
}
}
}

After run Activity we got error:

2023-06-15 13:21:52.140   697-2856  ActivityTaskManager     system_process  
W Background activity start [callingPackage:
com.background.starts;
callingUid: 1010151;
appSwitchState: 2;
isCallingUidForeground: false;
callingUidHasAnyVisibleWindow: false;
callingUidProcState: RECEIVER;
isCallingUidPersistentSystemProcess: false;
realCallingUid: 1010151;
isRealCallingUidForeground: false;
realCallingUidHasAnyVisibleWindow: false;
realCallingUidProcState: RECEIVER;
isRealCallingUidPersistentSystemProcess: false;
originatingPendingIntent: null;
allowBackgroundActivityStart: false;
intent: Intent { flg=0x10000000 cmp=com.example.myapplication/.MainActivity };
callerApp: ProcessRecord{1ddd024 3703:com.background.starts/u10a151};
inVisibleTask: false]

It says, we can’t start Activity from the background, cause we did not meet any conditions of method ActivityStarter#shouldAbortBackgroundActivityStart.

We can meet callingAppId == Process.SYSTEM_UID conditions by adding android:sharedUserId="android.uid.system" in AndroidManifest.xmland sign apk by platform key. In this case the callingAppId = 1000 because android.uid.system, also known as SYSTEM_UID or UID 1000, is the user ID assigned to the core system processes and applications in the Android operating system. It has the highest privilege level and is responsible for managing critical system functions and resources. So, AndroidManifest.xmlwill look like:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.background.starts"
android:sharedUserId="android.uid.system">

<application
android:allowBackup="true"
android:persistent="true">

<receiver android:name=".StartupReceiver"
android:exported="true">
<intent-filter>
<action android:name="background.starts.receiver" />
</intent-filter>
</receiver>
</application>

</manifest>

FYI using android:sharedUserId is deprecated as of API level 29, its use is strongly discouraged and might be removed in a future version of Android.

--

--

Volodymyr Kozhemiakin
Make Android

Android Engineer | Mobile | Automotive | Enterprise | AOSP | Applications, Android Framework, System Services, HAL, Kernel | C/C++ | Java | Kotlin