1.打包前必备(Android/iOS)
Android 签名配置(生成密钥库)
首先打开电脑win加r然后打开cmd进入控制台

你想在哪个文件夹生成签名,就先进入那个目录,然后执行签名命令,签名文件就会生成在当前目录!我就以F盘为例,我在F盘创建了个flutter文件夹然后在flutter文件夹内又创建了个key文件夹,如下

刚刚我们打开了cmd,然后在控制台内进入F:\flutter\key
/d 参数就是让 cd 同时切换盘符和目录。
bash
cd /d F:\flutter\key
然后执行生成密钥命令
bash
keytool -genkey -v -keystore upload-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload
输入完之后,回车就会让你填写一些资料
bash
输入密钥库口令:lidengkui(我用的是我的姓名)
再次输入新口令:lidengkui
您的姓名与姓氏是什么?
[Unknown]:
您的组织单位名称是什么?
[Unknown]:
您的组织名称是什么?
[Unknown]:
您所在的城市或区域名称是什么?
[Unknown]:
您所在的省/市/自治区名称是什么?
[Unknown]:
该单位的两字母国家代码是什么?
[Unknown]: CN
逐项说明:
输入密钥库口令
这是 .jks 文件本身的密码,必须记牢! 后面打包要用到
输入时不会显示字符,正常输入就行
再次输入新口令
重复一遍刚才的密码,确认一致
姓名与姓氏
可以填你的英文名 / 中文名,比如 Zhang San 或直接回车留空
组织单位名称
比如公司部门名,或直接回车
组织名称
公司名,或直接回车
城市 / 区域
城市名,或直接回车
省 / 市 / 自治区
省份名,或直接回车
两字母国家代码
中国填 CN,必须填,不能空
最后会问
bash
CN=xxx, OU=xxx, O=xxx, L=xxx, ST=xxx, C=CN 是否正确?
[否]: y
输入 y 回车确认即可
还会问
bash
输入 <upload> 的密钥口令
(如果和密钥库口令相同, 按回车):
建议直接回车,让密钥密码和密钥库密码一致,方便记忆
最简单的偷懒填法(推荐)
bash
口令:自己设一个复杂密码,务必记好
姓名到省份:全部直接按回车跳过
国家代码:输入 CN
确认:输入 y
密钥口令:直接回车(和库密码一致)
这样最快,也完全满足打包要求 ✅


2.在 android 文件夹创建 key.properties 文件
在 android/ 文件夹里新建一个文件,名字叫:
key.properties
内容复制下面这段,把密码改成你自己的:
bash
storePassword=你刚才设置的密钥库密码
keyPassword=你刚才设置的密钥密码(直接回车就是和上面一样)
keyAlias=upload
storeFile=upload-keystore.jks


弄完之后将刚刚第1步生成的upload-keystore.jks文件复制在android\app\目录下
即android\app\upload-keystore.jks

3.修改 android/app/build.gradle
打开这个文件:android/app/build.gradle
在文件最上面添加这段代码
bash
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
我的代码感觉跟别人的有点不一样,我加在了这页代码的android符号上面了


还是在当前的这个文件上android/app/build.gradle,继续编辑这个文件找到 android {...} 里面的 buildTypes部分
把原来的 buildTypes替换成:
bash
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}

总结来说就是改如下
你可以直接把下面这段完整替换到 android/app/build.gradle 里:
bash
// 先在文件顶部加载 key.properties
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
// ... 其他配置 ...
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
4.打包
打包 Android 正式 APK

在项目根目录终端输入:
bash
flutter build apk --release
生成路径:
build/app/outputs/flutter-apk/app-release.apk

这个打包也有一些区别
1.只针对 arm64-v8a 架构(主流 64 位安卓手机)构建单一 APK,产物只有 1 个 APK,体积更小
bash
flutter build apk --target-platform android-arm64
1.按不同 ABI 架构拆分生成多个独立 APK
每个 APK 只包含对应架构的代码,体积最小,应用商店会自动给用户推送最合适的 APK
bash
flutter build apk --split-per-abi
其他辅助
刚刚从别人的开发的app里面获取到一些知识
Android 权限声明
android/app/src/main/AndroidManifest.xml
写在 AndroidManifest.xml 文件里,作用是告诉安卓系统:你的 App 需要使用哪些系统能力。
在 Flutter 开发中,如果你的 App 有网络请求,必须在 AndroidManifest.xml 中声明 INTERNET 权限,否则会无法联网
位置:android/app/src/main/AndroidManifest.xml,放在 标签内、 标签外
bash
<manifest ...>
<!-- 网络权限 -->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- 网络状态权限 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application ...>
...
</application>
</manifest>
我帮你整理一份Flutter 常用 Android 权限清单(比如定位、存储、相机等),方便你以后直接复制使用
网络相关
bash
<!-- 访问网络(必须:所有需要联网的 App) -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 检查网络状态(判断 Wi-Fi/移动网络、是否联网) -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 检查 Wi-Fi 状态(精细控制 Wi-Fi 场景) -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
定位相关
注意:定位属于危险权限,需要在 Flutter 代码中动态申请。
bash
<!-- 粗略定位(基站/网络定位) -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 精确定位(GPS 定位) -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 后台定位(Android 10+,App 在后台时也能获取位置) -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
相机与媒体
相机、存储属于危险权限,需要动态申请。
bash
<!-- 相机权限(拍照、扫码、视频通话) -->
<uses-permission android:name="android.permission.CAMERA" />
<!-- 读取外部存储(Android 13 以下,读取图片/视频/文件) -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- 写入外部存储(Android 13 以下,保存图片/文件) -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- Android 13+ 读取图片(替代 READ_EXTERNAL_STORAGE) -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<!-- Android 13+ 读取视频(替代 READ_EXTERNAL_STORAGE) -->
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<!-- Android 13+ 读取音频(替代 READ_EXTERNAL_STORAGE) -->
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
麦克风与音频
bash
<!-- 麦克风权限(录音、语音通话) -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
电话与设备信息
bash
<!-- 读取设备状态(获取 IMEI、设备信息等,部分统计 SDK 需要) -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- 拨打电话(直接拨号,需动态申请) -->
<uses-permission android:name="android.permission.CALL_PHONE" />
通知与系统弹窗
bash
<!-- 通知权限(Android 13+ 需动态申请) -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<!-- 悬浮窗/系统弹窗(显示在其他 App 之上,如悬浮球) -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
重要说明
普通权限 vs 危险权限
普通权限(如 INTERNET):安装时自动授予,无需用户手动同意。
危险权限(如 CAMERA、LOCATION、STORAGE):必须在 Flutter 代码中动态申请,用户同意后才能使用。
权限声明最小化
只声明 App 实际需要的权限,避免冗余权限被系统或应用商店拒绝。
Android 版本适配
存储权限在 Android 13+ 有重大变更,用 READ_MEDIA_* 替代旧的 READ_EXTERNAL_STORAGE。
后台定位需要额外声明 ACCESS_BACKGROUND_LOCATION,且在 Android 10+ 中需要用户单独授权。
常用权限集合
bash
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.your_app">
<!-- 网络 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 定位 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 相机 -->
<uses-permission android:name="android.permission.CAMERA" />
<!-- 存储(适配 Android 13+) -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<!-- 麦克风 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!-- 通知(Android 13+) -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<application
android:label="your_app"
android:icon="@mipmap/ic_launcher">
<!-- ... 其他配置 ... -->
</application>
</manifest>