FlitterWebRTS videocall应用程序在点击android仿真器上的一个按钮时崩溃,相机显示出奇怪的图像
每次我按下一个按钮,视频通话应用程序就会崩溃,而且我会遇到很多错误,我只是不确定它到底出了什么问题。 照相机似乎显示彩色图像,而不是人的脸 Main.dartFlitterWebRTS 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
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.