flutter-webrtc icon indicating copy to clipboard operation
flutter-webrtc copied to clipboard

App crash in Android 14

Open harshmdr opened this issue 1 year ago • 20 comments

E/AndroidRuntime( 7187): java.lang.SecurityException: Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION

I am using flutter_webrtc: 0.9.27. var stream = await navigator.mediaDevices.getDisplayMedia({ 'video': {'deviceId': 'broadcast'}, 'audio': false });

Any solution?

harshmdr avatar Jul 17 '24 03:07 harshmdr

call this method Helper.requestCapturePermission() before navigator.mediaDevices.getDisplayMedia

Diya-Yi avatar Jul 19 '24 09:07 Diya-Yi

Thank you @Diya-Yi

harshmdr avatar Jul 19 '24 09:07 harshmdr

Not working after set targetSdversion to 34

Failed to handle method call E/MethodChannel#FlutterWebRTC.Method( 6423): java.lang.SecurityException: Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION E/MethodChannel#FlutterWebRTC.Method( 6423): at android.os.Parcel.createExceptionOrNull(Parcel.java:3057) E/MethodChannel#FlutterWebRTC.Method( 6423): at android.os.Parcel.createException(Parcel.java:3041) E/MethodChannel#FlutterWebRTC.Method( 6423): at android.os.Parcel.readException(Parcel.java:3024) E/MethodChannel#FlutterWebRTC.Method( 6423): at android.os.Parcel.readException(Parcel.java:2966) E/MethodChannel#FlutterWebRTC.Method( 6423): at android.media.projection.IMediaProjection$Stub$Proxy.start(IMediaProjection.java:313) E/MethodChannel#FlutterWebRTC.Method( 6423): at android.media.projection.MediaProjection.(MediaProjection.java:84) E/MethodChannel#FlutterWebRTC.Method( 6423): at android.media.projection.MediaProjection.(MediaProjection.java:75) E/MethodChannel#FlutterWebRTC.Method( 6423): at android.media.projection.MediaProjectionManager.getMediaProjection(MediaProjectionManager.java:236) E/MethodChannel#FlutterWebRTC.Method( 6423): at com.cloudwebrtc.webrtc.OrientationAwareScreenCapturer.startCapture(OrientationAwareScreenCapturer.java:123) E/MethodChannel#FlutterWebRTC.Method( 6423): at com.cloudwebrtc.webrtc.GetUserMediaImpl.getDisplayMedia(GetUserMediaImpl.java:559) E/MethodChannel#FlutterWebRTC.Method( 6423): at com.cloudwebrtc.webrtc.GetUserMediaImpl.getDisplayMedia(GetUserMediaImpl.java:511) E/MethodChannel#FlutterWebRTC.Method( 6423): at com.cloudwebrtc.webrtc.MethodCallHandlerImpl.getDisplayMedia(MethodCallHandlerImpl.java:1404) E/MethodChannel#FlutterWebRTC.Method( 6423): at com.cloudwebrtc.webrtc.MethodCallHandlerImpl.onMethodCall(MethodCallHandlerImpl.java:634) E/MethodChannel#FlutterWebRTC.Method( 6423): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:267) E/MethodChannel#FlutterWebRTC.Method( 6423): at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:292) E/MethodChannel#FlutterWebRTC.Method( 6423): at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:319) E/MethodChannel#FlutterWebRTC.Method( 6423): at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(Unknown Source:12) E/MethodChannel#FlutterWebRTC.Method( 6423): at android.os.Handler.handleCallback(Handler.java:958) E/MethodChannel#FlutterWebRTC.Method( 6423): at android.os.Handler.dispatchMessage(Handler.java:99) E/MethodChannel#FlutterWebRTC.Method( 6423): at android.os.Looper.loopOnce(Looper.java:205) E/MethodChannel#FlutterWebRTC.Method( 6423): at android.os.Looper.loop(Looper.java:294) E/MethodChannel#FlutterWebRTC.Method( 6423): at android.app.ActivityThread.main(ActivityThread.java:8177) E/MethodChannel#FlutterWebRTC.Method( 6423): at java.lang.reflect.Method.invoke(Native Method) E/MethodChannel#FlutterWebRTC.Method( 6423): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552) E/MethodChannel#FlutterWebRTC.Method( 6423): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971) E/MethodChannel#FlutterWebRTC.Method( 6423): Caused by: android.os.RemoteException: Remote stack trace: E/MethodChannel#FlutterWebRTC.Method( 6423): at com.android.server.media.projection.MediaProjectionManagerService$MediaProjection.start(MediaProjectionManagerService.java:940) E/MethodChannel#FlutterWebRTC.Method( 6423): at android.media.projection.IMediaProjection$Stub.onTransact(IMediaProjection.java:192) E/MethodChannel#FlutterWebRTC.Method( 6423): at android.os.Binder.execTransactInternal(Binder.java:1339) E/MethodChannel#FlutterWebRTC.Method( 6423): at android.os.Binder.execTransact(Binder.java:1275) E/MethodChannel#FlutterWebRTC.Method( 6423):

harshmdr avatar Jul 19 '24 10:07 harshmdr

When I do a fresh install and then

await Helper.requestCapturePermission()
var stream = await navigator.mediaDevices.getDisplayMedia({
'video': {'deviceId': 'broadcast'},
'audio': false
});

then gives error but after restart again then it works properly. Looks like android is not listening permission properly without hard reload.

harshmdr avatar Jul 19 '24 11:07 harshmdr

@Diya-Yi can you please help here?

harshmdr avatar Jul 19 '24 11:07 harshmdr

Also now it shows me 2 popups to start recording after adding await Helper.requestCapturePermission()

harshmdr avatar Jul 19 '24 12:07 harshmdr

hi @harshmdr-devslane,

Add this in your AndroidManifest.xml

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

Before call getDisplayMedia, add this:

final isGranted = await Helper.requestCapturePermission();

if (!isGranted) return;

lambiengcode avatar Aug 03 '24 03:08 lambiengcode

I am using the same code and I have got isGranted is true after allow but fails java.lang.SecurityException: Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION at only first time and then after restart, it is working fine.

harshmdr avatar Aug 03 '24 04:08 harshmdr

I am using android Emulator so may be the reason of it. I will try in real device and then let you know. Thanks @lambiengcode

harshmdr avatar Aug 03 '24 04:08 harshmdr

@lambiengcode Not working first time only.

harshmdr avatar Aug 05 '24 06:08 harshmdr

final isGranted = await Helper.requestCapturePermission();

if (!isGranted) return;

// start foreground service

var stream = await navigator.mediaDevices.getDisplayMedia({

Have you started the foreground service yet? @harshmdr-devslane

lambiengcode avatar Aug 05 '24 08:08 lambiengcode

yes, i have stared foreground service using flutter_background

harshmdr avatar Aug 05 '24 08:08 harshmdr

Is the sequence matters? My sequence is

  1. Start foreground service while app init.[One time]
  2. Helper.requestCapturePermission() [while start broadcasting everytime]
  3. navigator.mediaDevices.getDisplayMedia [Everytime]

harshmdr avatar Aug 05 '24 08:08 harshmdr

I changed the sequence but still same result. Not working for first time.

harshmdr avatar Aug 05 '24 09:08 harshmdr

This error is because Android 14 requires android:foregroundServiceType to be declared on the service tag in the android manifest file Example

<service
    android:name="de.julianassmann.flutter_background.IsolateHolderService"
    android:enabled="true"
    android:exported="false"
    android:foregroundServiceType="mediaProjection" />

victortive avatar Aug 06 '24 15:08 victortive

Hi @victortive I am using the same code. Only first time after install the app and after give permission, it give me the error and then after every time, it is working fine.

harshmdr avatar Aug 07 '24 04:08 harshmdr

Anyone who has found the solution?

EnterSoftwareSolutions avatar Oct 07 '24 11:10 EnterSoftwareSolutions

Hi there,

I just solved a similar issue and stumbled over this issue

Is the sequence matters? My sequence is 1. Start foreground service while app init.[One time] 2. Helper.requestCapturePermission() [while start broadcasting everytime] 3. navigator.mediaDevices.getDisplayMedia [Everytime]

Yes, ordering matters, you need to first request capture permission, then start the foreground service (and then do whatever you do, getDisplayMedia in this case)

According to the docs, the "standard" permission needs to be granted before attemping to use the foreground permission.

For example, if you try to launch a foreground service of type location, the system checks to make sure your app already has either the ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission. If it doesn't, the system throws SecurityException.

holzgeist avatar Nov 14 '24 12:11 holzgeist

For any viewers, this is what you must do to share your screen on Android 14+.

  1. Add package flutter_background
  2. Add this in your AndroidManifest
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />

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

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

  <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION"/>
  1. Add this to your AndroidManifest <service android:name="de.julianassmann.flutter_background.IsolateHolderService" android:foregroundServiceType="mediaProjection" android:enabled="true" android:exported="false"/>
  2. Call this function in main function of your app
 Future<bool> startForegroundService() async {
 const androidConfig = FlutterBackgroundAndroidConfig(
   notificationTitle: 'Title of the notification',
   notificationText: 'Text of the notification',

 );
 await FlutterBackground.initialize(androidConfig: androidConfig);
 return true;
}
  1. Call This function to share the screen
 Future<void> screenSharing() async {
  FlutterBackground.enableBackgroundExecution();
  final isGranted = await Helper.requestCapturePermission();
  if (!isGranted) return;
  _shareStream = await navigator.mediaDevices.getDisplayMedia({
    'audio': true,
    'video': {
      'cursor': 'always',
    },
  });

  await _replaceStream(_shareStream!);
}

ardeshir-33033 avatar Jan 20 '25 13:01 ardeshir-33033

For any viewers, this is what you must do to share your screen on Android 14+.

  1. Add package flutter_background
  2. Add this in your AndroidManifest
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />

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

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

  <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION"/>
  1. Add this to your AndroidManifest <service android:name="de.julianassmann.flutter_background.IsolateHolderService" android:foregroundServiceType="mediaProjection" android:enabled="true" android:exported="false"/>
  2. Call this function in main function of your app
 Future<bool> startForegroundService() async {
 const androidConfig = FlutterBackgroundAndroidConfig(
   notificationTitle: 'Title of the notification',
   notificationText: 'Text of the notification',

 );
 await FlutterBackground.initialize(androidConfig: androidConfig);
 return true;
}
  1. Call This function to share the screen
 Future<void> screenSharing() async {
  FlutterBackground.enableBackgroundExecution();
  final isGranted = await Helper.requestCapturePermission();
  if (!isGranted) return;
  _shareStream = await navigator.mediaDevices.getDisplayMedia({
    'audio': true,
    'video': {
      'cursor': 'always',
    },
  });

  await _replaceStream(_shareStream!);
}

But this is not working on Android 14 and 15 . it is Only working when you force your targetsdk to 28 . But this is not good when you publishing your App in google console. Becuz Google play console want taget sdk 33+. And Also what is your requestCapturePermission() , when i added this Permission it throw me error .

Sam15b avatar Apr 09 '25 06:04 Sam15b