Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash on apps targeting Android 14 (Unable to start foreground service) #1026

Closed
wisemuji opened this issue Mar 6, 2024 · 5 comments · Fixed by #1045
Closed

Crash on apps targeting Android 14 (Unable to start foreground service) #1026

wisemuji opened this issue Mar 6, 2024 · 5 comments · Fixed by #1045
Assignees
Labels
bug Something isn't working

Comments

@wisemuji
Copy link

wisemuji commented Mar 6, 2024

Describe the bug
App targeting Android 14 gets crash when run on Android 14 devices. It occurs regardless of whether I call LaunchCallPermissions or not. Removing the targetSdk = 34 from the gradle file or running it on devices below Android 14 does not crash. After granting permissions to the app manually, it works well too.

Tried out other demo apps on Android 14 devices, and they also crashed.

I think the problem is linked to the changes that require foreground service types in Android 14, as shown by the stacktrace.

java.lang.RuntimeException: Unable to start service io.getstream.video.android.core.notifications.internal.service.CallService
See all stacktraces
java.lang.RuntimeException: Unable to start service io.getstream.video.android.core.notifications.internal.service.CallService@a43d67e with Intent { cmp=com.wisemuji.zoomclone/io.getstream.video.android.core.notifications.internal.service.CallService (has extras) }: java.lang.SecurityException: Starting FGS with type microphone callerApp=ProcessRecord{7c9412f 17289:com.wisemuji.zoomclone/u0a194} targetSDK=34 requires permissions: all of the permissions allOf=true [android.permission.FOREGROUND_SERVICE_MICROPHONE] any of the permissions allOf=false [android.permission.CAPTURE_AUDIO_HOTWORD, android.permission.CAPTURE_AUDIO_OUTPUT, android.permission.CAPTURE_MEDIA_OUTPUT, android.permission.CAPTURE_TUNER_AUDIO_INPUT, android.permission.CAPTURE_VOICE_COMMUNICATION_OUTPUT, android.permission.RECORD_AUDIO]  and the app must be in the eligible state/exemptions to access the foreground only permission
                                                                                                    	at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4839)
                                                                                                    	at android.app.ActivityThread.-$$Nest$mhandleServiceArgs(Unknown Source:0)
                                                                                                    	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2289)
                                                                                                    	at android.os.Handler.dispatchMessage(Handler.java:106)
                                                                                                    	at android.os.Looper.loopOnce(Looper.java:205)
                                                                                                    	at android.os.Looper.loop(Looper.java:294)
                                                                                                    	at android.app.ActivityThread.main(ActivityThread.java:8177)
                                                                                                    	at java.lang.reflect.Method.invoke(Native Method)
                                                                                                    	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
                                                                                                    	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
                                                                                                    Caused by: java.lang.SecurityException: Starting FGS with type microphone callerApp=ProcessRecord{7c9412f 17289:com.wisemuji.zoomclone/u0a194} targetSDK=34 requires permissions: all of the permissions allOf=true [android.permission.FOREGROUND_SERVICE_MICROPHONE] any of the permissions allOf=false [android.permission.CAPTURE_AUDIO_HOTWORD, android.permission.CAPTURE_AUDIO_OUTPUT, android.permission.CAPTURE_MEDIA_OUTPUT, android.permission.CAPTURE_TUNER_AUDIO_INPUT, android.permission.CAPTURE_VOICE_COMMUNICATION_OUTPUT, android.permission.RECORD_AUDIO]  and the app must be in the eligible state/exemptions to access the foreground only permission
                                                                                                    	at android.os.Parcel.createExceptionOrNull(Parcel.java:3057)
                                                                                                    	at android.os.Parcel.createException(Parcel.java:3041)
                                                                                                    	at android.os.Parcel.readException(Parcel.java:3024)
                                                                                                    	at android.os.Parcel.readException(Parcel.java:2966)
                                                                                                    	at android.app.IActivityManager$Stub$Proxy.setServiceForeground(IActivityManager.java:6761)
                                                                                                    	at android.app.Service.startForeground(Service.java:862)
                                                                                                    	at androidx.core.app.ServiceCompat$Api34Impl.startForeground(ServiceCompat.java:240)
                                                                                                    	at androidx.core.app.ServiceCompat.startForeground(ServiceCompat.java:172)
                                                                                                    	at io.getstream.video.android.core.notifications.internal.service.CallService.onStartCommand(CallService.kt:224)
                                                                                                    	at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4821)
                                                                                                    	at android.app.ActivityThread.-$$Nest$mhandleServiceArgs(Unknown Source:0) 
                                                                                                    	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2289) 
                                                                                                    	at android.os.Handler.dispatchMessage(Handler.java:106) 
                                                                                                    	at android.os.Looper.loopOnce(Looper.java:205) 
                                                                                                    	at android.os.Looper.loop(Looper.java:294) 
                                                                                                    	at android.app.ActivityThread.main(ActivityThread.java:8177) 
                                                                                                    	at java.lang.reflect.Method.invoke(Native Method) 
                                                                                                    	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552) 
                                                                                                    	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971Caused by: android.os.RemoteException: Remote stack trace:
                                                                                                    	at com.android.server.am.ActiveServices.validateForegroundServiceType(ActiveServices.java:2611)
                                                                                                    	at com.android.server.am.ActiveServices.setServiceForegroundInnerLocked(ActiveServices.java:2322)
                                                                                                    	at com.android.server.am.ActiveServices.setServiceForegroundLocked(ActiveServices.java:1679)
                                                                                                    	at com.android.server.am.ActivityManagerService.setServiceForeground(ActivityManagerService.java:13281)
                                                                                                    	at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:3385)

SDK version

  • 0.5.1

To Reproduce
Steps to reproduce the behavior:

  1. Use Android 14 device
  2. Uninstall the existing app or remove all permissions from the app
  3. Make sure to add targetSdk = 34 block in gradle file
  4. Build & Run
  5. Enter video call
  6. See crash

Expected behavior
Does not crash on Android 14

Device:

  • Vendor and model: Samsung Galaxy S23, Google Pixel 7
  • Android version: 14
@wisemuji wisemuji added the bug Something isn't working label Mar 6, 2024
@skydoves
Copy link
Member

skydoves commented Mar 7, 2024

Thank you so much, @wisemuji, for highlighting this crucial issue! I've just talked with @aleksandar-apostolov about it, and he's committed to examining and resolving it as soon as possible. Given the critical nature of the issue, we want you to know that we will provide you with continuous updates. Your input is invaluable to us!

@jesusjav
Copy link

jesusjav commented Mar 12, 2024

Any idea when this is going to be release? Now i'm using
implementation("io.getstream:stream-video-android-compose:0.4.2") with 34 SDK

@skydoves
Copy link
Member

Hi @jesusjav,

The issue on Android 14 arises since the video call service was launched before getting proper media permissions (audio, foreground service, etc.), so ensuring the required permissions before launching the call service will resolve the Android 14 permission issue.

For now, we'd suggest using the code below:

  1. Add the accompanist-permission dependency to your project.

  2. Add the function below:

@OptIn(ExperimentalPermissionsApi::class)
@Composable
private fun EnsureVideoCallPermissions(onPermissionsGranted: () -> Unit) {
    // While the SDK will handle the microphone permission,
    // its not a bad idea to do it prior to entering any call UIs
    val permissionsState = rememberMultiplePermissionsState(
        permissions = buildList {
            // Access to camera & microphone
            add(Manifest.permission.CAMERA)
            add(Manifest.permission.RECORD_AUDIO)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                // Allow for foreground service for notification on API 26+
                add(Manifest.permission.FOREGROUND_SERVICE)
            }
        },
    )

    LaunchedEffect(key1 = Unit) {
        permissionsState.launchMultiplePermissionRequest()
    }

    LaunchedEffect(key1 = permissionsState.allPermissionsGranted) {
        if (permissionsState.allPermissionsGranted) {
            onPermissionsGranted()
        }
    }
}
  1. Join the video call using the EnsureVideoCallPermissions function.
EnsureVideoCallPermissions {
    call.join(create = true)
}

We will investigate a better way to get proper permissions before/after joining a video call service. Thanks again for reporting this crucial issue! @wisemuji @jesusjav

@skydoves skydoves self-assigned this Mar 15, 2024
@aleksandar-apostolov
Copy link
Collaborator

Hi all,
Thanks again for bringing this to our attention, we didn't experience this issue in our demo-app (see bellow) and only with contributions like these we can find such issues and improve our SDK.

The reason why this does not work is because, as soon as you call call.join() you are already in the call and the foreground service is started.

So basically the following code will crash:

LaunchCallPermissions(call)
call.join()

Why? because LaunchCallPermissions will show the pop-up but call.join() does not wait for the answer to join the call and joins without the required permission.

There are several ways to solve this issue:

  1. Request the permission on a prior screen (lobby screen or similar) with the same LaunchCallPermissions(call), we do this in our demo-app
  2. Wait for the permission to be granted using the callback in LaunchCallPermissions
LaunchCallPermissions(call = call, onPermissionsResult = { permissionResult: Map<String, Boolean> ->
  // you can query the permissionResult map to see if the required permission were granted
  call.join()
})
  1. Do not use the foreground service. In the StreamVideoBuilder there is a flag runForegroundServiceForCalls, if you set this to false the foreground-service is not started. Keep in mind that if you do this, you have to find another way to manage the call if the UI is gone, more or less writing your own foreground service.

The above solutions will work with the SDK you are currently using.

As for the update, there isn't much that can be done in the case where call.join() is invoked without a permission, we have improved the logging in this case, so its more clear what needs to be done to avoid this issue.
We have also added another way to manage the permissions in the SDK and this will be released next week or later, but feel free to checkout the #PR for more details. Also you can use the source code from that PR.

Thanks again for raising this issue and let us know if we can help you any further.

@wisemuji
Copy link
Author

@skydoves @aleksandar-apostolov

Thank you for clarifying the problem and providing solutions.
I've just checked that it works perfectly if I call call.join() it after the permissions have been granted.

Looking forward to see the new updates in the SDK, thank you for the heads-up about the upcoming release. 🙌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants