瀏覽代碼

1、网络请求的头部统一参数

2、淘宝授权修改
3、app更新的修改。
tags/0.0.2
PH2 4 年之前
父節點
當前提交
d17a6a5037
共有 7 個文件被更改,包括 345 次插入219 次删除
  1. +2
    -2
      lib/models/user/user_info_model.dart
  2. +15
    -5
      lib/models/user/user_info_model_notifier.dart
  3. +127
    -90
      lib/util/net_util.dart
  4. +34
    -19
      lib/util/taobao/taobao_auth.dart
  5. +26
    -0
      lib/util/update/app_update_model.dart
  6. +137
    -102
      lib/util/update/app_update_util.dart
  7. +4
    -1
      pubspec.yaml

+ 2
- 2
lib/models/user/user_info_model.dart 查看文件

@@ -10,12 +10,12 @@ class UserInfoModel {
String username;
List<String> perms;
String registerInviteCodeEnable;
bool isTBAuth;
bool isTBAuth; // 是否淘宝授权

// 获取模糊手机号码
get blurMobile => !EmptyUtil.isEmpty(mobile) ? mobile.length == 11 ? '${mobile.substring(0, 3)}****${mobile.substring(7, mobile.length)}' : mobile : mobile;

UserInfoModel({this.token, this.userId, this.username, this.perms, this.registerInviteCodeEnable});
UserInfoModel({this.token, this.userId, this.username, this.perms, this.registerInviteCodeEnable, this.isTBAuth = false});

UserInfoModel.fromJson(Map<String, dynamic> json) {
token = json['token'];


+ 15
- 5
lib/models/user/user_info_model_notifier.dart 查看文件

@@ -28,15 +28,25 @@ class UserInfoNotifier with ChangeNotifier {
}
return _userInfo;
}
/// 更新淘宝授权
void updateUserAuth(bool isAuth){
if(_userInfo != null){
void updateUserAuth(bool isAuth) {
if (null == _userInfo) {
getUserInfoModel().then((user) {
if (user != null) {
_userInfo = user;
_userInfo.isTBAuth = isAuth;
Logger.log('upate data TBAuth');
notifyListeners();
}
});
} else {
_userInfo.isTBAuth = isAuth;
Logger.log('upate data TBAuth');
notifyListeners();
}
}
/// 更新用户数据
void setUserInfo(UserInfoModel loginUser) async {
print('${loginUser.toString()}');
@@ -73,7 +83,7 @@ class UserInfoNotifier with ChangeNotifier {
String userInfoJson = await SharedPreferencesUtil.getStringValue(
GlobalConfig.SHARED_KEY_USER_INFO);
if (userInfoJson == null || userInfoJson == '') {
_userInfo = UserInfoModel();
_userInfo = UserInfoModel();
} else {
_userInfo = UserInfoModel.fromJson(jsonDecode(userInfoJson));
}


+ 127
- 90
lib/util/net_util.dart 查看文件

@@ -1,3 +1,4 @@
import 'dart:collection';
import 'dart:convert';
import 'dart:io';
import 'dart:ui';
@@ -77,53 +78,46 @@ class NetUtil {

/// 设置代理
void _setProxy(String proxyUrl) {
(_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
(HttpClient client) {
(_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (HttpClient client) {
client.findProxy = (uri) {
return "PROXY $proxyUrl";
};
client.badCertificateCallback =
(X509Certificate cert, String host, int port) => true;
client.badCertificateCallback = (X509Certificate cert, String host, int port) => true;
};
}

/// 同步请求
static Future<dynamic> post(String path,
{Map<String, dynamic> params,
NetMethod method = NetMethod.POST,
bool cache = false}) async {
static Future<dynamic> post(String path, {Map<String, dynamic> params, NetMethod method = NetMethod.POST, bool cache = false}) async {
if (params == null) {
params = {};
}
// 根据请求参数,获取缓存的Key
String cacheKey = getRequestParamsCachedKey(params, path);
// 参数签名 TODO 加密?
Map<String, dynamic> sign = await signParams(params);
// post请求的参数
Map<String, dynamic> bodyParams = params;
// 请求头参数
Map<String, dynamic> headParam = await _getMustHeadParams();

Response response;
try {
String token = await SharedPreferencesUtil.getStringValue(
GlobalConfig.SHARED_KEY_TOKEN) ??
'';
Dio dio = await NetUtil.getInstance().dio;
response = await dio.request(path,
data: sign,
options: Options(method: enumToString(method), headers: {'token': token, 'app_version': sign['app_version']}),
// options: Options(method: enumToString(method), headers: sign),
response = await dio.request(
path,
data: !EmptyUtil.isEmpty(bodyParams) ? bodyParams : null,
options: Options(method: enumToString(method), headers: headParam),
);
} on DioError catch (e) {
_formatError(e);
}

try {
var result =
response.data is Map ? response.data : jsonDecode(response.data);
var result = response.data is Map ? response.data : jsonDecode(response.data);
// TODO 解密?
if (isSuccess(result)) {
// 缓存成功的数据
if (cache) {
_setCallBackCacheData(cacheKey,
response.data is Map ? jsonEncode(response.data) : response.data);
_setCallBackCacheData(cacheKey, response.data is Map ? jsonEncode(response.data) : response.data);
}
return result;
// 缓存返回的数据
@@ -145,12 +139,7 @@ class NetUtil {
}

/// 异步请求
static void request(String path,
{NetMethod method = NetMethod.GET,
Map<String, dynamic> params,
OnSuccess onSuccess,
OnError onError,
OnCache onCache}) async {
static void request(String path, {NetMethod method = NetMethod.GET, Map<String, dynamic> params, OnSuccess onSuccess, OnError onError, OnCache onCache}) async {
if (params == null) {
params = {};
}
@@ -173,11 +162,7 @@ class NetUtil {
}

if (onError != null) {
onError(!EmptyUtil.isEmpty(result)
? !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_MSG])
? result[GlobalConfig.HTTP_RESPONSE_KEY_MSG]
: '未知错误'
: '未知错误');
onError(!EmptyUtil.isEmpty(result) ? !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_MSG]) ? result[GlobalConfig.HTTP_RESPONSE_KEY_MSG] : '未知错误' : '未知错误');
}
} catch (e) {
Logger.error('error: ' + e.toString());
@@ -190,8 +175,85 @@ class NetUtil {
}

/// 统一添加必要的参数
static Future<Map<String, dynamic>> signParams(
Map<String, dynamic> params) async {
// static Future<Map<String, dynamic>> signParams(Map<String, dynamic> params) async {
// // 应用信息
// PackageInfo packageInfo = await PackageInfo.fromPlatform();
// // 原生传的信息
// Map setting = await NativeUtil.getSetting();
//
// if (Platform.isIOS) {
// IosDeviceInfo iosInfo = await DeviceInfoPlugin().iosInfo;
// // 设备
// params["platform"] = "ios";
// // 设备系统版本
// params["system_version"] = iosInfo?.systemVersion;
// // 设备型号 如:iPhone 11pro
// params['device_model'] = iosInfo?.name;
// // 设备型号,如:MLMF2LL/A
// // params['device_number'] = iosInfo?.model;
// // 设备ID
// params['device_id'] = iosInfo?.identifierForVendor;
// } else if (Platform.isAndroid) {
// AndroidDeviceInfo androidInfo = await DeviceInfoPlugin().androidInfo;
// // 设备
// params["platform"] = "android";
// // 设备系统版本
// params["system_version"] = "Android ${androidInfo?.version?.release}";
// // 设备型号 如:iPhone 11pro
// params['device_model'] = androidInfo?.model;
// // 设备型号,如:MLMF2LL/A
// // params['device_number'] = androidInfo?.id;
// // 设备Id
// params['device_id'] = androidInfo?.androidId;
// }
// // 应用版本号
// params["app_version_name"] = packageInfo.version;
// params["app_version"] = -1 ;// packageInfo.buildNumber;
// // 分辨率
// params["solution"] =
// "${window.physicalSize.width.floor()}*${window.physicalSize.height.floor()}";
//
// // 站长ID
// String masterId = setting['master_id'];
// if (null != masterId &&
// masterId != '' &&
// (!params.containsKey('master_id') || params['master_id'] == '')) {
// params['master_id'] = masterId;
// }
//
// // secret_key
// params['secret_key'] = setting['secret_key'];
//
// // token 读取SP缓存中的用户token
// String token = await SharedPreferencesUtil.getStringValue(
// GlobalConfig.SHARED_KEY_TOKEN);
// if (!EmptyUtil.isEmpty(token)) {
// params['token'] = token;
// }
//
// // 当前时间戳:秒
// params["time"] = TimeUtil.getNowTime();
//
// // 过滤空字段,过滤首尾空格
// Map<String, dynamic> filters = Map<String, dynamic>();
// params.forEach((key, value) {
// if (key != '' && value != '') {
// filters[key] = (value is String) ? value.trim() : value;
// }
// });
// params = filters;
//
// List<String> list = List<String>();
// params.forEach((key, value) {
// list.add(key.toString() + value.toString());
// });
// params["sign"] = signWithArray(list);
// return params;
// }

/// 获取必须的请求参数(用于请求头部)
static Future<Map<String, String>> _getMustHeadParams() async {
Map<String, String> params = new HashMap<String, String>();
// 应用信息
PackageInfo packageInfo = await PackageInfo.fromPlatform();
// 原生传的信息
@@ -202,56 +264,47 @@ class NetUtil {
// 设备
params["platform"] = "ios";
// 设备系统版本
params["system_version"] = iosInfo?.systemVersion;
params["os_version"] = iosInfo?.systemVersion?.toString();
// 设备型号 如:iPhone 11pro
params['device_model'] = iosInfo?.name;
// 设备型号,如:MLMF2LL/A
// params['device_number'] = iosInfo?.model;
params['device_model'] = iosInfo?.name?.toString();
// 设备ID
params['device_id'] = iosInfo?.identifierForVendor;
params['device_id'] = iosInfo?.identifierForVendor?.toString();
} else if (Platform.isAndroid) {
AndroidDeviceInfo androidInfo = await DeviceInfoPlugin().androidInfo;
// 设备
params["platform"] = "android";
// 设备系统版本
params["system_version"] = "Android ${androidInfo?.version?.release}";
params["os_version"] = "Android ${androidInfo?.version?.release}";
// 设备型号 如:iPhone 11pro
params['device_model'] = androidInfo?.model;
// 设备型号,如:MLMF2LL/A
// params['device_number'] = androidInfo?.id;
params['device_model'] = androidInfo?.model?.toString();
// 设备Id
params['device_id'] = androidInfo?.androidId;
params['device_id'] = androidInfo?.androidId?.toString();
}
// 应用版本号
params["app_version_name"] = packageInfo.version;
params["app_version"] = packageInfo.buildNumber;
params["app_version_name"] = packageInfo.version?.toString();
params["app_version"] = packageInfo.buildNumber?.toString();
// 分辨率
params["solution"] =
"${window.physicalSize.width.floor()}*${window.physicalSize.height.floor()}";
params["solution"] = "${window.physicalSize.width.floor()}*${window.physicalSize.height.floor()}";

// 站长ID
String masterId = setting['master_id'];
if (null != masterId &&
masterId != '' &&
(!params.containsKey('master_id') || params['master_id'] == '')) {
params['master_id'] = masterId;
if (null != masterId && masterId != '' && (!params.containsKey('master_id') || params['master_id'] == '')) {
params['master_id'] = masterId ?? 'template_database';
}

// secret_key
params['secret_key'] = setting['secret_key'];

// token 读取SP缓存中的用户token
String token = await SharedPreferencesUtil.getStringValue(
GlobalConfig.SHARED_KEY_TOKEN);
String token = await SharedPreferencesUtil.getStringValue(GlobalConfig.SHARED_KEY_TOKEN);
if (!EmptyUtil.isEmpty(token)) {
params['token'] = token;
}
// secret_key
params['secret_key'] = setting['secret_key'] ?? '';

// 当前时间戳:秒
params["time"] = TimeUtil.getNowTime();

// 过滤空字段,过滤首尾空格
Map<String, dynamic> filters = Map<String, dynamic>();
Map<String, String> filters = Map<String, String>();
params.forEach((key, value) {
if (key != '' && value != '') {
filters[key] = (value is String) ? value.trim() : value;
@@ -261,25 +314,23 @@ class NetUtil {

List<String> list = List<String>();
params.forEach((key, value) {
list.add(key.toString() + value.toString());
list.add(key.toString() + '=' + value.toString() + '&');
});

params["sign"] = signWithArray(list);
params.remove('secret_key');
return params;
}

/// 获取请求缓存成功的数据
static Future<void> _onCallBackCacheData(
OnCache onCache, String cacheKey) async {
static Future<void> _onCallBackCacheData(OnCache onCache, String cacheKey) async {
// 读取缓存
Map<String, dynamic> cacheMap =
await SharedPreferencesUtil.getNetCacheResult(cacheKey);
Map<String, dynamic> cacheMap = await SharedPreferencesUtil.getNetCacheResult(cacheKey);

if (!EmptyUtil.isEmpty(cacheMap) &&
cacheMap.containsKey(GlobalConfig.HTTP_RESPONSE_KEY_CODE) &&
(cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_CODE] ==
GlobalConfig.RESPONSE_SUCCESS_CODE ||
cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_CODE] ==
'${GlobalConfig.RESPONSE_SUCCESS_CODE}') &&
(cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == GlobalConfig.RESPONSE_SUCCESS_CODE ||
cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == '${GlobalConfig.RESPONSE_SUCCESS_CODE}') &&
!EmptyUtil.isEmpty(cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) {
onCache(cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA]);
return;
@@ -293,17 +344,12 @@ class NetUtil {
}

/// 根据请求参数,获取缓存的数据
static Future<dynamic> getRequestCachedData(String url,
{Map<String, dynamic> params}) async {
Map<String, dynamic> cacheMap =
await SharedPreferencesUtil.getNetCacheResult(
getRequestParamsCachedKey(params, url));
static Future<dynamic> getRequestCachedData(String url, {Map<String, dynamic> params}) async {
Map<String, dynamic> cacheMap = await SharedPreferencesUtil.getNetCacheResult(getRequestParamsCachedKey(params, url));
if (!EmptyUtil.isEmpty(cacheMap) &&
cacheMap.containsKey(GlobalConfig.HTTP_RESPONSE_KEY_CODE) &&
(cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_CODE] ==
GlobalConfig.RESPONSE_SUCCESS_CODE ||
cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_CODE] ==
'${GlobalConfig.RESPONSE_SUCCESS_CODE}') &&
(cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == GlobalConfig.RESPONSE_SUCCESS_CODE ||
cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == '${GlobalConfig.RESPONSE_SUCCESS_CODE}') &&
!EmptyUtil.isEmpty(cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) {
return cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA];
}
@@ -314,10 +360,8 @@ class NetUtil {
static bool isSuccess(Map<String, dynamic> data) {
try {
if (!EmptyUtil.isEmpty(data) &&
(data[GlobalConfig.HTTP_RESPONSE_KEY_CODE] ==
GlobalConfig.RESPONSE_SUCCESS_CODE ||
data[GlobalConfig.HTTP_RESPONSE_KEY_CODE] ==
'${GlobalConfig.RESPONSE_SUCCESS_CODE}')) {
(data[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == GlobalConfig.RESPONSE_SUCCESS_CODE ||
data[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == '${GlobalConfig.RESPONSE_SUCCESS_CODE}')) {
return true;
}
} catch (e) {
@@ -327,8 +371,7 @@ class NetUtil {
}

/// 根据请求参数,获取缓存的Key
static String getRequestParamsCachedKey(
Map<String, dynamic> map, String path) {
static String getRequestParamsCachedKey(Map<String, dynamic> map, String path) {
if (EmptyUtil.isEmpty(map)) {
return EncodeUtil.generateMd5(path);
}
@@ -336,11 +379,7 @@ class NetUtil {
}

// 七牛云文件上传
static Future uploadFile(String url, File file,
{String method = 'POST',
Map<String, dynamic> params,
OnSuccess onSuccess,
OnError onError}) async {
static Future uploadFile(String url, File file, {String method = 'POST', Map<String, dynamic> params, OnSuccess onSuccess, OnError onError}) async {
if (params == null) {
params = {};
}
@@ -362,11 +401,10 @@ class NetUtil {
// 字母升序
params.sort();
String result = "";
// result += secret_key;
params.forEach((param) {
result += param;
});
// result += secret_key;
result = result.substring(0, result.length - 1);
return EncodeUtil.generateMd5(result);
}

@@ -405,8 +443,7 @@ class _NetInterceptors extends InterceptorsWrapper {

@override
Future onResponse(Response response) {
Logger.endNet(response?.request?.uri?.toString(),
data: response?.data?.toString() ?? '');
Logger.endNet(response?.request?.uri?.toString(), data: response?.data?.toString() ?? '');
// TODO 解密?
return super.onResponse(response);
}


+ 34
- 19
lib/util/taobao/taobao_auth.dart 查看文件

@@ -10,13 +10,14 @@ import 'package:zhiying_comm/zhiying_comm.dart';
import 'package:provider/provider.dart';

class TaobaoAuth {
static ProfileModel _profile;
// static ProfileModel _profile;

// 淘宝授权
static auth(BuildContext context) async {
bool isAuth = await TaobaoAuth.isAuth();
if (isAuth) {
Fluttertoast.showToast(msg: '你已经授权过了');
Provider.of<UserInfoNotifier>(context, listen: false).updateUserAuth(true);
return;
}

@@ -26,8 +27,7 @@ class TaobaoAuth {
return TaobaoAuthAlert();
});
if (isConfirm != null && isConfirm == true) {
Map<String, dynamic> data = Map<String, dynamic>.from(
await NetUtil.post('/api/v1/taobao/auth', method: NetMethod.GET));
Map<String, dynamic> data = Map<String, dynamic>.from(await NetUtil.post('/api/v1/taobao/auth', method: NetMethod.GET));
Logger.debug(data);
if (data['code'] != 1) {
return;
@@ -36,20 +36,15 @@ class TaobaoAuth {
print("授权链接" + url);
TradeResult result;
if (Platform.isAndroid) {
result = await FlutterAlibc.openByUrl(
url: url, backUrl: "alisdk://", isAuth: true);
// TradeResult result = await FlutterAlibc.openByUrl(url: '');
Logger.debug('${result.errorCode} ${result.errorMessage} ');
result = await FlutterAlibc.openByUrl(url: url, backUrl: "alisdk://", isAuth: true);
} else if (Platform.isIOS) {
result = await FlutterAlibc.openByUrl(url: url);
// TradeResult result = await FlutterAlibc.openByUrl(url: '');
Logger.debug('${result.errorCode} ${result.errorMessage} ');
}
if(null !=result && result.errorCode == '0'){
Provider.of<UserInfoNotifier>(context).updateUserAuth(true);
}
Logger.log('${result.errorCode} ${result.errorMessage} ');
// if(null != result && result.errorCode == '0'){
// Provider.of<UserInfoNotifier>(context, listen: false).updateUserAuth(true);
// }
await initAuth(context);
}
}

@@ -58,12 +53,32 @@ class TaobaoAuth {
// if (_profile != null) {
// return _profile.isAuth;
// }
Map<String, dynamic> data = Map<String, dynamic>.from(
await NetUtil.post('/api/v1/user/profile', method: NetMethod.GET));
if (data['code'] == 1) {
_profile = ProfileModel.fromJson(Map<String, dynamic>.from(data['data']));
return _profile.isAuth;
try {
Map<String, dynamic> data = Map<String, dynamic>.from(await NetUtil.post('/api/v1/user/profile', method: NetMethod.GET));
if (data['code'] == 1) {
ProfileModel _profile = ProfileModel.fromJson(Map<String, dynamic>.from(data['data']));
return _profile.isAuth;
}
}catch(e, s){
Logger.error(e, s);
}
return false;
}

// 返回是否授权
static void initAuth(BuildContext context) async {
try {
Map<String, dynamic> data = Map<String, dynamic>.from(await NetUtil.post('/api/v1/user/profile', method: NetMethod.GET));
if (data['code'] == 1) {
ProfileModel model = ProfileModel.fromJson(Map<String, dynamic>.from(data['data']));
if(null != model && model.isAuth){
Provider.of<UserInfoNotifier>(context, listen: false).updateUserAuth(true);
}
}
}catch(e, s){
Logger.error(e, s);
}

}

}

+ 26
- 0
lib/util/update/app_update_model.dart 查看文件

@@ -1,11 +1,32 @@
class AppUpdateModel {
/// Android的第三方URL更新链接 例如:应用宝
String appDownloadThirdpartyUrl;

/// 更新的下载链接(Android为应用内的下载链接,IOS为商店链接)
String appDownloadUrl;

/// 新版本号码
String appVersion;

/// 新版本昵称
String appVersionName;

/// 更新内容
String content;

/// 是否显示提示更新弹窗
String dialog;

/// 是否强制更新
String isForce;

/// 是否可以忽略此版本
String isIgnore;

/// 是否优先使用第三方更新
String isThirdparty;

/// 提示
String tip;

AppUpdateModel({
@@ -17,6 +38,7 @@ class AppUpdateModel {
this.isForce,
this.isThirdparty,
this.tip,
this.content,
});

AppUpdateModel.fromJson(Map<String, dynamic> json) {
@@ -26,8 +48,10 @@ class AppUpdateModel {
appVersionName = json['app_version_name'];
dialog = json['dialog'];
isForce = json['is_force'];
isIgnore = json['is_ignore'];
isThirdparty = json['is_thirdparty'];
tip = json['tip'];
content = json['content'];
}

Map<String, dynamic> toJson() {
@@ -38,8 +62,10 @@ class AppUpdateModel {
data['app_version_name'] = this.appVersionName;
data['dialog'] = this.dialog;
data['is_force'] = this.isForce;
data['is_ignore'] = this.isIgnore;
data['is_thirdparty'] = this.isThirdparty;
data['tip'] = this.tip;
data['content'] = this.content;
return data;
}
}

+ 137
- 102
lib/util/update/app_update_util.dart 查看文件

@@ -3,8 +3,10 @@ import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_update_dialog/flutter_update_dialog.dart';
// import 'package:flutter_xupdate/flutter_xupdate.dart';
import 'package:flutter_xupdate/flutter_xupdate.dart';
import 'package:package_info/package_info.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:zhiying_comm/util/shared_prefe_util.dart';
import 'package:zhiying_comm/util/update/app_update_model.dart';
import 'package:zhiying_comm/zhiying_comm.dart';
import 'package:fluttertoast/fluttertoast.dart';
@@ -15,48 +17,49 @@ import '../log/let_log.dart';
/// App更新工具类
///
class AppUpdateUtil {
static final String _IGNORE_VERSION = "xupdate_ignore_version";

///
/// 初始化更新插件
///
static void initXUpdate() {
if (Platform.isAndroid) {
// FlutterXUpdate.init(
//
// ///是否输出日志
// debug: true,
//
// ///是否使用post请求
// isPost: false,
//
// ///post请求是否是上传json
// isPostJson: false,
//
// ///是否开启自动模式
// isWifiOnly: false,
//
// ///是否开启自动模式
// isAutoMode: false,
//
// ///需要设置的公共参数
// supportSilentInstall: false,
//
// ///在下载过程中,如果点击了取消的话,是否弹出切换下载方式的重试提示弹窗
// enableRetry: false)
// .then((value) {
// // updateMessage("初始化成功: $value");
// Logger.log('初始化成功: $value');
// }).catchError((error) {
// print(error);
// });
// FlutterXUpdate.setErrorHandler(onUpdateError: (Map<String, dynamic> message) async {
// Logger.warn(message);
// // setState(() {
// // _message = "$message";
// // });
// });
FlutterXUpdate.init(
///是否输出日志
debug: true,
///是否使用post请求
isPost: false,
///post请求是否是上传json
isPostJson: false,
///是否开启自动模式
isWifiOnly: false,
///是否开启自动模式
isAutoMode: false,
///需要设置的公共参数
supportSilentInstall: false,
///在下载过程中,如果点击了取消的话,是否弹出切换下载方式的重试提示弹窗
enableRetry: false)
.then((value) {
Logger.log('初始化成功: $value');
}).catchError((error) {
print(error);
});
FlutterXUpdate.setErrorHandler(onUpdateError: (Map<String, dynamic> message) async {
Logger.warn(message);
});
FlutterXUpdate.setErrorHandler(onUpdateError: (Map<String, dynamic> message) async {
Logger.warn(message);
});
} else {
// updateMessage("ios暂不支持XUpdate更新");
Logger.log('ios暂不支持XUpdate更新');
}
}
@@ -64,74 +67,89 @@ class AppUpdateUtil {
///
/// 检查并且更新app
///
static void updateApp(BuildContext context) async {
PackageInfo packageInfo = await PackageInfo.fromPlatform();
Logger.log('version = ${packageInfo.version}, buildNum = ${packageInfo.buildNumber}');
var result = await NetUtil.post('/api/v1/appcheck', params: {'app_version': packageInfo.buildNumber}, method: NetMethod.GET);
customStyle(context, onUpdate: (){
Navigator.pop(context);
});
// UpdateEntity updateEntity = await _checkAppUpdate();
// // 有新版本,进行更新
// if (!EmptyUtil.isEmpty(updateEntity) && updateEntity.hasUpdate) {
// if (Platform.isAndroid) {
// FlutterXUpdate.updateByInfo(
// updateEntity: updateEntity,
// supportBackgroundUpdate: true,
// );
// } else if (Platform.isIOS) {
// // TODO 完成IOS更新
// String updateUrl = updateEntity.downloadUrl;
// customStyle(context, onUpdate: (){
//
//
//
// Navigator.pop(context);
// });
// }
// } else {
// Fluttertoast.showToast(msg: '已经是最新版本了~');
// }
/// @context 上下文
/// @needToast 是否需要提示最新版本
/// @mustShowDialog 是否必须弹窗(检查更新页面要弹窗)
///
static void updateApp(BuildContext context, {bool needToast = false, bool mustShowDialog = false}) async {
UpdateEntity updateEntity = await _checkAppUpdate();
// 有新版本,进行更新
if (!EmptyUtil.isEmpty(updateEntity) && updateEntity.hasUpdate) {
if (Platform.isAndroid) {
FlutterXUpdate.updateByInfo(
updateEntity: updateEntity,
supportBackgroundUpdate: true,
enableIgnore: mustShowDialog || updateEntity.isForce,
retryContent: '更新下载速度太慢了,是否考虑切换下载方式?',
enableRetry: updateEntity.thirdParty,
overrideGlobalRetryStrategy: true,
retryUrl: updateEntity.thirdUrl,
);
} else if (Platform.isIOS) {
bool ignore = await isIgnoreVersion(updateEntity?.versionCode?.toString());
if ((!ignore || mustShowDialog) || updateEntity.isForce || !updateEntity.isIgnorable) {
String updateUrl = updateEntity.downloadUrl;
customStyle(context, updateEntity, onUpdate: () {
// 打开第三方sdk
launch(updateUrl, forceSafariVC: true, enableJavaScript: true, forceWebView: true);
Navigator.pop(context);
});
}
}
} else {
if (needToast) Fluttertoast.showToast(msg: '已经是最新版本了~');
}
}

/// 检查是否有新版本
// static Future<UpdateEntity> _checkAppUpdate() async {
// try {
// PackageInfo packageInfo = await PackageInfo.fromPlatform();
// // var result = await NetUtil.post('/api/v1/appcheck', params: {'app_version': packageInfo.version}, method: NetMethod.GET);
//
// var result = {
// 'dialog': '1',
// 'is_force': '0',
// 'app_version': '5',
// 'app_version_name': '5.0.0',
// 'tip': '\n1、优化api接口。\n2、添加使用demo演示。\n3、新增自定义更新服务API接口。\n4、优化更新提示界面。',
// 'app_download_url': 'http://imtt.dd.qq.com/16891/apk/FAD58DEFE56A938D86B123DEA4E298EB.apk?fsname=com.hairuyi.www_5.8.8_469.apk&hsr=4d5s',
// };
// AppUpdateModel model = AppUpdateModel.fromJson(result);
// if (!EmptyUtil.isEmpty(model)) {
// // ⚠️ isIgnorable 目前只有两种状态,为强制更新和不强制更新(每次进来都会提示更新UI弹窗)
// return UpdateEntity(
// hasUpdate: model?.dialog == '1',
// isIgnorable: false,
// isForce: model?.isForce == '1',
// versionCode: int.parse(model?.appVersion ?? '1'),
// versionName: model?.appVersionName,
// downloadUrl: model?.appDownLoadUrl,
// updateContent: model?.tip,
// );
// }
// } catch (e, s) {
// Logger.error(e, s);
// }
// return null;
// }

static void customStyle(BuildContext context, {@required VoidCallback onUpdate }) {
static Future<UpdateEntity> _checkAppUpdate() async {
try {

// var result = {
// "code": 1,
// "data": {
// "app_download_thirdparty_url": "https://android.myapp.com/myapp/detail.htm?apkName=com.hairuyi.www&ADTAG=mobile",
// "app_download_url": "http://fir.osant.cn/zhiyi",
// "app_version": "1",
// "app_version_name": "1.0.0",
// "content": "更新接口\n完善app页面\n更新站长后台",
// "dialog": "1",
// "is_force": "0",
// "is_ignore": "0",
// "is_thirdparty": "1",
// "tip": "有新版下载"
// },
// "msg": "ok"
// };
PackageInfo packageInfo = await PackageInfo.fromPlatform();
var result = await NetUtil.post('/api/v1/appcheck', method: NetMethod.GET);
AppUpdateModel model = AppUpdateModel.fromJson(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]);
if (!EmptyUtil.isEmpty(model)) {
return UpdateEntity(
hasUpdate: model?.dialog == '1' || model?.isForce == '1',
isIgnorable: model?.isIgnore == '1' && model?.isForce != '1',
isForce: model?.isForce == '1',
versionCode: int.parse(model?.appVersion ?? '1'),
versionName: model?.appVersionName,
downloadUrl: model?.appDownloadUrl,
updateContent: model?.content,
tip: model?.tip,
thirdUrl: model?.appDownloadThirdpartyUrl,
thirdParty: model?.isThirdparty == '1',
);
}
} catch (e, s) {
Logger.error(e, s);
}
return null;
}

// IOS 样式
static void customStyle(BuildContext context, UpdateEntity updateEntity, {@required VoidCallback onUpdate}) {
UpdateDialog.showUpdate(context,
width: 250,
title: "是否升级到4.1.4版本?",
updateContent: "新版本大小:2.0M\n1.xxxxxxx\n2.xxxxxxx\n3.xxxxxxx",
title: "是否升级到${updateEntity?.versionName ?? '1.0.0'}版本?",
updateContent: updateEntity?.updateContent ?? '',
titleTextSize: 14,
contentTextSize: 12,
buttonTextSize: 12,
@@ -140,11 +158,28 @@ class AppUpdateUtil {
radius: 8,
themeColor: Colors.redAccent,
progressBackgroundColor: Color(0x5AFFAC5D),
isForce: false,
isForce: updateEntity?.isForce ?? false,
updateButtonText: '升级',
ignoreButtonText: '忽略此版本',
enableIgnore: true, onIgnore: () {
enableIgnore: updateEntity?.isIgnorable ?? false, onIgnore: () {
saveIgnoreVersion(updateEntity?.versionCode?.toString());
Navigator.pop(context);
}, onUpdate: onUpdate);
}

// 保存忽略的版本号码
static void saveIgnoreVersion(String newVersion) async {
if (!EmptyUtil.isEmpty(newVersion)) {
await SharedPreferencesUtil.setStringValue(_IGNORE_VERSION, newVersion);
}
}

// 是否是忽略版本
static Future<bool> isIgnoreVersion(String newVersion) async {
String oldVersion = await SharedPreferencesUtil.getStringValue(_IGNORE_VERSION);
if (!EmptyUtil.isEmpty(oldVersion) && !EmptyUtil.isEmpty(newVersion)) {
return oldVersion == newVersion;
}
return false;
}
}

+ 4
- 1
pubspec.yaml 查看文件

@@ -33,7 +33,10 @@ dependencies:
# 京东sdk
jdsdk: ^0.0.1
# Android app更新
# flutter_xupdate: ^1.0.0
flutter_xupdate:
git:
ref: 1.0.1
url: http://192.168.0.138:3000/FnuoOS_ZhiYing/flutter_xupdate.git
# app更新dialogUI(用于IOS,以便统一样式)
flutter_update_dialog: 1.0.0
flutter_alibc:


Loading…
取消
儲存