简体   繁体   English

Flutter Web-RTC getDisplayMedia 导致应用崩溃

[英]Flutter Web-RTC getDisplayMedia results in app crash

I want to create an app for Video-calling between 2 devices, with the possibility to share their own screen with the Flutter WebRTC plugin.我想为 2 台设备之间的视频通话创建一个应用程序,可以与 Flutter WebRTC 插件共享自己的屏幕。 I already made the video-calling part, but I ran into a problem with switching the UserMedia stream to DisplayMedia stream:我已经完成了视频通话部分,但是我遇到了将 UserMedia stream 切换到 DisplayMedia stream 的问题:

When I call the function getDisplayMedia() on android, sometimes it's working but when it's not, my app will crash with the following error:当我在 android 上调用 function getDisplayMedia()时,有时它可以工作,但当它不工作时,我的应用程序将崩溃并出现以下错误:

E/AndroidRuntime(28052): FATAL EXCEPTION: main
E/AndroidRuntime(28052): Process: com.robin.screenshare_sample, PID: 28052
E/AndroidRuntime(28052): java.lang.RuntimeException: Unable to resume activity {com.robin.screenshare_sample/com.robin.screenshare_sample.MainActivity}: java.lang.IllegalStateException: MediaStreamTrack has been disposed.
E/AndroidRuntime(28052):    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4657)
E/AndroidRuntime(28052):    at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4690)
E/AndroidRuntime(28052):    at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:52)
E/AndroidRuntime(28052):    at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176)
E/AndroidRuntime(28052):    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
E/AndroidRuntime(28052):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2267)
E/AndroidRuntime(28052):    at android.os.Handler.dispatchMessage(Handler.java:107)
E/AndroidRuntime(28052):    at android.os.Looper.loop(Looper.java:237)
E/AndroidRuntime(28052):    at android.app.ActivityThread.main(ActivityThread.java:8167)
E/AndroidRuntime(28052):    at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime(28052):    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)
E/AndroidRuntime(28052):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)
E/AndroidRuntime(28052): Caused by: java.lang.IllegalStateException: MediaStreamTrack has been disposed.
E/AndroidRuntime(28052):    at org.webrtc.MediaStreamTrack.checkMediaStreamTrackExists(MediaStreamTrack.java:120)
E/AndroidRuntime(28052):    at org.webrtc.MediaStreamTrack.enabled(MediaStreamTrack.java:93)
E/AndroidRuntime(28052):    at com.cloudwebrtc.webrtc.MethodCallHandlerImpl$5.isEnabled(MethodCallHandlerImpl.java:1710)
E/AndroidRuntime(28052):    at com.cloudwebrtc.webrtc.GetUserMediaImpl.reStartCamera(GetUserMediaImpl.java:1044)
E/AndroidRuntime(28052):    at com.cloudwebrtc.webrtc.MethodCallHandlerImpl.reStartCamera(MethodCallHandlerImpl.java:1704)
E/AndroidRuntime(28052):    at com.cloudwebrtc.webrtc.FlutterWebRTCPlugin$LifeCycleObserver.onResume(FlutterWebRTCPlugin.java:186)
E/AndroidRuntime(28052):    at androidx.lifecycle.FullLifecycleObserverAdapter.onStateChanged(FullLifecycleObserverAdapter.java:42)
E/AndroidRuntime(28052):    at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:361)
E/AndroidRuntime(28052):    at androidx.lifecycle.LifecycleRegistry.forwardPass(LifecycleRegistry.java:300)
E/AndroidRuntime(28052):    at androidx.lifecycle.LifecycleRegistry.sync(LifecycleRegistry.java:339)
E/AndroidRuntime(28052):    at androidx.lifecycle.LifecycleRegistry.moveToState(LifecycleRegistry.java:145)
E/AndroidRuntime(28052):    at androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent(LifecycleRegistry.java:131)
E/AndroidRuntime(28052):    at io.flutter.embedding.android.FlutterActivity.onResume(FlutterActivity.java:599)
E/AndroidRuntime(28052):    at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1454)
E/AndroidRuntime(28052):    at android.app.Activity.performResume(Activity.java:8111)
E/AndroidRuntime(28052):    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4647)
E/AndroidRuntime(28052):    ... 11 more

My code:我的代码:

if (Platform.isAndroid) {
    await startForegroundService();
    MediaStream stream = await navigator.mediaDevices.getDisplayMedia({'video':true,'audio':true});
    var connections = await peerConnection!.getSenders();
    connections.forEach((rtpSender) {
      if (rtpSender.track!.kind == 'video') {
        rtpSender.replaceTrack(stream.getVideoTracks()[0]);
      }
    });
    localVideo.srcObject = stream;
    localStream = stream;
}

To start a foreground service I use the plugin flutter_foreground_plugin .要启动前台服务,我使用插件flutter_foreground_plugin

If anyone has a suggestion, it will be a pleasure.如果有人有建议,那将是一种乐趣。 Thanks in advance.提前致谢。

Mine works.我的作品。 I am using flutter_foreground_task: ^3.5.5我正在使用 flutter_foreground_task: ^3.5.5

Just wrap scaffold body with WithForegroundTask widget provided by package.只需使用 package 提供的 WithForegroundTask 小部件包裹脚手架主体。

just add things described in the package description but add one more thing( media projection attribute should be added for it).只需添加 package 描述中描述的内容,但再添加一件事(应为其添加媒体投影属性)。

<service android:name="com.pravera.flutter_foreground_task.service.ForegroundService" android:foregroundServiceType="mediaProjection"/>
  Future<bool> _startForegroundTask() async {
    // You can save data using the saveData function.
    //await FlutterForegroundTask.saveData(key: 'customData', value: 'hello');

    ReceivePort? receivePort;
    if (await FlutterForegroundTask.isRunningService) {
      receivePort = await FlutterForegroundTask.restartService();
    } else {
      receivePort = await FlutterForegroundTask.startService(
        notificationTitle: 'Ongoing call',
        notificationText: 'Tap to return to the app',
        callback: () {
          //FlutterForegroundTask.setTaskHandler(FirstTaskHandler());
        },
      );
    }

/*     if (receivePort != null) {
      _receivePort = receivePort;
      _receivePort?.listen((message) {
        if (message is DateTime) {
          print('receive timestamp: $message');
        }
      });

      return true;
    } */

    return false;
  }

  Future<void> _initForegroundTask() async {
    await FlutterForegroundTask.init(
      androidNotificationOptions: AndroidNotificationOptions(
        channelId: 'ongoing_call_notification_channel_id',
        channelName: 'Ongoing call Notification',
        channelDescription:
            'This notification appears when the foreground service is running.',
        channelImportance: NotificationChannelImportance.LOW,
        priority: NotificationPriority.LOW,
        iconData: const NotificationIconData(
          resType: ResourceType.mipmap,
          resPrefix: ResourcePrefix.ic,
          name: 'launcher',
        ),
/*         buttons: [
          const NotificationButton(id: 'returnToCall', text: 'Return'),
          const NotificationButton(id: 'endCall', text: 'End Call'),
        ], */
      ),
      foregroundTaskOptions: const ForegroundTaskOptions(
        interval: 5000,
        autoRunOnBoot: false,
        allowWifiLock: true,
      ),
      printDevLog: true,
    );
    await _startForegroundTask();
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM