Skip to main content

Why do apps on some Android versions fail to capture audio and video after screen locking or switching to the background?

After screen locking or switching to the background on some Android versions, you may encounter the following issues:

  • On Android devices, remote audio is silent or video is not visible within 1 minute of the device being locked.
  • When the Android app switches to the background during operation, remote audio is silent.

Reason

  • Starting from Android 9, the Android system restricts background apps from accessing user data. For more details, see Android 9 behavior changes.
  • Starting from Android 14, the Android system requires apps to specify the necessary foreground service types. If developers set the app's targetSdkVersion to 34 or higher, the system will trigger a capability check when the app runs on devices with Android 14 or higher to verify if the app has correctly declared its foreground service types. If the app fails to integrate foreground services properly, issues such as microphone capture being ineffective and remote audio being silent may occur when the user switches the app to the background. For more details, see Android 14 behavior changes and Required foreground service types.

Solution

To ensure uninterrupted access to microphone, camera, media playback, and other functionalities when your device is locked or your app is in the background, it's crucial to correctly integrate foreground services. This prevents interruptions in audio and video capture due to system restrictions. Agora provides an example project demonstrating how to integrate foreground services. Here are the steps:

  1. In the AndroidManifest.xml file, declare the foreground service privilege (FOREGROUND_SERVICE) and specify the foreground service type (foregroundServiceType). For real-time audio/video interactive apps, you usually need to specify the microphone (microphone), camera (camera), and media playback (mediaPlayback) service types. The example code is as follows:


    _13
    <manifest ...>
    _13
    <!-- Declare front-end service permissions -->
    _13
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    _13
    _13
    <application ...>
    _13
    ...
    _13
    <!-- Specify the type of front desk service -->
    _13
    <service
    _13
    android:name=".YourForegroundService"
    _13
    android:foregroundServiceType="microphone|camera|mediaPlayback" />
    _13
    ...
    _13
    </application>
    _13
    </manifest>

  2. When a service is created, call startForeground to promote the specified service to the foreground. The sample code is as follows:


    _21
    @Override
    _21
    public void onCreate() {
    _21
    super.onCreate();
    _21
    // Get default notifications
    _21
    Notification notification = getDefaultNotification();
    _21
    try {
    _21
    // Depending on the Android version, choose the appropriate way to handle the frontend service
    _21
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
    _21
    // For Android 11 and above, start the foreground service and specify multiple service types
    _21
    int serviceTypes = ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE |
    _21
    ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA |
    _21
    ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK;
    _21
    this.startForeground(NOTIFICATION_ID, notification, serviceTypes);
    _21
    } else {
    _21
    // For Android 11 and below, there is no need to specify a service type, simply start the foreground service
    _21
    this.startForeground(NOTIFICATION_ID, notification);
    _21
    }
    _21
    } catch (Exception ex) {
    _21
    Log.e(TAG, "Error starting foreground service", ex);
    _21
    }
    _21
    }

  3. When the app switches to the background, call startForegroundService to start the service to ensure that the service continues to run. The sample code is as follows:


    _20
    @Override
    _20
    public void onPause() {
    _20
    super.onPause();
    _20
    startRecordingService();
    _20
    }
    _20
    _20
    private void startRecordingService() {
    _20
    if (joined) {
    _20
    // Create an intent
    _20
    Intent intent = new Intent(requireContext(), LocalRecordingService.class);
    _20
    // Depending on the Android version, choose the appropriate way to start the frontend service
    _20
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    _20
    // For Android 8 and above, start the service using startForegroundService
    _20
    requireContext().startForegroundService(intent);
    _20
    } else {
    _20
    // For Android 8 and below, use startService to start the service
    _20
    requireContext().startService(intent);
    _20
    }
    _20
    }
    _20
    }

Additional information

vundefined