flutter 配置安卓的签名

背景

最近遇到一个需求,需要实现app的热更新,了解了一下热更新方案时间的时间有点久,就做了个app升级的过渡版本,然后遇到问题 真机安装遇到签名不一致的问题

如下

安装过程

版本升级的代码如下

 ///版本更新检查static Future<VersionEntity> checkVersionUpdate() async {if (isWeb) {return VersionEntity(need: false);}PackageInfo packageInfo = await PackageInfo.fromPlatform();String version = packageInfo.version;// String jsonStr = await rootBundle.loadString('assets/json/version.json');// Map<String, dynamic> jsonData = json.decode(jsonStr);Map<String, dynamic> jsonData = await getVersion();VersionEntity versionEntity = VersionEntity.fromJson(jsonData);Version latestVersion = Version.parse(versionEntity.version ?? version);Version currentVersion = Version.parse(version);print(1);if (latestVersion > currentVersion) {_toUpdate(versionEntity);} else {return VersionEntity(need: false);}/// 非强制更新// if (versionEntity.data!.need! && !(versionEntity.data!.necessary!)) {//   _toUpdate(versionEntity);// } // 强制更新// else if (versionEntity.data!.need! && versionEntity.data!.necessary!) {//   _toUpdate(versionEntity);// } else {//   // KLogUtil.d('无需更新');// }return versionEntity;}///版本更新弹窗static _toUpdate(VersionEntity versionEntity) {// 进度String progress = '';double downloadProgress = 0.0;bool downloadStart = false;// 禁止返回bool disBack = versionEntity.necessary!;Get.bottomSheet(isDismissible: !(versionEntity.necessary!),enableDrag: !(versionEntity.necessary!),StatefulBuilder(builder: (context, state) {String fileAddress = '';return WillPopScope(onWillPop: () => _onBackPressed(disBack),child: AppToast.bottomSheetContainer(padding: EdgeInsets.fromLTRB(20.w, 5.h, 20.w, 20.h),height: 429.h,bgColor: const Color(0xFF25272B),child: Column(children: [Container(width: 36.w,height: 4.h,decoration: BoxDecoration(color: versionEntity.necessary!? Colors.transparent: const Color(0xFF3B3D40),borderRadius: BorderRadius.circular(3.r),),),10.verticalSpace,Assets.images.versionUpdate.image(width: 100.r, height: 100.r),Padding(padding: EdgeInsets.symmetric(vertical: 20.h),child: Text("Update to ${versionEntity.version}",style: TextStyle(color: Colors.white,fontSize: 16.sp,),),),Padding(padding: EdgeInsets.symmetric(vertical: 5.h),child: Row(children: [Text("更新内容:",style: TextStyle(color: Colors.white,fontSize: 14.sp,),),],),),Expanded(child: ListView.builder(itemCount: versionEntity.contents?.length ?? 0,itemBuilder: (context, index) {return Text(versionEntity!.contents![index],style: TextStyle(color: Colors.grey,fontSize: 13.sp,),);},),),Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,children: [versionEntity.necessary == false && disBack == false? Expanded(child: SizedBox(height: 56.h,child: ElevatedButton(onPressed: () {/// 每天弹一次更新Get.back();},style: ButtonStyle(backgroundColor: MaterialStateProperty.all(const Color(0xFF25272B)),shape: MaterialStateProperty.all(RoundedRectangleBorder(borderRadius:BorderRadius.circular(16.r),),),),child: Text("Not Now ",style: TextStyle(color: const Color(0xFF25272B),fontSize: 14.sp,fontWeight: FontWeight.bold,),),),),): Container(),versionEntity.necessary == false && disBack == false? SizedBox(width: 15.w): Container(),Visibility(visible: progress == '',child: Expanded(child: SizedBox(height: 56.h,child: ElevatedButton(onPressed: () async {if (Platform.isIOS) {InstallPlugin.install(iosAppStoreUrl);// AppInstaller.goStore(//     iosAppStoreUrl, "id1375433239",//     review: true);return;}if (progress == '') {state(() {downloadStart = true;});disBack = true; //开始下载后禁止退出弹窗final filePath =await getExternalStorageDirectory();fileAddress = '${filePath!.path}/app-LH.apk';try {Dio dio = Dio(BaseOptions(connectTimeout:const Duration(milliseconds: 10000),receiveTimeout: const Duration(milliseconds: 100000),sendTimeout:const Duration(milliseconds: 10000),),);await dio.download(versionEntity.url!,fileAddress,onReceiveProgress: (received, total) {if (total != -1) {state(() {progress ="${(received / total * 100).toStringAsFixed(2)}%";downloadProgress = received / total;});}},).then((response) async {if (response.statusMessage == 'OK') {// AppInstaller.installApk(fileAddress);InstallPlugin.install(fileAddress);// await AppInstaller.installApk(//     fileAddress);} else {AppToast.toast(stateType: StateType.error,tips: "Failed to download");disBack = false;}},);} catch (e) {print(e);}}},style: ButtonStyle(backgroundColor: MaterialStateProperty.all(const Color(0xFF4677FF)),shape: MaterialStateProperty.all(RoundedRectangleBorder(borderRadius:BorderRadius.circular(16.r)),),),child: downloadStart? CircularProgressIndicator(valueColor: const AlwaysStoppedAnimation(Colors.white),backgroundColor:Colors.white.withOpacity(.1),): Text("Update",style: TextStyle(fontSize: 14.sp,fontWeight: FontWeight.bold,color: Colors.white,)),),),),),Visibility(visible: progress != '',child: Expanded(child: Container(decoration: BoxDecoration(color: Colors.white.withOpacity(.1),borderRadius: BorderRadius.circular(16.r),),clipBehavior: Clip.hardEdge,child: Stack(alignment: AlignmentDirectional.center,children: [InkWell(child: SizedBox(height: 56.h,width: double.infinity,child: LinearProgressIndicator(value: downloadProgress,backgroundColor: Colors.transparent,valueColor: const AlwaysStoppedAnimation(Color(0xFF4677FF)),),),onTap: () async {if (progress == "100.00%") {await InstallPlugin.install(fileAddress);}},),Text(progress == ''? "Update": (progress == "100.00%"? "安装app": progress),style: TextStyle(fontSize: 14.sp,fontWeight: FontWeight.bold,))],),),),),],),],),),);},),);}static Future<bool> _onBackPressed(bool necessary) async {// 强更 禁止退出弹窗if (necessary) {return false;} else {return true;}}class VersionEntity {bool? necessary;bool? need;String? version;String? url;List<String>? contents;VersionEntity({this.necessary, this.need, this.version, this.url});VersionEntity.fromJson(Map<String, dynamic> json) {necessary = json['necessary'];need = json['need'];version = json['version'];url = json['url'];contents = json['contents'].cast<String>();}Map<String, dynamic> toJson() {final Map<String, dynamic> data = <String, dynamic>{};data['necessary'] = necessary;data['need'] = need;data['version'] = version;data['url'] = url;data['contents'] = contents;return data;}
}

下面是解决签名不一致的问题 解决方案

keytool -genkey -v -keystore ./key.jks -keyalg RSA -keysize 2048 -validity 20000 -alias HL

很多会遇到  原因是keytool 是java的库  需要配置java环境  或者 在java目录下进行操作

bash: keytool: command not found

在java环境目录 打开cmd 执行后 复制key.jks 到你的安卓目录下 (android/) 

在安卓目录下(android/) 新增key.properties 文件

写入 密码是你自己设置的密码

storePassword=789asd
keyPassword=789asd
keyAlias=LH
storeFile=../key.jks

最后在你 (android/app) 下的build.gradle 配置 buildTypes

// 最上面
def keystorePropertiesFile = rootProject.file("key.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))//签名信息signingConfigs {release {keyAlias keystoreProperties['keyAlias']keyPassword keystoreProperties['keyPassword']storeFile file(keystoreProperties['storeFile'])storePassword keystoreProperties['storePassword']}}buildTypes {release {// TODO: Add your own signing config for the release build.// Signing with the debug keys for now, so `flutter run --release` works.debuggable falseminifyEnabled true// signingConfig signingConfigs.debugsigningConfig signingConfigs.releasendk{ // 必须加入这部分,否则可能导致编译成功的release包在真机中会闪退abiFilters "armeabi-v7a"}}debug {ndk {//这里要加上,否则debug包会出问题,后面三个为可选,x86建议加上不然部分模拟器回报错abiFilters "armeabi", "armeabi-v7a", "arm64-v8a",  "x86"}}}
flutter build apk --release

这样就解决了升级遇到的签名版本不一致的问题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/610448.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

冲刺2024年AMC8竞赛:往年真题练一练和答案详解(3)

今天我们继续来做一做往年的AMC8真题&#xff0c;通过高质量的真题来体会我们所学的知识如何解题&#xff0c;建立快速思考、做对题目的策略。 今天分享的五道题目仍然是随机从六分成长独家制作的575道在线题库&#xff08;来自于往年真题&#xff09;中抽取5道题来做一下&…

Parallel patterns: convolution —— An introduction to stencil computation

在接下来的几章中&#xff0c;我们将讨论一组重要的并行计算模式。这些模式是许多并行应用中出现的广泛并行算法的基础。我们将从卷积开始&#xff0c;这是一种流行的阵列操作&#xff0c;以各种形式用于信号处理、数字记录、图像处理、视频处理和计算机视觉。在这些应用领域&a…

Linux环境变量LD_LIBRARY_PATH配置

解决snmpwalk报错 报错提示&#xff1a;./bin/snmpwalk:error while loading shared libraries:libnetsnmp.so.40:cannot open shared object file: No such file or directory. 环境变量LD_LIBRARY_PATH LD_LIBRARY_PATH是Linux环境变量名&#xff0c;该环境变量主要用于指…

基于ChatGPT4+Python近红外光谱数据分析及机器学习与深度学习建模

2022年11月30日&#xff0c;可能将成为一个改变人类历史的日子——美国人工智能开发机构OpenAI推出了聊天机器人ChatGPT3.5&#xff0c;将人工智能的发展推向了一个新的高度。2023年4月&#xff0c;更强版本的ChatGPT4.0上线&#xff0c;文本、语音、图像等多模态交互方式使其在…

Java泛型:灵活多变的类型参数化工具

&#x1f451;专栏内容&#xff1a;Java⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;前路未远&#xff0c;步履不停 目录 一、泛型1、什么是泛型2、泛型的语法 二、泛型类的使用1、泛型类的语法2、泛型如何编译的2.1、擦除机制2.2、为什么不能实例化泛…

控制el-table的列显示隐藏

控制el-table的列显示隐藏&#xff0c;一般的话可以通过循环来实现&#xff0c;但是假如业务及页面比较复杂的话&#xff0c;list数组循环并不好用。 在我们的页面中el-table-column是固定的&#xff0c;因为现在是对现有的进行维护和迭代更新。 对需要控制列显示隐藏的页面进…

Queue接口分析

一、Queue是什么 该接口是Java集合框架成员 Queue&#xff1a; 通常&#xff08;但不一定&#xff09;队列就是一个先入先出&#xff08;FIFO&#xff09;的数据结构&#xff0c;和堆一样&#xff08;但可以进行转换&#xff0c;比如优先级列队排序&#xff0c;又或者改为栈形…

私域爆款活动实操指南,让你轻松成为营销高手!

私域运营活动是公司运营中非常重要的一环&#xff0c;它能够提高用户参与度、增加用户忠诚度&#xff0c;并为公司带来更多的商业机会。然而&#xff0c;策划和执行一场成功的私域运营活动并不容易&#xff0c;需要思维缜密、部门合作以及落地能力等方面的综合素养。今天来跟大…

centos下升级git版本

1 问题描述 centos7系统默认的git安装版本是1.8&#xff0c;但是在项目构建中发现git版本过低&#xff0c;导致构建AI模型环境时出现各种错误&#xff0c;于是用源码编译的方式进行升级&#xff0c;同时该文章也适用于安装新的git。 2. 升级安装 2.1 第一步卸载原有的git r…

怎么把视频设置为电脑桌面

1、打开腾讯软件中心&#xff0c;搜索并下载【火萤视频桌面】&#xff0c;不要安装&#xff08;因为卸载会出错&#xff09;。 2、找到下载的火萤视频桌面exe程序&#xff0c;以【打开压缩包】的方式打开&#xff0c;把其中的WPengine文件夹解压到桌面。 3、双击打开WPengine…

亚信安全深度解读2023年中国网络安全重要政策法规

亚信安全在对2023年国内网络安全政策的持续跟踪和研究基础上进行了详细分析。观察整体态势&#xff0c;本年度网络安全政策的发布呈现出高密度特征&#xff0c;共计引起行业高度关注的政策达50余项。数据安全领域、个人信息保护和数据跨境安全成为关注的热点&#xff0c;分别有…

Java面试之并发篇(一)

1、前言 本篇主要总结JAVA面试中关于并发相关的高频面试题。本篇的面试题基于网络整理&#xff0c;和自己编辑。在不断的完善补充哦。 2、简述程序、进程、线程、的基本概念&#xff1f; 2.1、程序 程序&#xff0c;是含有指令和数据的文件&#xff0c;被存储在磁盘或其他的…

大数据开发个人简历范本(2024最新版-附模板)

大数据开发工程师个人简历范本> 男 22 本科 张三 计算机科学与技术 1234567890 个人概述 具备深入的Hadoop大数据运维工程师背景&#xff0c;熟悉相关技术和工具 具备良好的团队合作能力&#xff0c;善于沟通和协作 具有快速学习新知识和解决问题的能力 对于数据科学…

Java中的集合框架

概念与作用 集合概念 现实生活中&#xff1a;很多事物凑在一起 数学中的集合&#xff1a;具有共同属性的事物的总体 java中的集合类&#xff1a;是一种工具类&#xff0c;就像是容器&#xff0c;储存任意数量的具有共同属性的对象 在编程时&#xff0c;常常需要集中存放多个…

GEE计算Landsat8的NDVI

目录 前言源代码结果 前言 NDVI&#xff08;近红-红&#xff09;/&#xff08;近红红&#xff09; normalizedDifference方法是&#xff08;A-B&#xff09;/&#xff08;AB&#xff09;的计算方法 计算NDVI一般用来配合其他反演参数&#xff0c;构造指数或者数据升降尺度。 …

Java IO学习和总结(超详细)

一、理解 I/O 是输入和输出的简写&#xff0c;指的是数据在计算机内部和外部设备之间的流动。简单来说&#xff0c;当你从键盘输入数据、从鼠标选择操作&#xff0c;或者在屏幕上看到图像&#xff0c;这些都是 I/O 操作。它就像是计算机与外部世界沟通的桥梁&#xff0c;没有 I…

linux项目部署(jdk,tomcat,mysql,nginx,redis)

打开虚拟机&#xff0c;与连接工具连接好&#xff0c;创建一个文件夹 cd /tools 把jdk,tomcat安装包放入这个文件夹里面 jdk安装 #解压 tar -zxvf apache-tomcat-8.5.20.tar.gz #解压jdk tar -zxvf jdk-8u151-linux-x64.tar.gz 编辑jdk文件以及测试jdk安装 第一行代码路径…

Poi实现根据word模板导出-图表篇

往期系列传送门&#xff1a; Poi实现根据word模板导出-文本段落篇 &#xff08;需要完整代码的直接看最后位置&#xff01;&#xff01;&#xff01;&#xff09; 前言&#xff1a; 补充Word中图表的知识&#xff1a; 每个图表在word中都有一个内置的Excel&#xff0c;用于…

以unity技术开发视角对android权限的讲解

目录 前言 Android权限分类 普通权限 普通权限定义 普通权限有哪些 危险权限 危险权限的定义 危险权限有哪些 动态申请权限实例 申请单个权限实例 第一步&#xff1a;在清单文件中声明权限 第二步&#xff1a;在代码中进行动态申请权限 申请多个权限实例 第一步&am…

大众汽车宣布将ChatGPT,批量集成在多种汽车中!

1月9日&#xff0c;大众汽车在官网宣布&#xff0c;将ChatGPT批量集成到电动、内燃机汽车中。 大众表示&#xff0c;将ChatGPT与其IDA语音助手相结合&#xff0c;用户通过自然语言就能与ChatGPT进行互动&#xff0c;例如&#xff0c;帮我看看最近的三星米其林饭店在哪里&#…