YSVersionView.dart 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. import 'dart:io';
  2. import 'package:dio/dio.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:flutterappfuyou/code/base/YSTools.dart';
  5. import 'package:open_file/open_file.dart';
  6. import 'package:package_info/package_info.dart';
  7. import 'package:path_provider/path_provider.dart';
  8. import 'package:permission_handler/permission_handler.dart';
  9. import 'package:url_launcher/url_launcher_string.dart';
  10. class YSVersionView extends StatefulWidget {
  11. final String content;
  12. final String url;
  13. final String buildNumber;
  14. final bool isMust;
  15. const YSVersionView({Key key, this.content = '', this.url = '', this.buildNumber, this.isMust=false}) : super(key: key);
  16. @override
  17. YSVersionViewState createState() => YSVersionViewState();
  18. }
  19. class YSVersionViewState extends State<YSVersionView> {
  20. int _progress = 0;
  21. bool _isTap = false;
  22. @override
  23. Widget build(BuildContext context) {
  24. return WillPopScope(
  25. onWillPop: () async{
  26. return false;
  27. },
  28. child: Center(child: Container(
  29. height: 390,
  30. width: ysWidth(context)-100,
  31. decoration: const BoxDecoration(
  32. color: Colors.white,
  33. borderRadius: BorderRadius.all(Radius.circular(5))
  34. // image: DecorationImage(image: AssetImage('images/组version.png',),fit: BoxFit.fill)
  35. ),
  36. padding: EdgeInsets.all(10),
  37. child: Column(
  38. crossAxisAlignment: CrossAxisAlignment.end,
  39. children: [
  40. Container(
  41. height: 40,
  42. child: centerAlertText('发现新版本', size: 16,color: Colors.black,isBold: true),
  43. alignment: Alignment.center,
  44. ),
  45. Container(
  46. margin: EdgeInsets.only(top: 10),
  47. height: 320,
  48. child: Column(
  49. children: [
  50. Container(
  51. height: 230,
  52. alignment: Alignment.topLeft,
  53. padding: const EdgeInsets.all(0),
  54. child: SingleChildScrollView(
  55. padding: EdgeInsets.all(5),
  56. child: centerAlertText('新版本更新说明\n${widget.content}', size: 15,
  57. color: const Color(0xFFAFAFAF),line: 100),
  58. ),
  59. ),
  60. GestureDetector(
  61. onTap: () async{
  62. if(_isTap)return;
  63. if(Platform.isAndroid==true){
  64. bool isPer = await _checkPermission();
  65. if(isPer==true){
  66. _isTap = true;
  67. _installApk(widget.url);
  68. }
  69. }else if(Platform.isIOS==true){
  70. launchUrlString(widget.url);
  71. }
  72. },
  73. behavior: HitTestBehavior.opaque,
  74. child: Container(
  75. height: 40,
  76. margin: EdgeInsets.only(left: 20,right: 20,top: widget.isMust?30:10,bottom: 10),
  77. decoration: const BoxDecoration(
  78. color: Colors.pinkAccent,
  79. borderRadius: BorderRadius.all(Radius.circular(3))
  80. ),
  81. alignment: Alignment.center,
  82. child: centerAlertText('立即升级${_progress==0||_progress==100?'':' $_progress%'}',
  83. color: Colors.white, size: 15,),
  84. ),
  85. ),
  86. if(widget.isMust==false)GestureDetector(
  87. onTap: (){Navigator.pop(context);},
  88. behavior: HitTestBehavior.opaque,
  89. child: Container(
  90. height: 30,
  91. margin: EdgeInsets.only(left: 20,right: 20),
  92. alignment: Alignment.center,
  93. child: centerAlertText('稍后升级',color: const Color(0xFFAFAFAF), size: 15,),
  94. ),
  95. )
  96. ],
  97. ),
  98. )
  99. ],
  100. ),
  101. )),
  102. );
  103. }
  104. Future<bool> _checkPermission() async {
  105. if(Platform.isAndroid==true){
  106. if (await Permission.requestInstallPackages.request().isDenied) {
  107. Map<Permission, PermissionStatus> statuses = await [
  108. Permission.requestInstallPackages,
  109. ].request();
  110. if(statuses[Permission.requestInstallPackages].isDenied){
  111. return false;
  112. }
  113. }
  114. }
  115. return true;
  116. }
  117. Future<File> _downloadAndroid(String url) async {
  118. PackageInfo packageInfo = await PackageInfo.fromPlatform();
  119. /// 创建存储文件
  120. Directory storageDir = await getExternalStorageDirectory();
  121. String storagePath = storageDir.path;
  122. File file = File('$storagePath/${packageInfo.appName}v'
  123. '${packageInfo.buildNumber}.apk');
  124. if (!file.existsSync()) {
  125. file.createSync();
  126. }
  127. try {
  128. LogUtil.d(url);
  129. /// 发起下载请求
  130. Response response = await Dio().get(
  131. url,
  132. onReceiveProgress: showDownloadProgress,
  133. options: Options(responseType: ResponseType.bytes,followRedirects: true,)
  134. );
  135. file.writeAsBytesSync(response.data);
  136. return file;
  137. } catch (e) {
  138. LogUtil.d(e);
  139. return null;
  140. }
  141. }
  142. /// 安装apk
  143. Future<void> _installApk(String url) async {
  144. File apkFile = await _downloadAndroid(url);
  145. String apkFilePath = apkFile.path;
  146. if (apkFilePath.isEmpty) {
  147. return;
  148. }
  149. OpenFile.open(apkFilePath);
  150. }
  151. /// 展示下载进度
  152. void showDownloadProgress(num received, num total) {
  153. if (total != -1) {
  154. _progress = int.parse('${(received / total~/0.01)}');
  155. setState(() {});
  156. if(_progress==100){
  157. _isTap = false;
  158. }
  159. }
  160. }
  161. }
  162. centerAlertText(String text,{Color color = Colors.white,double size,bool isBold = false,int line = 1}) {
  163. return Text(text,style: TextStyle(fontSize: size,color: color,decoration: TextDecoration.none,
  164. fontWeight: isBold?FontWeight.bold:FontWeight.normal,),maxLines: line,overflow: TextOverflow.ellipsis,);
  165. }