import 'dart:convert'; import 'dart:developer' as developer; import 'dart:io'; import 'dart:math'; import 'package:camera/camera.dart'; import 'package:convert/convert.dart'; import 'package:crypto/crypto.dart' as crypto; import 'package:device_info/device_info.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; //import '../my_wechat_assets_picker_fix/my_asset_picker_1.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hyzp_ybqx04_changning/provider/player_region.dart'; import 'UserInfo.dart'; //////////////////////////////////////////// // begin hyzp_ybqx-Commit022-区县切换新方法-OK // 1、修改手机桌面的App图标文本 // R:\FlutterProject\FlutterProject51-hyzp_ybqx\hyzp_ybqx\android\app\src\main\AndroidManifest.xml // android:label="宜宾黑烟抓拍" // android:label="宜宾市翠屏黑烟抓拍" // android:label="宜宾市兴文黑烟抓拍" // android:label="宜宾市筠连黑烟抓拍" // android:label="宜宾市长宁黑烟抓拍" // 2、修改App的android和Flutter启动图片,制作并运行 hyzp_ybqx04_changning.images_copy.cmd,自动完成两项拷贝任务 // (1)、拷贝不同分辨率的图片文件hyzp_ybqx04_changning_launche.png到下面目录,作为App的android启动图片 // r:\FlutterProject\FlutterProject51-hyzp_ybqx\hyzp_ybqx\android\app\src\main\res\mipmap-hdpi\ // r:\FlutterProject\FlutterProject51-hyzp_ybqx\hyzp_ybqx\android\app\src\main\res\mipmap-mdpi\ // r:\FlutterProject\FlutterProject51-hyzp_ybqx\hyzp_ybqx\android\app\src\main\res\mipmap-xhdpi\ // r:\FlutterProject\FlutterProject51-hyzp_ybqx\hyzp_ybqx\android\app\src\main\res\mipmap-xxhdpi\ // r:\FlutterProject\FlutterProject51-hyzp_ybqx\hyzp_ybqx\android\app\src\main\res\mipmap-xxxhdpi\ // (2)、拷贝 750 * 1334 的图片文件到下面目录,作为App的Flutter启动图片 // r:\FlutterProject\FlutterProject51-hyzp_ybqx\hyzp_ybqx\assets\images\hyzp_ybqx01_cuiping_launche.png // 3、修改文本变量 // 位于文件 R:\FlutterProject\FlutterProject51-hyzp_ybqx\hyzp_ybqx\lib\components\commonFun.dart 中 // (1)、宜宾市 // String service_tel = '\n服务热线:187-8467-8300'; // String yibin_QuXian = '宜宾'; // String copyright_info = '© ' + yibin_QuXian + '市生态环境局 四川省踏石科技有限公司 版权所有' + service_tel; // String copyright_info_PinYin = 'YIBIN BLACK SMOKE CAR CAPTURE SYSTEM'; // (2)、翠屏区 // String service_tel = ''; // String yibin_QuXian = '宜宾市翠屏'; // String copyright_info = '© ' + yibin_QuXian + '生态环境局 版权所有' + service_tel; // String copyright_info_PinYin = 'YIBIN CUIPING BLACK SMOKE CAR CAPTURE SYSTEM'; // (3)、兴文县 // String service_tel = '\n服务热线:187-8467-8300'; // String yibin_QuXian = '宜宾市兴文'; // String copyright_info = '© ' + yibin_QuXian + '生态环境局 四川省踏石科技 版权所有' + service_tel; // String copyright_info_PinYin = 'YIBIN XINGWEN BLACK SMOKE CAR CAPTURE SYSTEM'; // (4)、筠连县 // String service_tel = '\n服务热线:187-8467-8300'; // String yibin_QuXian = '宜宾市筠连'; // String copyright_info = '© ' + yibin_QuXian + '生态环境局 四川省踏石科技 版权所有' + service_tel; // String copyright_info_PinYin = 'YIBIN JUNLIAN BLACK SMOKE CAR CAPTURE SYSTEM'; // (5)、长宁县 String service_tel = ''; String yibin_QuXian = '宜宾市长宁'; String copyright_info = '© ' + yibin_QuXian + '生态环境局 版权所有' + service_tel; String copyright_info_PinYin = 'YIBIN CHANGNING BLACK SMOKE CAR CAPTURE SYSTEM'; // 4、全局替换,将 ”hyzp_ybqx04_changning“全部替换为 ”hyzp_ybqx04_changning“,自动完成以下修改 // (1)、修改 R:\FlutterProject\FlutterProject51-hyzp_ybqx\hyzp_ybqx\pubspec.yaml 文件中的AppID,但存放目錄不變 // name: hyzp_ybqx00_yibin // name: hyzp_ybqx01_cuiping // name: hyzp_ybqx04_changning // (2)、全局替换: // A、将 “com.flutter.hyzp_ybqx00_yibin” 全部替换为 “com.flutter.hyzp_ybqx04_changning” // B、将 “package:hyzp_ybqx00_yibin/” 全部替换为 “package:hyzp_ybqx04_changning/” // C、将 “# hyzp_ybqx00_yibin” 全部替换为 “# hyzp_ybqx04_changning” // D、将 “hyzp_ybqx00_yibin” 全部替换为 “hyzp_ybqx04_changning” // 5、完成以上修改后,打开 Android Studio 的终端窗口,切换到项目的 lib 目录下,运行 flutter clean // 6、重新编译运行App // end hyzp_ybqx-Commit022-区县切换新方法-OK //////////////////////////////////////////// //LED字幕信息 //String g_ledMessage = '绿水青山就是金山银山 宜宾市翠屏生态环境局宣。'; // 是否已经调用 FlutterDownloader.initialize(debug: true) bool bFlutterDownloader_initialize = false; bool bNewVer = false; //是否发现新版本 //处理延时登录,判断从网络获取三种统计数据是否完成 bool bMayLogin = false; //处理延时登录,判断是否已经点击登录按钮 bool bPreLoading = false; //处理延时登录,判断用户名登录是否验证通过 bool bLoginVerify = false; bool bHasMore = true; //part library //dart中,通过使用part、part of、library来实现拆分库,这样,就可以将一个庞大的库拆分成各种小库,只要引用主库即可 //点位总数 int dwSum = -1; Size sizeWindowPhysicalSize; //String dateAppCompile = '2020.12.30'; //1.0.1+1 //String dateAppCompile = '2021.02.20'; //1.2.5+1 //String dateAppCompile = '2021.03.18'; //1.2.6+1 //String dateAppCompile = '2021.05.18'; //1.2.7 List g_list = []; //正在获取点位视频标志,禁止重入 bool getingDwVideo = false; int getCount = 1; //获取点位视频地址尝试次数 int getSumTime = 0; //获取点位视频地址耗时(秒) int getingIndex = -1; //正在获取视频的点位的索引号 String getingDwmc = ''; //正在获取视频的点位名称 String urlnew = "http://www.yibinu.edu.cn/__local/5/35/DF/264049B7E978EEE2F5849688986_05D4A6FE_152CDB8C.mp4?e=.mp4"; bool isVideoUrl(String url, {bool showToast = false}) { print('url = $url'); String prefix = url.substring(0, 4); List list = ['http', 'rtmp', 'rstp']; for (String item in list) { if (prefix == item) { return true; } } if (showToast) { Fluttertoast.showToast( msg: '获取视频地址失败', toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.CENTER, ); } return false; } final TextEditingController myController = TextEditingController(); bool Playing = false; //禁止同时启动两次播放器 //final FijkPlayer player = FijkPlayer(); int g_iIndex = 0; PlayerRegionProvide playerRegionProvide; Future sysPop() async { // currentPos = player.currentPos.inMilliseconds; //seekto方法的参数是毫秒 // await writeCurrentPosFile(); // await player.stop(); await SystemChannels.platform.invokeMethod('SystemNavigator.pop'); } //人脸注册和人脸识别登录成功标志 int faceReg = -1; //1 成功,0 失败,-1 处理中 int faceLogin = -1; //1 成功,0 失败,-1 处理中 //人脸注册时所需用户ID int faceRegUserID = -1; //人脸注册时所需用户ID,-1 非法 List cameras; UserInfo g_userInfo = UserInfo(mapUserInfoRet: { "ret": 200, "data": { "is_login": true, "user_id": 1, "token": "B93EC91FA2FE293B7077162D4527FC4BB228CD6C0A4F24A882B9A8BBE6C3FB47" }, "msg": "" }); Future getMapFromJson(var response) async { String _str = json.encode(response); Map _map = json.decode(_str); return _map; } // Future getVideoList(BuildContext context) async { // List assets = []; // return await MyAssetPicker.pickAssets( // context, // maxAssets: 1, // selectedAssets: assets, // requestType: RequestType.video, // ); // } Future getAndroidId() async { DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; //print('每个手机唯一的设备号:${androidInfo.androidId}'); // e.g. "Moto G (4)" g_userInfo.thisAndroidId = androidInfo.androidId; return g_userInfo.thisAndroidId; } // void playOrPause() { // playerRegionProvide.changePlayerState(bPlaying); // // if (bPlaying) { // player.start(); // } else { // player.pause(); // } // // Storage.setString('bFirstPlay', bFirstPlay ? 'true' : 'false'); // Storage.setString('bPlaying', bPlaying ? 'true' : 'false'); // // //updateFile(); // } // // void playAndPause() { // if (player.state == FijkState.started) { // bPlaying = false; // player.pause(); // } else if (player.state == FijkState.paused) { // bPlaying = true; // player.start(); // } // //setState(() {}); // playerRegionProvide.changePlayerState(bPlaying); // Storage.setString('bPlaying', bPlaying ? 'true' : 'false'); // } Alignment getAlignment(Offset offset, Size size) { // final double centerX = offset.dx / 2.0; // final double centerY = offset.dy / 2.0; //offset.dx = centerX + alignment.x * centerX; //double alignmentX = (0.0 == centerX) ? 0.0 : ((offset.dx - centerX) / centerX); double alignmentX = (offset.dx / size.width).clamp(-1.0, 1.0); //offset.dy = centerY + alignment.y * centerY; //double alignmentY = (0.0 == centerY) ? 0.0 : ((offset.dy - centerY) / centerY); double alignmentY = (offset.dy / size.height).clamp(-1.0, 1.0); // print('offset.dx = ${offset.dx}, offset.dy = ${offset.dy}'); print('Alignment.X = $alignmentX, Alignment.Y = $alignmentY'); return Alignment(alignmentX, alignmentY); } //flutter (dart)生成N位随机数 //https://blog.csdn.net/qq_36071410/article/details/101268640 // 庄童 2019-09-24 10:24:58 10271 收藏 String RandomBit(int len) { String scopeF = '123456789'; //首位 String scopeC = '0123456789'; //中间 String result = ''; for (int i = 0; i < len; i++) { if (i == 0) { result = scopeF[Random().nextInt(scopeF.length)]; } else { result = result + scopeC[Random().nextInt(scopeC.length)]; } } return result; } // sign=md5(ijddvzgEGaxbzsbmCtpdohxHyrAArwJB1003) // =3967eaebec0eed0642a1d395ac9293dd String APPkey = 'ijddvzgEGaxbzsbmCtpdohxHyrAArwJB'; //Flutter对字符串进行MD5运算 发表于 2019-03-26 更新于 2020-12-04 分类于 Flutter 阅读次 String GenerateMd5(String str) { var content = new Utf8Encoder().convert(str); var md5 = crypto.md5; var digest = md5.convert(content); return hex.encode(digest.bytes); } //加载中的圈圈 Widget getMoreWidget2({ Color color = Colors.white, String text = '加载中...', double size = 30.0, double strokeWidth = 3.0, FontWeight fontWeight, double edge = 10.0, double height = 34, }) { return Center( child: Padding( padding: EdgeInsets.all(edge), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ SizedBox( height: size, width: size, child: CircularProgressIndicator( strokeWidth: strokeWidth, valueColor: AlwaysStoppedAnimation(color), ), ), SizedBox( height: ScreenUtil().setHeight(height), ), Text( text, textAlign: TextAlign.center, style: TextStyle( fontSize: size, // 文字大小 color: color, fontWeight: fontWeight, // 文字颜色 ), ), ], ), ), ); } //加载中的圈圈 Widget getMoreWidget({ String text = '加载中...', Color color = Colors.white, double size = 30.0, double strokeWidth = 3.0, TextAlign textAlign = TextAlign.left, }) { return Center( child: Padding( padding: EdgeInsets.all(10.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ SizedBox( height: size, width: size, child: CircularProgressIndicator( strokeWidth: strokeWidth, valueColor: AlwaysStoppedAnimation(color), ), ), SizedBox( height: 10, ), Text( text, textAlign: textAlign, style: TextStyle( fontSize: size, // 文字大小 color: color, ), ), ], ), ), ); } //自定义带说明图标按钮函数。点击说明文字有反应 Widget getIconAndTextButton( {IconData iconData, Color iconColor = Colors.black, var onPress = null}) { return Container( width: 50, height: 50, alignment: const Alignment(0, 0), child: FlatButton( padding: EdgeInsets.all(0), onPressed: onPress, //color: Colors.blue, color: Colors.transparent, //解决报错问题:FittedBox ← Expanded ← ConstrainedBox ← Container ← Center ← Padding ← // Container ← IconTheme ← Builder ← _PointerListener child: ConstrainedBox( constraints: BoxConstraints( maxHeight: 36, //最大高度 maxWidth: 36, //最大宽度 ), child: Padding( padding: EdgeInsets.only(top: 1), child: Icon(iconData, color: iconColor, size: 32), // child: Image.asset( // 'assets/images/left_arrow.png', // fit: BoxFit.fitWidth, // color: iconColor, // //fit: BoxFit.cover, // ), ), // child: Row( // mainAxisAlignment: MainAxisAlignment.center, // crossAxisAlignment: CrossAxisAlignment.end, // children: [ // Image.asset('assets/images/left_arrow.png', fit: BoxFit.cover), // // Expanded( // // //child: Icon(iconData, color: iconColor, size: 24), // // child: Image.asset('assets/images/left_arrow.png', fit: BoxFit.cover), // // ), // ], // ), ), //The offending Expanded is currently placed inside a ConstrainedBox widget. //The ownership chain for the RenderObject that received the incompatible parent data was: // FittedBox ← Expanded ← ConstrainedBox ← Container ← Center ← Padding ← Container ← IconTheme ← //Builder ← _PointerListener //The ParentDataWidget Expanded(flex: 1) wants to apply ParentData of type FlexParentData to a //RenderObject, which has been set up to accept ParentData of incompatible type ParentData. //Usually, this means that the Expanded widget has the wrong ancestor RenderObjectWidget. Typically, //Expanded widgets are placed directly inside Flex widgets. //The offending Expanded is currently placed inside a FittedBox widget. //The ownership chain for the RenderObject that received the incompatible parent data was: // ConstrainedBox ← Container ← Expanded ← FittedBox ← Center ← Padding ← Container ← IconTheme ← //Builder ← _PointerListener ← ⋯ // child: ConstrainedBox( // constraints: BoxConstraints( // maxHeight: 20, //最大高度 // maxWidth: 28, //最大宽度 // ), // child: Container( // child: Expanded( // child: new Icon(iconData, color: iconColor), // ), // ), // ), // child: ConstrainedBox( // constraints: BoxConstraints( // maxHeight: 30, //最大高度 // maxWidth: 38, //最大宽度 // minWidth: 38, //最大宽度 // ), // child: Row( // crossAxisAlignment: CrossAxisAlignment.start, // children: [ // Expanded( // child: Icon(iconData, color: iconColor, size: 24), // ), // ], // ), // ), // child: Container( // width: 28, // height: 20, // child: Expanded( // child: new FittedBox( // fit: BoxFit.fill, // child: new Icon(iconData, color: iconColor), // ), // ), // ), // child: FittedBox( // fit: BoxFit.fitWidth, // alignment: Alignment.topLeft, // child: Container( // width: 28, // height: 20, // child: Expanded( // child: new FittedBox( // fit: BoxFit.fill, // child: new Icon(iconData, color: iconColor), // ), // ), // ), // ), ), ); } ///获取缩进空白符 String getDeepSpace(int deep) { var tab = StringBuffer(); for (int i = 0; i < deep; i++) { tab.write("\t"); } return tab.toString(); } // List map2list(Map _map) { // List _list = []; // _list = List.generate(listContacts2[widget.contactIndex].length, (index) { // String key = listContacts2[widget.contactIndex].keys.elementAt(index); // //return TextEditingController(text: listContacts2[widget.contactIndex][key]); // return TextEditingController(text: getUserText3(widget.contactIndex, key)); // }); // // } /// [object] 解析的对象 /// [deep] 递归的深度,用来获取缩进的空白长度 /// [isObject] 用来区分当前map或list是不是来自某个字段,则不用显示缩进。单纯的map或list需要添加缩进 String json_print(dynamic object, int deep, {bool isObject = false}) { var buffer = StringBuffer(); var nextDeep = deep + 1; if (object is Map) { var list = object.keys.toList(); if (!isObject) { //如果map来自某个字段,则不需要显示缩进 buffer.write("${getDeepSpace(deep)}"); } buffer.write("{"); if (list.isEmpty) { //当map为空,直接返回‘}’ buffer.write("}"); } else { buffer.write("\n"); for (int i = 0; i < list.length; i++) { buffer.write("${getDeepSpace(nextDeep)}\"${list[i]}\":"); buffer.write(json_print(object[list[i]], nextDeep, isObject: true)); if (i < list.length - 1) { buffer.write(","); buffer.write("\n"); } } buffer.write("\n"); buffer.write("${getDeepSpace(deep)}}"); } } else if (object is List) { if (!isObject) { //如果list来自某个字段,则不需要显示缩进 buffer.write("${getDeepSpace(deep)}"); } buffer.write("["); if (object.isEmpty) { //当list为空,直接返回‘]’ buffer.write("]"); } else { buffer.write("\n"); for (int i = 0; i < object.length; i++) { buffer.write(json_print(object[i], nextDeep)); if (i < object.length - 1) { buffer.write(","); buffer.write("\n"); } } buffer.write("\n"); buffer.write("${getDeepSpace(deep)}]"); } } else if (object is String) { //为字符串时,需要添加双引号并返回当前内容 buffer.write("\"$object\""); } else if (object is num || object is bool) { //为数字或者布尔值时,返回当前内容 buffer.write(object); } else { //如果对象为空,则返回null字符串 buffer.write("null"); } return buffer.toString(); } //人脸识别和上传的图片,都需要转换为 Base64 格式的字符串提交 //通过图片路径将图片转换成 Base64 字符串 Future image2Base64(String imagePath) async { File file = File(imagePath); List imageBytes = await file.readAsBytes(); String bs64 = base64Encode(imageBytes); String ext = getFileExtension(imagePath); print('imagePath = $imagePath, ext = $ext'); //String bs64Image = "data:image/png;base64," + bs64; String bs64Image = "data:image/${ext};base64," + bs64; return bs64Image; } //从字符路径 path 获取扩展名,不含点号 getFileExtension(String path) { //return path.substring(path.lastIndexOf('.')); //imagePath = /data/user/0/com.flutter.hyzp_ybqx04_changning/app_flutter/Pictures/flutter_test/1614662209478.jpg, ext = .jpg return path.substring(path.lastIndexOf('.') + 1); //不含点号 } //从字符路径 path 获取文件名(含扩展名) getFileName(String path) { //return path.substring(path.lastIndexOf('.')); //imagePath = /data/user/0/com.flutter.hyzp_ybqx04_changning/app_flutter/Pictures/flutter_test/1614662209478.jpg, ext = .jpg return path.substring(path.lastIndexOf('/') + 1); //不含点号 } Widget getBtnSizeX({@required text, double width = 70.0, double height = 40.0, onPressedFun}) { return Container( color: Colors.white12, //onPressedFun为null时无效 width: width, height: height, child: RaisedButton( padding: EdgeInsets.all(0), textColor: Colors.black, child: Text(text), onPressed: onPressedFun, ), ); } //返回主页ashamp // 博客园首页新随笔联系管理订阅订阅随笔 - 33 文章 - 0 评论 - 51 阅读 - 55018 // 在debug时使Flutter中的print打印json数据时更美观易读 // 为了避免deubg信息在生产环境打印,只在测试时打印,在main函数中,改变debugPrint的指向 // // 复制代码 // main(){ // if (Api.isDebug) { // debugPrint = (String message, {int wrapWidth}) { // try { // var object = json.decode(message); // message = JsonEncoder.withIndent(' ').convert(object); // } catch (e) {} // printWrapped(message); // }; // } else { // debugPrint = (String message, {int wrapWidth}) {}; // } // } // 复制代码 // 将printWrapped方法放入工具类或你需要的地方 // // void printWrapped(String text) { // final pattern = new RegExp('.{1,800}'); // 800 is the size of each chunk // pattern.allMatches(text).forEach((match) => developer.log(match.group(0))); // } // log方法需要引入 // // import 'dart:developer' as developer; // //在debug时使 Flutter 中的 print 打印 json 数据时更美观易读 void jsonPrint(String message, {int len = 800}) { //是否在生产环境 const bool isDebug = !const bool.fromEnvironment("dart.vm.product"); // if (!isDebug) { // return; // } try { var object = json.decode(message); message = JsonEncoder.withIndent(' ').convert(object); } catch (e) { print('e = $e'); } printWrapped(message); } // 打印长字符串 void printWrapped(String text, {int len = 800}) { final pattern = RegExp('.{1,$len}'); // 800 is the size of each chunk pattern.allMatches(text).forEach((match) => developer.log(match.group(0))); } //OK void my_segmentPrint(String str, {int len = 800}) { //是否在生产环境 const bool isDebug = !const bool.fromEnvironment("dart.vm.product"); if (!isDebug) { return; } List list = strToList(str); for (int i = 0; i < list.length; i++) { print('${list[i]}'); } } //OK List strToList(String str, {int len = 800}) { List strList = []; if (str.length <= len) { strList.add(str); } else { int splitCount = str.length ~/ len; //应该切割的次数 for (int i = 0; i < splitCount; i++) { strList.add(str.substring(len * i, len * (i + 1))); } //处理最后一段 if (str.length % len != 0) { strList.add(str.substring(len * splitCount)); } } print('strList:${strList.toString}'); return strList; } Widget getImageWidget() { return Container( alignment: Alignment(0, 0), height: ScreenUtil().setHeight(346), width: ScreenUtil().setWidth(942), decoration: BoxDecoration( image: DecorationImage(image: AssetImage('assets/images/装饰图片10.png'), fit: BoxFit.cover), ), child: Column( children: [ Container( alignment: Alignment.centerLeft, padding: EdgeInsets.only(top: ScreenUtil().setWidth(30), left: ScreenUtil().setWidth(55)), child: Text('改善城市空气质量', style: TextStyle(fontSize: 17, color: Colors.white)), ), Container( alignment: Alignment.centerLeft, padding: EdgeInsets.only(left: ScreenUtil().setWidth(55)), child: Text('建设长江生态第一城', style: TextStyle( fontSize: 19, color: Color.fromRGBO(49, 216, 123, 1), fontWeight: FontWeight.bold)), ), ], ), // child: Image.asset( // 'assets/images/装饰图片10.png', // fit: BoxFit.cover, // ), ); } Widget getIconBtnSizeX( {@required text, width = 233, height = 116, onTop, Color color = Colors.black, double circular = 10, double textSize = 18}) { return InkWell( onTap: onTop, child: Container( alignment: Alignment(0, 0), margin: EdgeInsets.all(0), padding: EdgeInsets.all(0), width: ScreenUtil().setWidth(width), height: ScreenUtil().setHeight(height), decoration: BoxDecoration(color: color, borderRadius: BorderRadius.circular(circular)), child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ SizedBox(width: ScreenUtil().setWidth(12)), Icon(Icons.play_arrow, color: Colors.white, size: ScreenUtil().setWidth(56)), Text( text, style: TextStyle(color: Colors.white, fontSize: textSize), ) ], ), ), ); }