FlitterWebRTS videocall应用程序在点击android仿真器上的一个按钮时崩溃,相机显示出奇怪的图像

FlitterWebRTS videocall应用程序在点击android仿真器上的一个按钮时崩溃,相机显示出奇怪的图像,android,flutter,android-studio,android-emulator,webrtc,Android,Flutter,Android Studio,Android Emulator,Webrtc,每次我按下一个按钮,视频通话应用程序就会崩溃,而且我会遇到很多错误,我只是不确定它到底出了什么问题。 照相机似乎显示彩色图像,而不是人的脸 Main.dart import 'dart:convert'; import 'package:flutter/material.dart'; // import 'package:flutter_webrtc/web/rtc_session_description.dart'; import 'package:flutter_webrtc/flutt

每次我按下一个按钮,视频通话应用程序就会崩溃,而且我会遇到很多错误,我只是不确定它到底出了什么问题。 照相机似乎显示彩色图像,而不是人的脸

Main.dart

import 'dart:convert';


import 'package:flutter/material.dart';
// import 'package:flutter_webrtc/web/rtc_session_description.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart';
import 'package:sdp_transform/sdp_transform.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'WebRTC lets learn together'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool _offer = false;
  RTCPeerConnection _peerConnection;
  MediaStream _localStream;
  RTCVideoRenderer _localRenderer = new RTCVideoRenderer();
  RTCVideoRenderer _remoteRenderer = new RTCVideoRenderer();

  final sdpController = TextEditingController();

  @override
  dispose() {
    _localRenderer.dispose();
    _remoteRenderer.dispose();
    sdpController.dispose();
    super.dispose();
  }

  @override
  void initState() {
    initRenderers();
    _createPeerConnection().then((pc) {
      _peerConnection = pc;
    });
    super.initState();
  }

  initRenderers() async {
    await _localRenderer.initialize();
    await _remoteRenderer.initialize();
  }

  void _createOffer() async {
    RTCSessionDescription description =
        await _peerConnection.createOffer({'offerToReceiveVideo': 1});
    var session = parse(description.sdp);
    print(json.encode(session));
    _offer = true;

    // print(json.encode({
    //       'sdp': description.sdp.toString(),
    //       'type': description.type.toString(),
    //     }));

    _peerConnection.setLocalDescription(description);
  }

  void _createAnswer() async {
    RTCSessionDescription description =
        await _peerConnection.createAnswer({'offerToReceiveVideo': 1});

    var session = parse(description.sdp);
    print(json.encode(session));
    // print(json.encode({
    //       'sdp': description.sdp.toString(),
    //       'type': description.type.toString(),
    //     }));

   await _peerConnection.setLocalDescription(description);
  }

  void _setRemoteDescription() async {
    String jsonString = sdpController.text;
    dynamic session = await jsonDecode('$jsonString');

    String sdp = write(session, null);

    // RTCSessionDescription description =
    //     new RTCSessionDescription(session['sdp'], session['type']);
    RTCSessionDescription description =
        new RTCSessionDescription(sdp, _offer ? 'answer' : 'offer');
    print(description.toMap());

    await _peerConnection.setRemoteDescription(description);
  }

  void _addCandidate() async {
    String jsonString = sdpController.text;
    dynamic session = await jsonDecode('$jsonString');
    print(session['candidate']);
    dynamic candidate = new RTCIceCandidate(
        session['candidate'], session['sdpMid'], session['sdpMlineIndex']);
    await _peerConnection.addCandidate(candidate);
  }

  _createPeerConnection() async {
    Map<String, dynamic> configuration = {
      "iceServers": [
        {"url": "stun:stun.l.google.com:19302"},
      ]
    };

    final Map<String, dynamic> offerSdpConstraints = {
      "mandatory": {
        "OfferToReceiveAudio": true,
        "OfferToReceiveVideo": true,
      },
      "optional": [],
    };

    _localStream = await _getUserMedia();

    RTCPeerConnection pc =
        await createPeerConnection(configuration, offerSdpConstraints);
    // if (pc != null) print(pc);
    pc.addStream(_localStream);

    pc.onIceCandidate = (e) {
      if (e.candidate != null) {
        print(json.encode({
          'candidate': e.candidate.toString(),
          'sdpMid': e.sdpMid.toString(),
          'sdpMlineIndex': e.sdpMlineIndex,
        }));
      }
    };

    pc.onIceConnectionState = (e) {
      print(e);
    };

    pc.onAddStream = (stream) {
      print('addStream: ' + stream.id);
      _remoteRenderer.srcObject = stream;
    };

    return pc;
  }

  _getUserMedia() async {
    final Map<String, dynamic> mediaConstraints = {
      'audio': false,
      'video': {
        'facingMode': 'user',
      },
    };

    MediaStream stream =
        await navigator.mediaDevices.getUserMedia(mediaConstraints);

    // _localStream = stream;
    _localRenderer.srcObject = stream;
    RTCVideoView(_localRenderer, mirror: true);

    // _peerConnection.addStream(stream);

    return stream;
  }

  SizedBox videoRenderers() => SizedBox(
      height: 210,
      child: Row(children: [
        Flexible(
          child: new Container(
              key: new Key("local"),
              margin: new EdgeInsets.fromLTRB(5.0, 5.0, 5.0, 5.0),
              decoration: new BoxDecoration(color: Colors.black),
              child: new RTCVideoView(_localRenderer)),
        ),
        Flexible(
          child: new Container(
              key: new Key("remote"),
              margin: new EdgeInsets.fromLTRB(5.0, 5.0, 5.0, 5.0),
              decoration: new BoxDecoration(color: Colors.black),
              child: new RTCVideoView(_remoteRenderer)),
        )
      ]));

  Row offerAndAnswerButtons() => Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: <Widget>[
          new ElevatedButton(
            onPressed: _createOffer,
            child: Text(
              'Offer',
              style: TextStyle(
                color: Colors.amber,
              ),
            ),
          ),
          ElevatedButton(
            onPressed: _createAnswer,
            child: Text(
              'Answer',
              style: TextStyle(color: Colors.amber),
            ),
          ),
        ],
      );

  Row sdpCandidateButtons() => Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: <Widget>[
          ElevatedButton(
            onPressed: _setRemoteDescription,
            child: Text(
              'Set Remote Desc',
              style: TextStyle(color: Colors.amber),
            ),
          ),
          ElevatedButton(
            onPressed: _addCandidate,
            child: Text(
              'Add Candidate',
              style: TextStyle(color: Colors.amber),
            ),
          ),
        ],
      );

  Padding sdpCandidatesTF() => Padding(
        padding: const EdgeInsets.all(16.0),
        child: TextField(
          controller: sdpController,
          keyboardType: TextInputType.multiline,
          maxLines: 4,
          maxLength: TextField.noMaxLength,
        ),
      );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Container(
        child: SingleChildScrollView(
          child: Column(
            children: [
              videoRenderers(),
              offerAndAnswerButtons(),
              sdpCandidatesTF(),
              sdpCandidateButtons(),
            ],
          ),
        ),
      ),
    );
  }
}
导入'dart:convert';
进口“包装:颤振/材料.省道”;
//导入“包:flatter_webrtc/web/rtc_session_description.dart”;
导入“包:flatter_webrtc/flatter_webrtc.dart”;
导入“package:sdp_transform/sdp_transform.dart”;
void main(){
runApp(MyApp());
}
类MyApp扩展了无状态小部件{
//此小部件是应用程序的根。
@凌驾
小部件构建(构建上下文){
返回材料PP(
标题:“颤振演示”,
主题:主题数据(
主样本:颜色。蓝色,
视觉密度:视觉密度。自适应平台密度,
),
主页:MyHomePage(标题:“WebRTC让我们一起学习”),
);
}
}
类MyHomePage扩展StatefulWidget{
MyHomePage({Key,this.title}):超级(Key:Key);
最后的字符串标题;
@凌驾
_MyHomePageState createState()=>\u MyHomePageState();
}
类_MyHomePageState扩展状态{
bool_offer=false;
RTPEERCONNECTION\u peerConnection;
MediaStream localStream;
RTCDeorenderer_localRenderer=新的RTCDeorenderer();
RTCDeorenderer_remoteRenderer=新的RTCDeorenderer();
最终sdpController=TextEditingController();
@凌驾
处置{
_localRenderer.dispose();
_remoteRenderer.dispose();
sdpController.dispose();
super.dispose();
}
@凌驾
void initState(){
initrenders();
_createPeerConnection()。然后((pc){
_peerConnection=pc;
});
super.initState();
}
initrenders()异步{
等待_localRenderer.initialize();
等待_remoteRenderer.initialize();
}
void\u createOffer()异步{
RTCSessionDescription描述=
wait _peerConnection.createOffer({'offerToReceiveVideo':1});
var session=parse(description.sdp);
打印(json.encode(会话));
_报价=真实;
//打印(json.encode)({
//“sdp”:description.sdp.toString(),
//“类型”:description.type.toString(),
//     }));
_peerConnection.setLocalDescription(描述);
}
void _createAnswer()异步{
RTCSessionDescription描述=
wait _peerConnection.createAnswer({'offerToReceiveVideo':1});
var session=parse(description.sdp);
打印(json.encode(会话));
//打印(json.encode)({
//“sdp”:description.sdp.toString(),
//“类型”:description.type.toString(),
//     }));
wait_peerConnection.setLocalDescription(描述);
}
void\u setRemoteDescription()异步{
字符串jsonString=sdpController.text;
动态会话=等待jsonDecode(“$jsonString”);
字符串sdp=write(会话,null);
//RTCSessionDescription描述=
//新的RTCSessionDescription(会话['sdp'],会话['type']);
RTCSessionDescription描述=
新的RTCSessionDescription(sdp,_offer?'response':'offer');
打印(description.toMap());
wait_peerConnection.setRemoteDescription(描述);
}
void\u addCandidate()异步{
字符串jsonString=sdpController.text;
动态会话=等待jsonDecode(“$jsonString”);
打印(会话[“候选人]);
动态候选对象=新的候选对象(
会话['candidate',会话['sdpMid',会话['sdpMlineIndex']);
等待对等连接。添加候选(候选);
}
_createPeerConnection()异步{
映射配置={
“ICEServer”:[
{“url”:“stun:stun.l.google.com:19302”},
]
};
最终映射offerSdpConstraints={
“强制性”:{
“OfferToReceiveAudio”:正确,
“OfferToReceiveVideo”:正确,
},
“可选”:[],
};
_localStream=await_getUserMedia();
RTPEERCONNECTION pc=
等待createPeerConnection(配置、offerSdpConstraints);
//如果(pc!=null)打印(pc);
pc.addStream(_localStream);
pc.onIceCandidate=(e){
如果(例如,候选者!=null){
打印(json.encode)({
'candidate':e.candidate.toString(),
“sdpMid”:e.sdpMid.toString(),
“sdpMlineIndex”:例如sdpMlineIndex,
}));
}
};
pc.onIceConnectionState=(e){
印刷品(e);
};
pc.onAddStream=(流){
打印('addStream:'+stream.id);
_remoteRenderer.srcObject=流;
};
返回pc;
}
_getUserMedia()异步{
最终映射媒体约束={
“音频”:错误,
“视频”:{
“facingMode”:“用户”,
},
};
媒体流=
等待navigator.mediaDevices.getUserMedia(mediaConstraints);
//_localStream=流;
_localRenderer.srcObject=stream;
RTCVideoView(_localRenderer,mirror:true);
//_peerConnection.addStream(流);
回流;
}
SizedBox视频渲染器()=>SizedBox(
身高:210,
子对象:行(子对象:[
灵活的(
子容器:新容器(
密钥:新密钥(“本地”),
边距:LTRB(5.0,5.0,5.0,5.0,5.0)的新边距集,
装饰:新盒子装饰(颜色:颜色。黑色),
子级:新的RTCVideoView(_localRenderer)),
),
灵活的(
子容器:新容器(
密钥:新密钥(“远程”),
边距:LTRB(5.0,5.0,5.0,5.0,5.0)的新边距集,
装饰:新盒子装饰(颜色:颜色。黑色),
子级:新的RTCVideoView(_remoteRenderer)),
)
]));
行offerAndAnswerButtons()=>行(
mainAxisAlignment:mainAxisAlignment.space,
儿童:[
新升降按钮(
按下按钮:_createOffer,
子:文本(
“报价”,
样式:TextStyle(
颜色:颜色。琥珀色,
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.webrtc">
    <!-- Flutter needs it to communicate with the running application
         to allow setting breakpoints, to provide hot reload, etc.
    -->
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.CAMERA"/>
</manifest>
W/System.err( 5730): java.lang.SecurityException: ConnectivityService: Neither user 10085 nor current process has android.permission.ACCESS_NETWORK_STATE.
W/System.err( 5730):    at android.os.Parcel.createException(Parcel.java:1950)
W/System.err( 5730):    at android.os.Parcel.readException(Parcel.java:1918)
W/System.err( 5730):    at android.os.Parcel.readException(Parcel.java:1868)
W/System.err( 5730):    at android.net.IConnectivityManager$Stub$Proxy.getActiveNetworkInfo(IConnectivityManager.java:1207)
W/System.err( 5730):    at android.net.ConnectivityManager.getActiveNetworkInfo(ConnectivityManager.java:883)
W/System.err( 5730):    at org.webrtc.NetworkMonitorAutoDetect$ConnectivityManagerDelegate.getNetworkState(NetworkMonitorAutoDetect.java:168)
W/System.err( 5730):    at org.webrtc.NetworkMonitorAutoDetect.<init>(NetworkMonitorAutoDetect.java:578)
W/System.err( 5730):    at org.webrtc.NetworkMonitor$1.create(NetworkMonitor.java:50)
W/System.err( 5730):    at org.webrtc.NetworkMonitor.createNetworkChangeDetector(NetworkMonitor.java:181)
W/System.err( 5730):    at org.webrtc.NetworkMonitor.startMonitoring(NetworkMonitor.java:108)
W/System.err( 5730):    at org.webrtc.NetworkMonitor.startMonitoring(NetworkMonitor.java:129)
W/System.err( 5730): Caused by: android.os.RemoteException: Remote stack trace:
W/System.err( 5730):    at android.app.ContextImpl.enforce(ContextImpl.java:1812)
W/System.err( 5730):    at android.app.ContextImpl.enforceCallingOrSelfPermission(ContextImpl.java:1840)
W/System.err( 5730):    at com.android.server.ConnectivityService.enforceAccessPermission(ConnectivityService.java:1665)
W/System.err( 5730):    at com.android.server.ConnectivityService.getActiveNetworkInfo(ConnectivityService.java:1174)
W/System.err( 5730):    at android.net.IConnectivityManager$Stub.onTransact(IConnectivityManager.java:85)
E/rtc     ( 5730): 
E/rtc     ( 5730): 
E/rtc     ( 5730): #
E/rtc     ( 5730): # Fatal error in: gen/sdk/android/generated_metrics_jni/../../../../../../../../usr/local/google/home/sakal/code/webrtc-aar-release/src/sdk/android/src/jni/jni_generator_helper.h, line 94
E/rtc     ( 5730): # last system error: 0
E/rtc     ( 5730): # Check failed: !env->ExceptionCheck()
E/rtc     ( 5730): # 
F/libc    ( 5730): Fatal signal 6 (SIGABRT), code -6 (SI_TKILL) in tid 5855 (network_thread ), pid 5730 (.example.webrtc)
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'google/sdk_gphone_x86_arm/generic_x86_arm:9/PSR1.180720.122/6736742:userdebug/dev-keys'
Revision: '0'
ABI: 'x86'
pid: 5730, tid: 5855, name: network_thread  >>> com.example.webrtc <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
    eax 00000000  ebx 00001662  ecx 000016df  edx 00000006
    edi 00001662  esi b967f4d0
    ebp b967f4f8  esp b967f488  eip ea0f5b39
backtrace:
    #00 pc 00000b39  [vdso:ea0f5000] (__kernel_vsyscall+9)
    #01 pc 0001fdf8  /system/lib/libc.so (syscall+40)
    #02 pc 00022ed3  /system/lib/libc.so (abort+115)
    #03 pc 002a2ee6  /data/app/com.example.webrtc-Pui2eU9wGk2OaaPG5l8buQ==/lib/x86/libjingle_peerconnection_so.so
    #04 pc 00280e8e  /data/app/com.example.webrtc-Pui2eU9wGk2OaaPG5l8buQ==/lib/x86/libjingle_peerconnection_so.so
    #05 pc 0029f826  /data/app/com.example.webrtc-Pui2eU9wGk2OaaPG5l8buQ==/lib/x86/libjingle_peerconnection_so.so
    #06 pc 0028be22  /data/app/com.example.webrtc-Pui2eU9wGk2OaaPG5l8buQ==/lib/x86/libjingle_peerconnection_so.so
    #07 pc 0028bd88  /data/app/com.example.webrtc-Pui2eU9wGk2OaaPG5l8buQ==/lib/x86/libjingle_peerconnection_so.so
    #08 pc 00686782  /data/app/com.example.webrtc-Pui2eU9wGk2OaaPG5l8buQ==/lib/x86/libjingle_peerconnection_so.so
    #09 pc 0068656b  /data/app/com.example.webrtc-Pui2eU9wGk2OaaPG5l8buQ==/lib/x86/libjingle_peerconnection_so.so
    #10 pc 00678da5  /data/app/com.example.webrtc-Pui2eU9wGk2OaaPG5l8buQ==/lib/x86/libjingle_peerconnection_so.so
    #11 pc 00670e4f  /data/app/com.example.webrtc-Pui2eU9wGk2OaaPG5l8buQ==/lib/x86/libjingle_peerconnection_so.so
    #12 pc 0073b230  /data/app/com.example.webrtc-Pui2eU9wGk2OaaPG5l8buQ==/lib/x86/libjingle_peerconnection_so.so
    #13 pc 0073e6c1  /data/app/com.example.webrtc-Pui2eU9wGk2OaaPG5l8buQ==/lib/x86/libjingle_peerconnection_so.so
    #14 pc 0029d960  /data/app/com.example.webrtc-Pui2eU9wGk2OaaPG5l8buQ==/lib/x86/libjingle_peerconnection_so.so
    #15 pc 0029df17  /data/app/com.example.webrtc-Pui2eU9wGk2OaaPG5l8buQ==/lib/x86/libjingle_peerconnection_so.so
    #16 pc 0029d30c  /data/app/com.example.webrtc-Pui2eU9wGk2OaaPG5l8buQ==/lib/x86/libjingle_peerconnection_so.so
    #17 pc 0029cb15  /data/app/com.example.webrtc-Pui2eU9wGk2OaaPG5l8buQ==/lib/x86/libjingle_peerconnection_so.so
    #18 pc 0029bb2e  /data/app/com.example.webrtc-Pui2eU9wGk2OaaPG5l8buQ==/lib/x86/libjingle_peerconnection_so.so
    #19 pc 0029cfd1  /data/app/com.example.webrtc-Pui2eU9wGk2OaaPG5l8buQ==/lib/x86/libjingle_peerconnection_so.so
    #20 pc 0029cf0b  /data/app/com.example.webrtc-Pui2eU9wGk2OaaPG5l8buQ==/lib/x86/libjingle_peerconnection_so.so
    #21 pc 0008f065  /system/lib/libc.so (__pthread_start(void*)+53)
    #22 pc 0002485b  /system/lib/libc.so (__start_thread+75)
Lost connection to device.