簡體   English   中英

Flutter Web-RTC getDisplayMedia 導致應用崩潰

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

我想為 2 台設備之間的視頻通話創建一個應用程序,可以與 Flutter WebRTC 插件共享自己的屏幕。 我已經完成了視頻通話部分,但是我遇到了將 UserMedia stream 切換到 DisplayMedia stream 的問題:

當我在 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

我的代碼:

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;
}

要啟動前台服務,我使用插件flutter_foreground_plugin

如果有人有建議,那將是一種樂趣。 提前致謝。

我的作品。 我正在使用 flutter_foreground_task: ^3.5.5

只需使用 package 提供的 WithForegroundTask 小部件包裹腳手架主體。

只需添加 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