library aku_app_upgrade; import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:dio/dio.dart'; import 'package:r_upgrade/r_upgrade.dart'; const apkLink = 'https://saas.kaidalai.cn/resource/appPackage/app.apk'; enum ForceUpgrade { force(1), unForce(2); final int typeNum; static ForceUpgrade getValue(int value) => ForceUpgrade.values.firstWhere((element) => element.typeNum == value); const ForceUpgrade(this.typeNum); } enum AndroidStoreName { googlePlay('谷歌商店', 'com.android.vending'), tencent('应用宝', 'com.tencent.android.qqdownloader'), qihoo('360手机助手', 'com.qihoo.appstore'), baidu('百度手机助手', 'com.baidu.appsearch'), xiaomi('小米应用商店', 'com.xiaomi.market'), wandou('豌豆荚', 'com.wandoujia.phoenix2'), huawei('华为应用市场', 'com.huawei.appmarket'), taobao('淘宝手机助手', 'com.taobao.appcenter'), hiApk('安卓市场', 'com.hiapk.marketpho'), goApk('安智市场', 'cn.goapk.market'), coolApk('酷安', 'com.coolapk.market'), empty('', ''); final String name; final String packageName; static AndroidStoreName getValue(String packageName) { return AndroidStoreName.values.firstWhere( (element) => element.packageName == packageName, orElse: () => AndroidStoreName.empty); } AndroidStore get getAndroidStore => AndroidStore.internal(packageName); const AndroidStoreName(this.name, this.packageName); } class AppUpgrade { static final AppUpgrade _instance = AppUpgrade._(); factory AppUpgrade() => _instance; AppUpgrade._(); Future checkUpgrade( BuildContext context, { Function(String)? onError, Function(Map)? onRequestFail, Function()? onLaunchFail, }) async { WidgetsFlutterBinding.ensureInitialized(); PackageInfo packageInfo = await PackageInfo.fromPlatform(); int buildNo = int.parse(packageInfo.buildNumber); if (kDebugMode) { print('当前版本号:${packageInfo.version}${packageInfo.buildNumber}'); } Response? response; try { response = await Dio().get( 'http://121.41.26.225:8006/app/version/findNewVersion', queryParameters: {'buildNo': buildNo}); } catch (e) { onError?.call(e.toString()); return; } if (kDebugMode) { print('查询最新版本结果:${response.data}'); } if (response.data['success']) { AkuAppVersion akuAppVersion = AkuAppVersion.fromMap(response.data['data']); if (buildNo < akuAppVersion.buildNo) { await showDialog( context: context, barrierDismissible: akuAppVersion.forceEM != ForceUpgrade.force, builder: (context) { return WillPopScope( onWillPop: () async { return akuAppVersion.forceEM != ForceUpgrade.force; }, child: upgradeDialog( context, packageInfo, onLaunchFail, akuAppVersion)); }); } } else { onRequestFail?.call(response.data); } } upgradeDialog(BuildContext context, PackageInfo packageInfo, Function()? onLaunchFail, AkuAppVersion akuAppVersion) { return Center( child: Container( width: 300, height: 200, clipBehavior: Clip.antiAliasWithSaveLayer, decoration: BoxDecoration( color: Colors.white, boxShadow: const [ BoxShadow( color: Colors.blue, blurRadius: 5, spreadRadius: 0, ) ], borderRadius: BorderRadius.circular(24), ), child: Material( child: Container( decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, stops: [ 0, 0.7 ], colors: [ Color(0x33FBE541), Colors.white, ])), child: Column( children: [ const Padding( padding: EdgeInsets.all(32), child: Text( '当前不是最新版本\n请升级最新版', textAlign: TextAlign.center, style: TextStyle( color: Colors.black, fontSize: 22, fontWeight: FontWeight.bold), ), ), const Spacer(), Container( height: 1, width: double.infinity, color: Colors.black.withOpacity(0.45), ), SizedBox( height: 50, child: Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ if (akuAppVersion.forceEM != ForceUpgrade.force) Expanded( child: MaterialButton( onPressed: () { Navigator.pop(context); }, child: const Text( '取消', style: TextStyle( color: Colors.black, fontSize: 20, fontWeight: FontWeight.normal), ), ), ), Offstage( offstage: akuAppVersion.forceEM == ForceUpgrade.force, child: Container( height: double.infinity, width: 1, color: Colors.black.withOpacity(0.45), ), ), Expanded( child: MaterialButton( onPressed: () async { if (Platform.isAndroid) { showModalBottomSheet( isDismissible: false, context: context, builder: (context) { return Container( child: Column( children: [ const SizedBox(height: 20), const Text('选择下载途径',style: TextStyle(fontSize: 24),), const Divider(), GestureDetector( onTap: () async{ await RUpgrade.upgrade(apkLink); }, child: Padding( padding: const EdgeInsets.only(top: 0), child: Column(children: [ const Divider(), SizedBox( height: 20, child:Text( '直接下载',style:const TextStyle(fontSize: 14,),), ), ],) ), ), const Divider(), GestureDetector( onTap: () async{ var stores = await RUpgrade.androidStores; if (stores == null || stores.isEmpty) { onLaunchFail?.call(); return; } var storeEMs = []; for (var element in stores) { var re = AndroidStoreName.getValue( element.packageName); if (re != AndroidStoreName.empty) { storeEMs.add(re); } } AndroidStoreName? selectStore; selectStore = await showModalBottomSheet( isDismissible: false, context: context, builder: (context) { return Container( // decoration: const BoxDecoration(gradient: LinearGradient( // begin: Alignment.topCenter, // end: Alignment.bottomCenter, // stops: [ // 0, // 0.7 // ], // colors: [ // Color(0x33FBE541), // Colors.white, // ]), // // borderRadius: BorderRadius.only( // // topLeft: Radius.circular(25.0), // // topRight: Radius.circular(25.0)) // ), child: Column( children: [ const SizedBox(height: 20), const Text('选择应用商店',style: TextStyle(fontSize: 24),), Expanded( child: ListView.separated( itemBuilder: (context, index) { return GestureDetector( onTap: () { Navigator.pop(context, storeEMs[index]); }, child: Padding( padding: const EdgeInsets.only(top: 0), child: Column(children: [ const Divider(), SizedBox( height: 20, child:Text( storeEMs[index] .name,style:const TextStyle(fontSize: 14,),), ), ],) ), ); }, separatorBuilder: (context, index) { return const SizedBox( height: 10, ); }, itemCount: storeEMs.length), ), GestureDetector(onTap: (){ Navigator.pop(context); },child: const Text('取消',style: TextStyle(fontSize: 20),),) ], ), ); }); await Future.delayed(Duration.zero, () async { if (selectStore == null) return; }); await RUpgrade.upgradeFromAndroidStore( selectStore!.getAndroidStore); }, child: Padding( padding: const EdgeInsets.only(top: 0), child: Column(children: [ const Divider(), SizedBox( height: 20, child:Text( '应用市场',style:const TextStyle(fontSize: 14,),), ), ],) ), ), ], ), ); }); } else if (Platform.isIOS) { await RUpgrade.upgradeFromAppStore( packageInfo.packageName); } else {} }, child: const Text( '去升级', style: TextStyle( color: Colors.black, fontSize: 20, fontWeight: FontWeight.normal), ), ), ) ], ), ), ], ), ), ), ), ); } } class AkuAppVersion { final int id; final String versionNumber; final int buildNo; final int forceUpdate; final String createDate; ForceUpgrade get forceEM => ForceUpgrade.getValue(forceUpdate); // const AkuAppVersion({ required this.id, required this.versionNumber, required this.buildNo, required this.forceUpdate, required this.createDate, }); @override bool operator ==(Object other) => identical(this, other) || (other is AkuAppVersion && runtimeType == other.runtimeType && id == other.id && versionNumber == other.versionNumber && buildNo == other.buildNo && forceUpdate == other.forceUpdate && createDate == other.createDate); @override int get hashCode => id.hashCode ^ versionNumber.hashCode ^ buildNo.hashCode ^ forceUpdate.hashCode ^ createDate.hashCode; @override String toString() { return 'AkuAppVersion{ id: $id, versionNumber: $versionNumber, buildNo: $buildNo, forceUpdate: $forceUpdate, createDate: $createDate,}'; } AkuAppVersion copyWith({ int? id, String? versionNumber, int? buildNo, int? forceUpdate, String? createDate, }) { return AkuAppVersion( id: id ?? this.id, versionNumber: versionNumber ?? this.versionNumber, buildNo: buildNo ?? this.buildNo, forceUpdate: forceUpdate ?? this.forceUpdate, createDate: createDate ?? this.createDate, ); } Map toMap() { return { 'id': id, 'versionNumber': versionNumber, 'buildNo': buildNo, 'forceUpdate': forceUpdate, 'createDate': createDate, }; } factory AkuAppVersion.fromMap(Map map) { return AkuAppVersion( id: map['id'] as int, versionNumber: map['versionNumber'] as String, buildNo: map['buildNo'] as int, forceUpdate: map['forceUpdate'] as int, createDate: map['createDate'] as String, ); } // }