DEV Community

joe wang
joe wang

Posted on

Android Foreground Services in 2026: What Changed and How to Adapt

If you're an Android developer working with foreground services, 2026 has brought some significant changes you need to know about. Starting with Android 14 (API 34), Google introduced strict foreground service type requirements that affect how apps like screen translators, media players, and location trackers operate.

In this post, I'll walk through what changed, why it matters, and how we adapted our app — Screen Translator — to comply with the new rules.

What Changed in Android 14+

Before Android 14, you could start a foreground service without specifying a type. The system didn't care what your service was doing — as long as you showed a notification, you were good.

Android 14 changed that. Now, every foreground service must declare a foregroundServiceType in the manifest. If you don't, your app will crash with a MissingForegroundServiceTypeException.

Here are the available types:

<service
    android:name=".MyForegroundService"
    android:foregroundServiceType="mediaProjection|camera|microphone|location|dataSync|mediaPlayback|phoneCall|connectedDevice|remoteMessaging|health|systemExempted|shortService|specialUse"
    android:exported="false" />
Enter fullscreen mode Exit fullscreen mode

You must pick the type(s) that match what your service actually does.

The MediaProjection Challenge

For apps that capture the screen — like Screen Translator — the relevant type is mediaProjection. This is one of the most restricted types because screen capture has obvious privacy implications.

Here's what you need to declare in your AndroidManifest.xml:

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

<service
    android:name=".ScreenCaptureService"
    android:foregroundServiceType="mediaProjection"
    android:exported="false" />
Enter fullscreen mode Exit fullscreen mode

And when starting the service in Kotlin:

val serviceIntent = Intent(this, ScreenCaptureService::class.java)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
    startForegroundService(serviceIntent)
} else {
    startForegroundService(serviceIntent)
}
Enter fullscreen mode Exit fullscreen mode

Inside the service, you must call startForeground() with the correct type:

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    val notification = createNotification()

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
        startForeground(
            NOTIFICATION_ID,
            notification,
            ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
        )
    } else {
        startForeground(NOTIFICATION_ID, notification)
    }

    return START_STICKY
}
Enter fullscreen mode Exit fullscreen mode

Android 15: Even More Restrictions

Android 15 (API 35) added another layer. Now, dataSync foreground services have a 6-hour time limit. After that, the system will stop your service. If your app relied on long-running data sync services, you need to rethink your architecture.

For screen translators, the key restriction is that mediaProjection services now require the user to grant permission every time the app starts a new session. You can no longer cache the MediaProjection token across app restarts.

// This no longer works in Android 15+
// val savedToken = sharedPrefs.getString("projection_token", null)

// You must request a new MediaProjection each time
val mediaProjectionManager = getSystemService(MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
val captureIntent = mediaProjectionManager.createScreenCaptureIntent()
startActivityForResult(captureIntent, REQUEST_CODE)
Enter fullscreen mode Exit fullscreen mode

How Screen Translator Adapted

When building Screen Translator, we had to make several architectural changes:

  1. Declared the correct service type: We use mediaProjection for screen capture and specialUse for our floating bubble overlay service.

  2. Handled the per-session permission flow: Instead of caching the projection token, we now guide users through a clean permission flow each time they start a translation session.

  3. Optimized service lifecycle: We stop the foreground service as soon as the user dismisses the floating bubble, rather than keeping it running in the background.

  4. Graceful degradation: On older Android versions, we fall back to the simpler foreground service API without type declarations.

fun startCaptureService(resultCode: Int, data: Intent) {
    val serviceIntent = Intent(context, ScreenCaptureService::class.java).apply {
        putExtra("resultCode", resultCode)
        putExtra("data", data)
    }

    ContextCompat.startForegroundService(context, serviceIntent)
}
Enter fullscreen mode Exit fullscreen mode

Common Pitfalls

Here are mistakes I've seen developers make:

  • Declaring types you don't use: Google Play will reject your app if you declare camera or location foreground service types but don't actually use those capabilities.

  • Not handling the permission dialog: On Android 14+, the MediaProjection permission dialog looks different and includes a "single app" vs "entire screen" option. Make sure your app handles both cases.

  • Forgetting the notification channel: Foreground services still require a notification, and on Android 13+ you need the POST_NOTIFICATIONS permission too.

Testing Tips

Test your foreground service changes on multiple API levels:

// In your test setup
@Test
fun testForegroundServiceType() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
        // Verify service type is declared correctly
        val serviceInfo = packageManager.getServiceInfo(
            ComponentName(context, ScreenCaptureService::class.java),
            PackageManager.GET_META_DATA
        )
        assertTrue(
            serviceInfo.foregroundServiceType and 
            ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION != 0
        )
    }
}
Enter fullscreen mode Exit fullscreen mode

Wrapping Up

The foreground service changes in Android 14 and 15 are significant, but they make sense from a user privacy perspective. As developers, we need to be explicit about what our services do and why they need to run in the foreground.

If you're building an app that uses screen capture, OCR, or floating overlays, these changes will directly affect you. Plan your migration early and test thoroughly across API levels.

For a real-world example of an app that handles all of this, check out Screen Translator on Google Play — it's a floating bubble translator that uses MediaProjection for OCR-based screen translation.


Have questions about foreground services or MediaProjection? Drop a comment below — happy to help!

Top comments (0)