1.新增一键登录

2.视频对讲优化--优化帧选择算法,缓冲区管理优化
This commit is contained in:
sky_min 2025-11-15 17:37:42 +08:00
parent 749b79f2b1
commit dfb368d822
7 changed files with 389 additions and 434 deletions

View File

@ -1,6 +1,7 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:star_lock/flavors.dart';
@ -38,6 +39,10 @@ class _StarLockLoginPageState extends State<StarLockLoginPage> {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
AppFirstEnterHandle().getAppFirstEnter(isAgreePrivacy);
//
if (state.isChinaUser.value) {
// state.getPhoneNumber();
}
});
// StartChartManage().init();
}
@ -83,193 +88,202 @@ class _StarLockLoginPageState extends State<StarLockLoginPage> {
onTap: () {
FocusScope.of(context).unfocus();
},
child: ListView(
padding: EdgeInsets.only(top: 120.h, left: 40.w, right: 40.w),
children: <Widget>[
Container(
padding: EdgeInsets.all(10.w),
child: Center(child: Image.asset('images/icon_main_sky_1024.png', width: 110.w, height: 110.w))),
SizedBox(height: 50.w),
Obx(() => CommonItem(
leftTitel: '你所在的国家/地区'.tr,
rightTitle: '',
isHaveLine: true,
isPadding: false,
isHaveRightWidget: true,
isHaveDirection: true,
rightWidget: Text(
'${state.countryName} +${state.countryCode.value}',
textAlign: TextAlign.end,
style: TextStyle(fontSize: 22.sp, color: AppColors.darkGrayTextColor),
),
action: () async {
final result = await Get.toNamed(Routers.selectCountryRegionPage);
if (result != null) {
result as Map<String, dynamic>;
state.countryCode.value = result['code'];
state.countryKey.value = result['countryName'];
logic.checkIpAction();
child: state.isChinaUser.value ? _buildChinaUser() : _buildForeignUser()
),
);
}
Widget _buildChinaUser() {
return ListView(
padding: EdgeInsets.only(top: 120.h, left: 40.w, right: 40.w),
children: <Widget>[
Container(
padding: EdgeInsets.all(10.w),
alignment: Alignment.center,
child: Column(children: [
Image.asset('images/icon_main_sky_1024.png', width: 110.w, height: 110.w),
SizedBox(height: 50.w),
Text(state.emailOrPhone.value.isNotEmpty ? state.emailOrPhone.value : '获取手机号中...'),
SizedBox(height: 50.w),
SubmitBtn(
btnName: '一键登录',
fontSize: 28.sp,
borderRadius: 20.w,
padding: EdgeInsets.only(top: 25.w, bottom: 25.w),
onClick: () {
if (state.agree.value == false) {
logic.showToast('请先同意用户协议及隐私政策'.tr);
return;
} else {
logic.oneClickLoginAction(context);
}
},
)),
LoginInput(
focusNode: logic.state.emailOrPhoneFocusNode,
controller: state.emailOrPhoneController,
onchangeAction: (v) {
logic.checkNext(state.emailOrPhoneController);
},
leftWidget: Padding(
padding: EdgeInsets.only(top: 30.w, bottom: 20.w, right: 5.w, left: 5.w),
child: Image.asset(
'images/icon_login_account.png',
width: 36.w,
height: 36.w,
),
),
hintText: '请输入手机号或者邮箱'.tr,
// keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[
// FilteringTextInputFormatter.allow(RegExp('[0-9]')),
LengthLimitingTextInputFormatter(30),
FilteringTextInputFormatter.singleLineFormatter
]),
SizedBox(height: 10.h),
LoginInput(
focusNode: logic.state.pwdFocusNode,
controller: state.pwdController,
onchangeAction: (v) {
logic.checkNext(state.pwdController);
},
isPwd: true,
// isSuffixIcon: 2,
leftWidget: Padding(
padding: EdgeInsets.only(top: 30.w, bottom: 20.w, right: 5.w, left: 5.w),
child: Image.asset(
'images/icon_login_password.png',
width: 36.w,
height: 36.w,
),
),
hintText: '请输入密码'.tr,
inputFormatters: <TextInputFormatter>[
LengthLimitingTextInputFormatter(20),
]),
// SizedBox(height: 15.h),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Obx(() => GestureDetector(
onTap: () {
state.agree.value = !state.agree.value;
logic.changeAgreeState();
},
child: Container(
// color: Colors.red,
padding: EdgeInsets.only(left: 5.w, top: 20.w, right: 10.w, bottom: 20.h),
child: Image.asset(
state.agree.value ? 'images/icon_round_select.png' : 'images/icon_round_unSelect.png',
width: 35.w,
height: 35.w,
),
))),
// SizedBox(
// width: 5.w,
// ),
Flexible(
child: RichText(
text: TextSpan(
text: '我已阅读并同意'.tr,
style: TextStyle(color: const Color(0xff333333), fontSize: 20.sp),
children: <InlineSpan>[
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: GestureDetector(
child:
Text('${'用户协议'.tr}', style: TextStyle(color: AppColors.mainColor, fontSize: 20.sp)),
onTap: () {
Get.toNamed(Routers.webviewShowPage, arguments: <String, String>{
'url': XSConstantMacro.userAgreementURL,
'title': '用户协议'.tr
});
},
)),
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: GestureDetector(
child:
Text('${'隐私政策'.tr}', style: TextStyle(color: AppColors.mainColor, fontSize: 20.sp)),
onTap: () {
Get.toNamed(Routers.webviewShowPage, arguments: <String, String>{
'url': XSConstantMacro.privacyPolicyURL,
'title': '隐私政策'.tr
});
},
)),
],
)),
)
],
}),
SizedBox(height: 50.w),
_agreentWidget(),
]))
]);
}
Widget _buildForeignUser() {
return ListView(
padding: EdgeInsets.only(top: 120.h, left: 40.w, right: 40.w),
children: <Widget>[
Container(
padding: EdgeInsets.all(10.w),
child: Center(child: Image.asset('images/icon_main_sky_1024.png', width: 110.w, height: 110.w))),
SizedBox(height: 50.w),
Obx(() => CommonItem(
leftTitel: '你所在的国家/地区'.tr,
rightTitle: '',
isHaveLine: true,
isPadding: false,
isHaveRightWidget: true,
isHaveDirection: true,
rightWidget: Text(
'${state.countryName} +${state.countryCode.value}',
textAlign: TextAlign.end,
style: TextStyle(fontSize: 22.sp, color: AppColors.darkGrayTextColor),
),
action: () async {
final result = await Get.toNamed(Routers.selectCountryRegionPage);
if (result != null) {
result as Map<String, dynamic>;
state.countryCode.value = result['code'];
state.countryKey.value = result['countryName'];
logic.checkIpAction();
}
},
)),
LoginInput(
focusNode: logic.state.emailOrPhoneFocusNode,
controller: state.emailOrPhoneController,
onchangeAction: (v) {
logic.checkNext(state.emailOrPhoneController);
},
leftWidget: Padding(
padding: EdgeInsets.only(top: 30.w, bottom: 20.w, right: 5.w, left: 5.w),
child: Image.asset(
'images/icon_login_account.png',
width: 36.w,
height: 36.w,
),
),
SizedBox(height: 50.w),
Obx(() => SubmitBtn(
btnName: '登录'.tr,
fontSize: 28.sp,
borderRadius: 20.w,
padding: EdgeInsets.only(top: 25.w, bottom: 25.w),
isDisabled: state.canNext.value,
onClick: state.canNext.value
? () {
if (state.agree.value == false) {
logic.showToast('请先同意用户协议及隐私政策'.tr);
return;
} else {
logic.login();
}
}
: null)),
// SizedBox(height: 20.w),
// Obx(() => Visibility(
// visible: state.isCheckVerifyEnable.value,
// child: SubmitBtn(
// btnName: '一键登录',
// fontSize: 28.sp,
// borderRadius: 20.w,
// padding: EdgeInsets.only(top: 25.w, bottom: 25.w),
// // isDisabled: state.canNext.value,
// onClick: () {
// if (state.agree.value == false) {
// logic.showToast('请先同意用户协议及隐私政策'.tr);
// return;
// } else {
// logic.oneClickLoginAction();
// }
// }),
// )),
SizedBox(height: 50.w),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GestureDetector(
child: SizedBox(
// width: 150.w,
height: 50.h,
// color: Colors.red,
child: Center(
child: Text('${'忘记密码'.tr}', style: TextStyle(fontSize: 22.sp, color: AppColors.mainColor)),
),
),
onTap: () {
Navigator.pushNamed(context, Routers.starLockForgetPasswordPage);
},
hintText: '请输入邮箱'.tr,
inputFormatters: <TextInputFormatter>[
LengthLimitingTextInputFormatter(30),
FilteringTextInputFormatter.singleLineFormatter
]),
SizedBox(height: 10.h),
LoginInput(
focusNode: logic.state.pwdFocusNode,
controller: state.pwdController,
onchangeAction: (v) {
logic.checkNext(state.pwdController);
},
isPwd: true,
leftWidget: Padding(
padding: EdgeInsets.only(top: 30.w, bottom: 20.w, right: 5.w, left: 5.w),
child: Image.asset(
'images/icon_login_password.png',
width: 36.w,
height: 36.w,
),
),
hintText: '请输入密码'.tr,
inputFormatters: <TextInputFormatter>[
LengthLimitingTextInputFormatter(20),
]),
SizedBox(height: 50.w),
Obx(() => SubmitBtn(
btnName: '登录'.tr,
fontSize: 28.sp,
borderRadius: 20.w,
padding: EdgeInsets.only(top: 25.w, bottom: 25.w),
isDisabled: state.canNext.value,
onClick: state.canNext.value
? () {
if (state.agree.value == false) {
logic.showToast('请先同意用户协议及隐私政策'.tr);
return;
} else {
logic.login();
}
} : null)),
SizedBox(height: 20.w),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GestureDetector(
child: SizedBox(
// width: 150.w,
height: 50.h,
// color: Colors.red,
child: Center(
child: Text('${'忘记密码'.tr}', style: TextStyle(fontSize: 22.sp, color: AppColors.mainColor)),
),
],
),
onTap: () {
Navigator.pushNamed(context, Routers.starLockForgetPasswordPage);
},
),
],
),
),
],
);
}
Widget _agreentWidget() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Obx(() => GestureDetector(
onTap: () {
state.agree.value = !state.agree.value;
logic.changeAgreeState();
},
child: Container(
// color: Colors.red,
padding: EdgeInsets.only(left: 5.w, top: 20.w, right: 10.w, bottom: 20.h),
child: Image.asset(
state.agree.value ? 'images/icon_round_select.png' : 'images/icon_round_unSelect.png',
width: 35.w,
height: 35.w,
),
))),
RichText(
text: TextSpan(
text: '我已阅读并同意'.tr,
style: TextStyle(color: const Color(0xff333333), fontSize: 20.sp),
children: <InlineSpan>[
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: GestureDetector(
child:
Text('${'用户协议'.tr}', style: TextStyle(color: AppColors.mainColor, fontSize: 20.sp)),
onTap: () {
Get.toNamed(Routers.webviewShowPage, arguments: <String, String>{
'url': XSConstantMacro.userAgreementURL,
'title': '用户协议'.tr
});
},
)),
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: GestureDetector(
child:
Text('${'隐私政策'.tr}', style: TextStyle(color: AppColors.mainColor, fontSize: 20.sp)),
onTap: () {
Get.toNamed(Routers.webviewShowPage, arguments: <String, String>{
'url': XSConstantMacro.privacyPolicyURL,
'title': '隐私政策'.tr
});
},
)),
],
)),
]);
}
Widget loginInput(
{TextEditingController? controller,
List<TextInputFormatter>? inputFormatters,

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../app_settings/app_settings.dart';
import '../../tools/jverify_one_click_login.dart';
import '../../translations/current_locale_tool.dart';
class StarLockLoginState {
@ -14,6 +15,11 @@ class StarLockLoginState {
RxString countryCode = '86'.obs;
RxString countryKey = '中国'.tr.obs;
//
final RxBool isChinaUser = false.obs;
//
final RxBool showOneClickLogin = false.obs;
///
String get countryName => countryKey.value.tr;

View File

@ -689,18 +689,35 @@ class LockDetailLogic extends BaseGetXController {
//
Future<void> remoteOpenLock() async {
final catEyeConfig = state.keyInfos.value.lockSetting?.catEyeConfig ?? [];
//
if (state.keyInfos.value.lockFeature?.isSupportCatEye == 1 && catEyeConfig[0].catEyeMode == 0) {
showToast('猫眼设置为省电模式时无法进行远程开锁,请在猫眼设置中切换为其他模式'.tr);
return;
final LockListInfoItemEntity currentKeyInfo = CommonDataManage().currentKeyInfo;
var lockId = currentKeyInfo.lockId ?? 0;
var remoteUnlock = currentKeyInfo.lockSetting?.remoteUnlock ?? 0;
final lockPeerId = StartChartManage().lockPeerId;
final LockListInfoGroupEntity? lockListInfoGroupEntity = await Storage.getLockMainListData();
if (lockListInfoGroupEntity != null) {
lockListInfoGroupEntity!.groupList?.forEach((element) {
final lockList = element.lockList;
if (lockList != null && lockList.length != 0) {
for (var lockInfo in lockList) {
final peerId = lockInfo.network?.peerId;
if (peerId != null && peerId != '') {
if (peerId == lockPeerId) {
lockId = lockInfo.lockId ?? 0;
remoteUnlock = lockInfo.lockSetting?.remoteUnlock ?? 0;
}
}
}
}
});
}
final LoginEntity entity = await ApiRepository.to.remoteOpenLock(
lockId: state.keyInfos.value.lockId.toString(),
timeOut: 60,
);
if (entity.errorCode!.codeIsSuccessful) {
showToast('已开锁'.tr);
if (remoteUnlock == 1) {
final LoginEntity entity = await ApiRepository.to.remoteOpenLock(lockId: lockId.toString(), timeOut: 60);
if (entity.errorCode!.codeIsSuccessful) {
showToast('已开锁'.tr);
StartChartManage().lockListPeerId = [];
}
}
}
@ -849,8 +866,6 @@ class LockDetailLogic extends BaseGetXController {
showToast('设备未配网'.tr);
return;
}
//
AudioPlayerManager().disableRingtone();
//
// PacketLossStatistics().reset();
// id

View File

@ -41,20 +41,8 @@ class SelectLockTypeLogic extends BaseGetXController {
if (!Platform.isIOS) {
final bool locationRequest = await PermissionDialog.request(Permission.location);
final bool bluetoothRequest = await PermissionDialog.requestBluetooth();
//
final bool storageRequest = await PermissionDialog.request(Permission.storage);
bool isHarmonyOS = await checkIfHarmonyOS();
// 鸿
if(isHarmonyOS){
print('鸿蒙手机提示----');
if (!bluetoothRequest || !locationRequest || !storageRequest) {
return;
}
} else {
if (!bluetoothRequest || !locationRequest) {
return;
}
if (!bluetoothRequest || !locationRequest) {
return;
}
}

View File

@ -193,34 +193,10 @@ class _MessageListPageState extends State<MessageListPage>
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 30.sp)),
//
// GestureDetector(
// onTap: () {
// // api接口使
// // if (_showCheckboxes.value) {
// // deleteSelectedMessages();
// // } else {
// // setState(() {
// // _showCheckboxes.value =
// // !_showCheckboxes.value;
// // });
// // }
// },
// child: _showCheckboxes.value
// ? Text('删除',
// style: TextStyle(
// fontSize: 24.sp,
// color: Colors.red))
// : Image.asset(
// 'images/mine/icon_message_checbox.png',
// width: 30.w,
// height: 30.h),
// )
]),
)
]))),
Container(
child: Container(
padding: EdgeInsets.only(
top: showNotificationBanner ? 80 : 50),
child: ListView.builder(
@ -270,7 +246,6 @@ class _MessageListPageState extends State<MessageListPage>
},
),
),
)
],
);
})),
@ -342,7 +317,7 @@ class _MessageListPageState extends State<MessageListPage>
if (!isLastInGroupSimple)
Container(
width: 0.5,
height: 190.h,
height: 120.h,
color: AppColors.placeholderTextColor,
)
],
@ -370,7 +345,7 @@ class _MessageListPageState extends State<MessageListPage>
],
), child: Container(
width: 1.sw,
margin: EdgeInsets.all(20.h),
margin: EdgeInsets.all(10.h),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10.w),
@ -381,42 +356,8 @@ class _MessageListPageState extends State<MessageListPage>
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// SizedBox(height: 4.h),
// Row(
// children: <Widget>[
// Flexible(
// child: Text(
// //
// '远程开门请求',
// maxLines: 1,
// overflow: TextOverflow.ellipsis,
// style: TextStyle(
// fontSize: 22.sp,
// color: messageItemEntity.readAt! == 0
// ? AppColors.blackColor
// : AppColors.placeholderTextColor),
// ),
// ),
// ],
// ),
// SizedBox(height: 4.h),
Wrap(
children: <Widget>[
// if (messageItemEntity.readAt! == 0)
// Container(
// width: 10.w,
// height: 10.w,
// decoration: BoxDecoration(
// color: Colors.red,
// borderRadius: BorderRadius.circular(5.w),
// ),
// )
// else
// Container(),
// if (messageItemEntity.readAt! == 0)
// SizedBox(width: 5.w)
// else
// Container(),
Container(
margin: EdgeInsets.only(top: 4.h),
child: Text(
@ -437,7 +378,7 @@ class _MessageListPageState extends State<MessageListPage>
? AppColors.blackColor
: AppColors.placeholderTextColor,
),
Container(transform: Matrix4.translationValues(0, -18, 0),
Container(transform: Matrix4.translationValues(0, -22, 0),
child: Text(' ${messageItemEntity.data!}',
maxLines: 2,
overflow: TextOverflow.ellipsis,
@ -453,24 +394,6 @@ class _MessageListPageState extends State<MessageListPage>
),alignment: Alignment.centerRight,)
],
),
// SizedBox(height: 5.h),
// Row(
// mainAxisAlignment: MainAxisAlignment.start,
// children: <Widget>[
// // Image.asset('images/mine/icon_mine_gatewaySignal_strong.png', width: 40.w, height: 40.w,),
// // SizedBox(width: 10.w,),
// Text(
// DateTool().dateToHnString(messageItemEntity
// .createdAt!
// .toString()),
// style: TextStyle(
// fontSize: 18.sp,
// color: messageItemEntity.readAt! == 0
// ? AppColors.blackColor
// : AppColors.placeholderTextColor)),
// ],
// ),
// SizedBox(width: 20.h),
]))))),
//
if (_showCheckboxes.value)

View File

@ -41,6 +41,33 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
final LockDetailState lockDetailState = Get.put(LockDetailLogic()).state;
//
final Map<TalkDataH264Frame_FrameTypeE, List<MapEntry<int, int>>> _frameIndexCache = {};
bool _frameIndexDirty = true;
//
void _invalidateFrameIndex() {
_frameIndexDirty = true;
}
//
List<MapEntry<int, int>> _buildFrameIndex(TalkDataH264Frame_FrameTypeE frameType) {
if (!_frameIndexDirty && _frameIndexCache.containsKey(frameType)) {
return _frameIndexCache[frameType]!;
}
final List<MapEntry<int, int>> index = [];
for (int i = 0; i < state.h264FrameBuffer.length; i++) {
final frame = state.h264FrameBuffer[i];
if (frame['frameType'] == frameType) {
index.add(MapEntry(frame['frameSeq'] as int, i));
}
}
index.sort((a, b) => a.key.compareTo(b.key));
_frameIndexCache[frameType] = index;
_frameIndexDirty = false;
return index;
}
//
int _networkQualityScore = 5; // 1-55
int _frameDropCount = 0;
@ -296,7 +323,13 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
VideoDecodePlugin.setOnFrameRenderedListener((textureId) {
AppLog.log('已经开始渲染=======');
// loading
Future.microtask(() => state.isLoading.value = false);
Future.microtask(() {
state.isLoading.value = false;
//
if (state.animationController.isAnimating) {
state.animationController.stop();
}
});
});
} else {
AppLog.log('视频解码器初始化失败或超时, 耗时: ${duration}ms');
@ -432,6 +465,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
//
state.h264FrameBuffer.add(frameMap);
_invalidateFrameIndex();
}
///
@ -494,11 +528,43 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
} else {
// P帧或B帧
state.h264FrameBuffer.removeAt(0);
_invalidateFrameIndex();
}
}
int _findEarliestIFrame() {
final iFrameIndexes = _buildFrameIndex(TalkDataH264Frame_FrameTypeE.I);
return iFrameIndexes.isNotEmpty ? iFrameIndexes.first.value : -1;
}
int _findRelatedPFrame(int refIFrameSeq) {
final pFrameIndexes = _buildFrameIndex(TalkDataH264Frame_FrameTypeE.P);
for (final entry in pFrameIndexes) {
final frame = state.h264FrameBuffer[entry.value];
if (frame['frameSeqI'] == refIFrameSeq) {
return entry.value;
}
}
return -1;
}
int _findBestFrameIndex() {
// I帧相关的P帧
if (lastDecodedIFrameSeq != null) {
final pFrameIndex = _findRelatedPFrame(lastDecodedIFrameSeq!);
if (pFrameIndex >= 0) return pFrameIndex;
}
// I帧
final iFrameIndex = _findEarliestIFrame();
if (iFrameIndex >= 0) return iFrameIndex;
// I帧
return state.h264FrameBuffer.isNotEmpty ? 0 : -1;
}
///
void _processNextFrameFromBuffer() async {
final stopwatch = Stopwatch()..start();
_monitorFrameProcessingPerformance();
final startTime = DateTime.now().microsecondsSinceEpoch;
@ -543,63 +609,8 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
}
}
// -- I帧以加速首帧显示
int frameIndex = -1;
// I帧
final iFrames = state.h264FrameBuffer
.where((f) => f['frameType'] == TalkDataH264Frame_FrameTypeE.I)
.toList()
..sort((a, b) => (a['frameSeq'] as int).compareTo(b['frameSeq'] as int));
if (iFrames.isNotEmpty) {
final minIFrame = iFrames.first;
frameIndex = state.h264FrameBuffer.indexWhere(
(f) =>
f['frameType'] == TalkDataH264Frame_FrameTypeE.I &&
f['frameSeq'] == minIFrame['frameSeq'],
);
} else {
// I帧
frameIndex = 0;
}
// I帧相关的P帧
if (lastDecodedIFrameSeq != null) {
// I帧关联的P帧
final validPFrames = state.h264FrameBuffer
.where((f) =>
f['frameType'] == TalkDataH264Frame_FrameTypeE.P &&
f['frameSeqI'] == lastDecodedIFrameSeq)
.toList()
..sort((a, b) => (a['frameSeq'] as int).compareTo(b['frameSeq'] as int));
if (validPFrames.isNotEmpty) {
final minPFrame = validPFrames.first;
frameIndex = state.h264FrameBuffer.indexWhere(
(f) =>
f['frameType'] == TalkDataH264Frame_FrameTypeE.P &&
f['frameSeq'] == minPFrame['frameSeq'] &&
f['frameSeqI'] == lastDecodedIFrameSeq,
);
}
}
// P帧I帧
if (frameIndex == -1) {
final iFrames = state.h264FrameBuffer
.where((f) => f['frameType'] == TalkDataH264Frame_FrameTypeE.I)
.toList()
..sort((a, b) => (a['frameSeq'] as int).compareTo(b['frameSeq'] as int));
if (iFrames.isNotEmpty) {
final minIFrame = iFrames.first;
frameIndex = state.h264FrameBuffer.indexWhere(
(f) =>
f['frameType'] == TalkDataH264Frame_FrameTypeE.I &&
f['frameSeq'] == minIFrame['frameSeq'],
);
}
}
//
final frameIndex = _findBestFrameIndex();
//
if (frameIndex >= 0) {
@ -657,6 +668,8 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
AppLog.log('帧处理耗时过长: ${durationMs.toStringAsFixed(2)} ms, 缓冲区长度: ${state.h264FrameBuffer.length}');
}
}
stopwatch.stop();
print('执行耗时: ${stopwatch.elapsedMilliseconds} 毫秒');
}

View File

@ -10,21 +10,21 @@ import '../app_settings/app_settings.dart';
import '../common/XSConstantMacro/XSConstantMacro.dart';
import '../flavors.dart';
class JverifyOneClickLoginManage {
factory JverifyOneClickLoginManage() => shareManager()!;
factory JverifyOneClickLoginManage() => _getInstance()!;
JverifyOneClickLoginManage._init() {
_initSDK();
JverifyOneClickLoginManage._init() {}
static JverifyOneClickLoginManage get instance => _getInstance();
static JverifyOneClickLoginManage? _instance;
static JverifyOneClickLoginManage _getInstance() {
_instance ??= JverifyOneClickLoginManage._init();
return _instance!;
}
static JverifyOneClickLoginManage? _manager;
static JverifyOneClickLoginManage? shareManager() {
_manager ??= JverifyOneClickLoginManage._init();
return _manager;
}
JverifyOneClickLoginManage? get manager => shareManager();
JverifyOneClickLoginManage? get manager => _getInstance();
Jverify jverify = Jverify();
/// key
@ -39,106 +39,102 @@ class JverifyOneClickLoginManage {
///
String f_opr_key = 'operator';
Future<void> _initSDK() async {
Future<void> initSDK({Function? onSuccess, Function? onFailure}) async {
try {
await initPlatformState();
// SDK
jverify.addSDKSetupCallBackListener((JVSDKSetupEvent event) {
print('receive sdk setup call back event :${event.toMap()}');
if (event.code == 8000) {
onSuccess?.call();
} else {
onFailure?.call();
}
});
isInitSuccess();
jverify.setDebugMode(true); //
jverify.setCollectionAuth(true);
String appKey;
if (F.isSKY) {
appKey = '7ff37d174c1a568a89e98dad';
AppLog.log('appKey:7ff37d174c1a568a89e98dad');
} else {
appKey = '251fc8074820d122b6de58d2';
AppLog.log('appKey:251fc8074820d122b6de58d2');
}
jverify.setup(
appKey: appKey, //"你自己应用的 AppKey",
channel: 'devloper');
getToken();
///
jverify.addAuthPageEventListener((JVAuthPageEvent event) {
print('receive auth page event :${event.toMap()}');
});
preLogin();
// isInitSuccess();
// getToken();
// preLogin();
} catch (e) {
AppLog.log('SDK 初始化错误: $e');
}
}
Future<void> initPlatformState() async {
// SDK
jverify.addSDKSetupCallBackListener((JVSDKSetupEvent event) {
print('receive sdk setup call back event :${event.toMap()}');
});
jverify.setDebugMode(true); //
jverify.setCollectionAuth(true);
String appKey;
if (F.isSKY) {
appKey = '7ff37d174c1a568a89e98dad';
AppLog.log('appKey:7ff37d174c1a568a89e98dad');
} else {
appKey = '251fc8074820d122b6de58d2';
AppLog.log('appKey:251fc8074820d122b6de58d2');
}
jverify.setup(
appKey: appKey, //"你自己应用的 AppKey",
channel: 'devloper');
///
jverify.addAuthPageEventListener((JVAuthPageEvent event) {
print('receive auth page event :${event.toMap()}');
});
}
/// sdk
void isInitSuccess() {
jverify.isInitSuccess().then((map) {
final bool result = map[f_result_key];
AppLog.log('sdk 初始化结果:$map');
if (result) {
AppLog.log('sdk 初始化成功');
} else {
AppLog.log('sdk 初始化失败');
}
});
Future<bool> isInitSuccess() async {
final Map<dynamic, dynamic> map = await jverify.isInitSuccess();
final bool result = map[f_result_key];
AppLog.log('sdk 初始化结果:$map');
if (result) {
AppLog.log('sdk 初始化成功');
} else {
AppLog.log('sdk 初始化失败');
}
return Future.value(result);
}
///
Future<bool> checkVerifyEnable() async {
final isInitSuccess = await this.isInitSuccess();
if (!isInitSuccess) {
return false;
}
final Map map = await jverify.checkVerifyEnable();
AppLog.log('一家登录 sdk 初始化结果:$map');
print('一家登录 sdk 初始化结果:$map');
final bool result = map[f_result_key];
return result;
// state.jverify.checkVerifyEnable().then((map) {
// final bool result = map[f_result_key];
// if (result) {
// AppLog.log('当前网络环境【支持认证】!');
// } else {
// AppLog.log('当前网络环境【不支持认证】!');
// }
// return result;
// });
}
void getToken() {
jverify.checkVerifyEnable().then((map) {
final bool result = map[f_result_key];
if (result) {
jverify.getToken().then((map) {
final int code = map[f_code_key];
final String token = map[f_msg_key];
final String operator = map[f_opr_key];
AppLog.log('getToken code:$code token:$token operator:$operator');
});
} else {
AppLog.log('[2016],msg = 当前网络环境不支持认证');
}
});
}
// void getToken() {
// jverify.checkVerifyEnable().then((map) {
// final bool result = map[f_result_key];
// if (result) {
// jverify.getToken().then((map) {
// final int code = map[f_code_key];
// final String token = map[f_msg_key];
// final String operator = map[f_opr_key];
// AppLog.log('getToken code:$code token:$token operator:$operator');
// });
// } else {
// AppLog.log('[2016],msg = 当前网络环境不支持认证');
// }
// });
// }
///
void preLogin() {
jverify.checkVerifyEnable().then((map) {
final bool result = map[f_result_key];
if (result) {
jverify.preLogin().then((map) {
AppLog.log('预取号接口回调:${map.toString()}');
final int code = map[f_code_key];
final String message = map[f_msg_key];
});
} else {
AppLog.log('[2016],msg = 当前网络环境不支持认证');
}
});
Future<bool> preLogin() async {
final networkSupportVerify = await this.checkVerifyEnable();
if (!networkSupportVerify) {
return false;
}
final Map map = await jverify.preLogin();
final int code = map[f_code_key];
final String message = map[f_msg_key];
if (code > 0) {
return true;
}
AppLog.log('[2016],msg = 当前网络环境不支持认证');
return false;
}
/// SDK