import 'dart:io'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter_wallet/tools/YSColors.dart'; import 'package:open_file/open_file.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:path_provider/path_provider.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:webview_flutter/webview_flutter.dart'; // import 'package:url_launcher/url_launcher_string.dart'; import 'YSTools.dart'; class YSVersionView extends StatefulWidget { final String content; final String url; final String title; final bool isBack; const YSVersionView({Key? key, required this.content, required this.url, required this.title, this.isBack = true}) : super(key: key); @override YSVersionViewState createState() => YSVersionViewState(); } class YSVersionViewState extends State { int _progress = 0; bool _isTap = false; final WebViewController _webViewController = WebViewController(); @override void initState() { _webViewController.loadHtmlString(''' ${widget.content} '''); super.initState(); } @override Widget build(BuildContext context) { return WillPopScope( onWillPop: () async{ return widget.isBack; }, child: Center(child: Container( height: hsp(330), width: ysWidth(context)-hsp(100), decoration: BoxDecoration( color: YSColors.containColor(context), borderRadius: const BorderRadius.all(Radius.circular(5)) ), padding: EdgeInsets.all(hsp(10)), child: Column( children: [ Container( height: hsp(30), alignment: Alignment.center, child: centerAlertText(widget.title, size: 18, color: YSColors.iconColor(context),line: 100), ), Container( height: hsp(230), alignment: Alignment.topLeft, padding: const EdgeInsets.only(bottom: 10), child: WebViewWidget( controller: _webViewController, ) // SingleChildScrollView( // padding: EdgeInsets.all(hsp(5)), // child: centerAlertText(widget.content, size: 15, // color: YSColors.iconColor(context),line: 100), // ), ), GestureDetector( onTap: () async{ if(_isTap)return; if(Platform.isAndroid==true){ bool isPer = await _checkPermission(); if(isPer==true){ _isTap = true; _installApk(widget.url); } }else if(Platform.isIOS==true){ // launchUrlString(widget.url); } }, behavior: HitTestBehavior.opaque, child: Container( height: hsp(40), margin: EdgeInsets.only(left: hsp(20),right: hsp(20)), decoration: const BoxDecoration( color: Color(0xFF146DFE), borderRadius: BorderRadius.all(Radius.circular(3)) ), alignment: Alignment.center, child: centerAlertText('立即升级${_progress==0||_progress==100?'':' $_progress%'}', color: Colors.white, size: 15,), ), ), ], ), )), ); } Future _checkPermission() async { if(Platform.isAndroid==true){ if (await Permission.requestInstallPackages.request().isDenied) { Map statuses = await [ Permission.requestInstallPackages, ].request(); if(statuses[Permission.requestInstallPackages]!.isDenied){ return false; } } } return true; } Future _downloadAndroid(String url) async { PackageInfo packageInfo = await PackageInfo.fromPlatform(); /// 创建存储文件 Directory? storageDir = await getExternalStorageDirectory(); String storagePath = storageDir!.path; File file = File('$storagePath/${packageInfo.appName}v' '${packageInfo.buildNumber}.apk'); if (!file.existsSync()) { file.createSync(); } try { /// 发起下载请求 Response response = await Dio().get(url, onReceiveProgress: showDownloadProgress, options: Options(responseType: ResponseType.bytes,followRedirects: false, )); file.writeAsBytesSync(response.data); return file; } catch (e) { return null; } } /// 安装apk Future _installApk(String url) async { File? apkFile = await _downloadAndroid(url); String apkFilePath = apkFile!.path; if (apkFilePath.isEmpty) { return; } OpenFile.open(apkFilePath); } /// 展示下载进度 void showDownloadProgress(num received, num total) { if (total != -1) { _progress = int.parse('${(received / total~/0.01)}'); setState(() {}); if(_progress==100){ _isTap = false; } } } } centerAlertText(String text,{Color color = Colors.white,required int size,bool isBold = false,int line = 1}) { return Text(text,style: TextStyle(fontSize: zsp(size),color: color,decoration: TextDecoration.none, fontWeight: isBold?FontWeight.bold:FontWeight.normal,),maxLines: line,overflow: TextOverflow.ellipsis,); }