[Flutter] Flutter APK构建签名并推广到Github workflow

news/2025/10/10 20:43:00/文章来源:https://www.cnblogs.com/senlinjun/p/19133828

[Flutter] Flutter APK构建签名并推广到Github workflow

Flutter APK构建签名并推广到Github workflow

最近在开发flutter软件的时候发现构建出来的apk在手机上不能直接覆盖更新,会提示签名不一致,但由于我的软件是在github上自动构建的,所以就琢磨了一下自动签名

步骤如下:

  • 使用keytool生成一个密钥库
  • 添加配置文件
  • 修改构建配置文件
  • 设置Github Secret

生成密钥库

keytool在jdk中,如果cmd里没有的话把jdk丢进环境变量里就行了

接着,在android/app下打开命令行,输入

keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key

其中,10000表示有效日期,其他参数我个人认为不需要改

运行后应该是这样的

generate_key_store

密钥库口令需要保存好,后面需要用

添加配置文件

android/app下添加新文件:key.properties

storePassword = 123456
keyPassword = 123456
keyAlias = key
storeFile = key.jks

其中的storePasswordkeyPassword均填写前面的密钥库口令

修改构建配置文件

只需要添加/修改这些地方,下图已经标好了
(下面有可复制的文本!!)

code-snapshot

// android/app/build.gradle.ktsimport java.util.Properties
import java.io.FileInputStreamplugins {id("com.android.application")id("kotlin-android")// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.id("dev.flutter.flutter-gradle-plugin")
}android {ndkVersion = "27.0.12077973"namespace = "com.test.abc"compileSdk = flutter.compileSdkVersioncompileOptions {sourceCompatibility = JavaVersion.VERSION_11targetCompatibility = JavaVersion.VERSION_11}kotlinOptions {jvmTarget = JavaVersion.VERSION_11.toString()}signingConfigs {create("release") {// 从key.properties加载签名信息val keystorePropertiesFile = rootProject.file("app/key.properties")if (keystorePropertiesFile.exists()) {val keystoreProperties = Properties().apply {load(FileInputStream(keystorePropertiesFile))}storeFile = file(keystoreProperties.getProperty("storeFile"))storePassword = keystoreProperties.getProperty("storePassword")keyAlias = keystoreProperties.getProperty("keyAlias")keyPassword = keystoreProperties.getProperty("keyPassword")enableV1Signing = trueenableV2Signing = true}}}defaultConfig {// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).applicationId = "com.test.abc"// You can update the following values to match your application needs.// For more information, see: https://flutter.dev/to/review-gradle-config.minSdk = flutter.minSdkVersiontargetSdk = flutter.targetSdkVersionversionCode = flutter.versionCodeversionName = flutter.versionName}buildTypes {release {// TODO: Add your own signing config for the release build.// Signing with the debug keys for now, so `flutter run --release` works.signingConfig = signingConfigs.getByName("release")}}
}flutter {source = "../.."
}

现在可以先试着跑一下

flutter build apk

构建成功后,直接解压apk文件,进入META-INF文件夹,在cmd中输入

keytool -printcert -file CERT.RSA

如果显示了先前设置的信息,则签名成功了

success

推广到workflow

由于密钥库和口令都不能外泄,所以不能直接上传至github(git也是默认忽略掉了这些文件),我们需要通过Github Secret来动态写入密钥库与口令

在Github仓库-Settings-Secrets and variables-actions中新建secret
secret建议KEY_PROPERTIES因为这样后面就可以直接抄作业了(
secret内容直接复制我们刚刚的key.properties文件`

接下来是密钥库文件,由于不能直接丢二进制上去,我们需要先转成base64
powershell:

[Convert]::ToBase64String([IO.File]::ReadAllBytes("key.jks")) | Out-File -FilePath "key_base64.txt" -Encoding utf8

key_base64.txt加入到secret中,名字写KEY_STORE

接下来进入workflow文件中,在build命令之前加上:

- name: Generate keyrun: echo "${{ secrets.KEY_STORE }}" | base64 --decode > android/app/key.jks  && echo "${{ secrets.KEY_PROPERTIES }}" > android/app/key.properties

温馨提示:路径不要写错了,根据自己仓库的实际结构写
大功告成!可以跑一遍workflow再用上文提到的方法检验一遍

额外:根据参数选择是否签名

import java.util.Properties
import java.io.FileInputStreamplugins {id("com.android.application")id("kotlin-android")id("dev.flutter.flutter-gradle-plugin")
}android {ndkVersion = "27.0.12077973"namespace = "com.test.abc"compileSdk = flutter.compileSdkVersioncompileOptions {sourceCompatibility = JavaVersion.VERSION_11targetCompatibility = JavaVersion.VERSION_11}kotlinOptions {jvmTarget = JavaVersion.VERSION_11.toString()}// 配置release签名信息(仅在指定参数时使用)signingConfigs {create("release") {// 从key.properties加载签名信息val keystorePropertiesFile = rootProject.file("app/key.properties")if (keystorePropertiesFile.exists()) {val keystoreProperties = Properties().apply {load(FileInputStream(keystorePropertiesFile))}storeFile = file(keystoreProperties.getProperty("storeFile"))storePassword = keystoreProperties.getProperty("storePassword")keyAlias = keystoreProperties.getProperty("keyAlias")keyPassword = keystoreProperties.getProperty("keyPassword")enableV1Signing = trueenableV2Signing = true}}}defaultConfig {applicationId = "com.test.abc"minSdk = flutter.minSdkVersiontargetSdk = flutter.targetSdkVersionversionCode = flutter.versionCodeversionName = flutter.versionName}buildTypes {release {// 判断是否有签名参数,决定使用哪种签名// 命令行传递 -PuseReleaseSigning=true 时使用release签名val useReleaseSigning = project.hasProperty("useReleaseSigning") && project.property("useReleaseSigning") == "true"// 默认使用debug签名,指定参数时使用release签名signingConfig = if (useReleaseSigning) {signingConfigs.getByName("release")} else {signingConfigs.getByName("debug") // 使用默认的debug签名}proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"),"proguard-rules.pro")}}
}flutter {source = "../.."
}

这时,如果直接执行

flutter build apk

则不会签名,需要加上参数

flutter build apk -PuseReleaseSigning=true

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

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

相关文章

Windows 电脑安装 XTerminal 1.25.1 x64 版(带安装包下载关键词)​

Windows 电脑安装 XTerminal 1.25.1 x64 版(带安装包下载关键词)​​XTerminal​ 是一款运行在 Windows 系统上的终端工具(类似命令行窗口),通常用于开发者、运维人员或高级用户来执行命令、连接远程服务器、运行…

YOLOv11的神经辐射场(NeRF)辅助训练-(通过合成视角增强内容多样性)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

题解:AT_arc138_f [ARC138F] KD Tree

题意:平面上有 \(n\) 个点 \((i,p_i)\),\(p\) 是一个排列。每次操作可以选择 \(x/y\) 和一个坐标,将点列分成左右/上下两边(保持两边的相对顺序不变),分别递归下去,直到只剩下一个点,把它加入答案序列末尾。求…

SP33 TRIP - Trip 个人题解

题目链接 题目大意: 给出两个字符串,要求求出所有 LCS (最长公共子序列问题)的具体方案,并按字典序输出 解题方法: 首先我们要清楚求 LCS 的长度的方法,按照闫氏DP分析法我们得到一下过程:但是我们如果直接在此…

经营不是老板一个人的事 - 智慧园区

很多企业都陷入了“高层定目标,中层传口号,基层盲执行”的怪圈。一提到“经营”,大家就会想到董事长、总经理,觉得那是高层的事。但真相是:如果经营思维只停留在高层,企业正在走向危险边缘。一、经营到底是什么?…

Codeforces Round 1051 (Div. 2)[A ~E]

―僕は其れに縋る事さえ/出来無かった訳ですから目录Codeforces Round 1051 (Div. 2)A. All Lengths SubtractionB. DiscountsC. Max TreeD. Inversion Graph Coloring Easy Version/Hard VersionE. Make Good Codefo…

如何在 Spring Boot 应用中配置多个 Spring AI 的 LLM 客户端

1. 概述 越来越多的现代应用开始集成大型语言模型(LLM),以构建更智能的功能。如何使用Spring AI快速整合LLM能力到自己的Spring Boot应用,在之前的博文中有过很多篇关于使用Spring AI使用不同供应商LLM的整合案例。…

【Azure APIM】解答REST API实现禁用自签名证书的证书链验证中的backends参数值从那里取值的问题?

问题描述 使用APIM服务时候,因为后端的API需要使用自签名证书进行验证。如果通过浏览器直接访问后端API返回正常,但是APIM请求的时候返回为500报错。 在开启Trace后,发现报错信息为:error message :The underlyin…

2025 AI 进化图谱:技术突破、场景落地与产业重构 - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

题解:P14065 [PO Final 2022] 对弈 / Laserschack

题目传送门 先警示后人: 我在看题目的时候看成了 \(1 \le r,c \le 4000\) 然后被迫想了一个 \(\operatorname{O}(\operatorname{RC} \ \operatorname{log} \ \operatorname{RC})\) 发现好像有点玄 最后乱加一堆优化跑…

[Git] 放弃暂存区的修改

1 需求描述在使用 Git 进行版本控制时,有时我们会在暂存区(staging area)中暂存了一些修改,但后来发现这些修改是不需要的,想要放弃这些修改并恢复到上一次提交的状态。Git 提供了几种方法来实现这一操作。2 解决…

前端里面transform和transition 属性的区别

transform 和 transition 都是用于在 HTML 中控制元素的视觉效果和动画的 CSS 属性,但它们的作用和功能不同。下面详细解释这两个属性的区别: 1. transform 属性 transform 属性允许你对元素进行 2D 或 3D 转换(即对…

【MAC环境】安装多个 JDK - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

CF2064E Mycraft Sand Sort

Sol 首先 \(c\) 不能变,否则第一列就会改变。 然后注意到 \(i,j(i<j)\) 能交换当且仅当满足以下任意一条:\(\displaystyle\max_{k=i+1}^{j-1}a_k<\min(a_i,a_j)\) i+1=j那么考虑从小到大做,每次把小的数删除,…

使用eBPF技术保护FastAPI安全

本文详细介绍如何利用eBPF技术保护面向互联网的API安全,包括FastAPI、Flask、Django等框架。通过secimport工具实现Python代码的实时追踪、沙箱策略构建和运行时监控,有效防御远程代码执行等安全威胁。使用eBPF保护F…

项目案例作业2:对案例进行面向对象分析

学生管理系统面向对象分析报告 小组成员:李天瑞 202421336012 目录学生管理系统面向对象分析报告1. 案例中哪里体现出了封装性及其好处?封装性的体现封装性带来的好处2. 案例中的setter/getter模式与封装性什么是set…

20251010周五日记

20251010周五日记今天十点多回学校了,好不容易不下雨了。没想到国庆还真加了那么多天班= = 今日: 1.早上吃完早饭收拾东西慢慢悠悠回来了,打印朋辈表多亏师哥妙手回春。准备去开学代会,说来又要翘课了。 2.中午吃了…

k8s 主节点重启后 从节点 get 异常 - 教程

k8s 主节点重启后 从节点 get 异常 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "…