本文介绍flutter项目,安卓端打包流程
官方文档:构建和发布为 Android 应用
Flutter中文网: 发布Android版APP
版本号
、接口地址
、包名、应用名称、应用图标、启动图等信息flutter build apk //(flutter build 默认带有 --release 参数)
flutter build apk --release
flutter build apk --debug
没有适配空安全就打没有空安全的包
flutter build apk --release --no-sound-null-safety
生成的 release APK 文件位于:
项目所在文件夹下的 build/app/outputs/flutter-apk/app-release.apk
如果包体积过大的话,可以考虑使用:
flutter build apk --split-per-abi
上述打包命令会在/build/app/outputs/apk/release
目录下生成两个apk文件:
app-armeabi-v7a-release.apk
app-armeabi-v8a-release.apk
移除 --split-per-abi参数后,会生成支持所有ABI平台的Apk文件,这样会导致文件体积变大。
Flutter暂不支持x86平台 说明
flutter build appbundle // 运行 flutter build 默认构建一个发布版本
生成的 release bundle 文件位于:
项目所在文件夹下的 build/app/outputs/bundle/release/app.aab.
报错
* What went wrong:
Execution failed for task ':app:lintVitalRelease'.
> Lint infrastructure error
Caused by: java.lang.reflect.InvocationTargetException
...
解决方法
安卓 lintOptions配置项说明
lintOptions {
disable 'InvalidPackage'
// 下面两行代码解决构建release apk时报错:Execution failed for task ':app:lintVitalRelease'.
abortOnError false // 是否发现错误,则停止构建
checkReleaseBuilds false // 检查到有导致崩溃的错误是否停止构建(在 release 版本是否检查 fatal 类型错误,默认release版本为开启。开启后,检查到 fatal 类型错误则会关闭)
}
注:最好还是找到出问题的地方解决掉问题
报错
* What went wrong:
Execution failed for task ':app:lintVitalRelease'.
> Could not resolve all artifacts for configuration ':image_picker_android:debugUnitTestRuntimeClasspath'.
> Failed to transform bcprov-jdk15on-1.68.jar (org.bouncycastle:bcprov-jdk15on:1.68) to match attributes {artifactType=processed-jar, org.gradle.category=library, org.gradle.libraryelements=jar, org.gradle.status=release, org.gra
dle.usage=java-runtime}.
> Execution failed for JetifyTransform: C:\Users\xxx\.gradle\caches\modules-2\files-2.1\org.bouncycastle\bcprov-jdk15on\1.68\46a080368d38b428d237a59458f9bc915222894d\bcprov-jdk15on-1.68.jar.
> Failed to transform 'C:\Users\xxx\.gradle\caches\modules-2\files-2.1\org.bouncycastle\bcprov-jdk15on\1.68\46a080368d38b428d237a59458f9bc915222894d\bcprov-jdk15on-1.68.jar' using Jetifier. Reason: IllegalArgumentException,
message: Unsupported class file major version 59. (Run with --stacktrace for more details.)
Suggestions:
- Check out existing issues at https://issuetracker.google.com/issues?q=componentid:460323&s=modified_time:desc, it's possible that this issue has already been filed there.
- If this issue has not been filed, please report it at https://issuetracker.google.com/issues/new?component=460323 (run with --stacktrace and provide a stack trace if possible).
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
解决办法
在 Android目录下的gradle.propertie文件,加上
android.jetifier.blacklist=bcprov-jdk15on
注:网上搜到有说是java版本过高,我用的java17,没有测试降级是否可行
在pubspec.yaml
中
version: 1.0.0+1
在Android中,应用的版本分为versionCode & versionName
versionCode:内部管理的版本号
versionName:用户显示的版本号
Flutter中我们如何管理这两个版本号呢?
1.0.0:用户显示的版本
1:内部管理的版本
启动图标资源路径 :
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
在
/android/app/src/main/AndroidManifest.xml
中,更新application
标签中的 android:icon 属性来引用上一步骤中我们自己的图标文件
<application
android:icon="@mipmap/ic_launcher">
</application>
用 flutter run 运行 app,检查启动程序中的 app 图标是否已经替换成我们自己的图标文件。
在
/android/app/src/main/AndroidManifest.xml
目录中
更新application
标签中的android:label
属性来更新APP名称
<application
android:label="XXX"> // APP的名称
</application>
启动图片资源路径 :
/android/app/src/main/res/mipmap-xxhdpi/launch_image.png
/android/app/src/main/res/mipmap-xxxhdpi/launch_image.png
在
/android/app/src/main/res/drawable/launch_background.xml
中,更新bitmap
标签中的 android:src属性来更新启动图片
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<item>
<bitmap
android:src="@mipmap/launch_image" />
</item>
</layer-list>
用 flutter run 运行 app,检查启动程序中的 app 启动图片是否已经替换成我们自己的图片文件。
创建项目时就录入的有包名,一般不需要改动
,
同样的,在app/build.gradle
中设置安卓兼容版本targetSdkVersion
、最低版本minSdkVersion
、编译版本compileSdkVersion
,一般不用设置,除非你是要变更
如果需要改动包名,需要改动以下的地方:
/android/app/src/main/AndroidManifest.xml
文件修改package=“xxx.xxx.xxx”;
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.xxx">
</manifest>
/android/app/build.gradle
文件修改applicationId =“xxx.xxx.xxx”;
defaultConfig {
applicationId "com.example.xxx"
}
/android/app/src/main/包名/MainActivity.java
文件修改对应的包路径
package com.example.xxx;
在Android中某些用户权限需要在AndroidManifest.xml进行配置:
比如默认情况下应用程序是不能发送网络请求的,如果之后App中有用到网络请求,那么需要在AndroidManifest.xml中进行如下配置(默认debug模式下有配置网络请求)
注:
Android 6.0 (API 23) 之前应用的权限在安装时全部授予,运行时应用不再需要询问用户。在 Android 6.0 或更高版本对权限进行了分类,对某些涉及到用户隐私的权限可在运行时根据用户的需要动态授予。这样就不需要在安装时被强迫同意某些权限。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.xxx">
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
Android 权限大全
Android 权限大全
<!--访问网络-->
<uses-permission android:name="android.permission.INTERNET" />
<!--拍照权限,允许访问摄像头进行拍照-->
<uses-permission android:name="android.permission.CAMERA" />
<!--内置sd卡的读写权限-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--获取网络信息状态,如当前的网络连接是否有效-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!--获取当前WiFi接入的状态以及WLAN热点的信息-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!--读取电话状态-->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!--拨打电话,允许程序从非系统拨号器里输入电话号码-->
<uses-permission android:name="android.permission.CALL_PHONE" />
<!--读取短信内容-->
<uses-permission android:name="android.permission.READ_SMS" />
<!--写入联系人,但不可读取-->
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<!--获取精确位置,通过GPS芯片接收卫星的定位信息,定位精度达10米以内-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!--获取错略位置,通过WiFi热点或移动基站的方式获取用户错略的经纬度信息,定位精度大概误差在30~1500米-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
flutter官方文档:为 app 签名
Android Studio官方文档:为你的应用签名
Flutter中文网:发布Android版APP
生成签名证书 .jks
Android系统在安装APK的时候,首先会检验APK的签名,如果发现签名文件不存在或者校验签名失败,则会拒绝安装,所以应用程序在发布之前一定要进行签名。
官方说明:
要想把 app 发布到 Play store,还需要给 app 一个数字签名。我们可以采用以下步骤来为 app 签名:
Android 中有两种签名密钥: 部署和上传。终端用户下载到的 .apk 文件是被部署密钥签名过的文件,上传密钥用于验证开发者上载到 Play 商店的 .aab 或 .apk 文件。上传密钥是给予部署密钥重新签名的密钥,上载 Play 商店时候需要用到。
严重推荐你选择云托管的方式来管理部署密钥,更多相关信息,请参阅官方文档 使用 Play 应用签名功能。
使用签名的主要作用是:
应用程序升级:只有以同一个证书签名,系统才会允许安装升级的应用程序。如果你采用了不同的证书,那么系统会要求你的应用程序采用不同的包名称,在这种情况下相当于安装了一个全新的应用程序。如果想升级应用程序,签名证书要相同,包名称要相同!
应用程序模块化:Android 系统可以允许同一个证书签名的多个应用程序在一个进程里运行,系统实际把他们作为一个单个的应用程序,此时就可以把我们的应用程序以模块的方式进行部署,而用户可以独立的升级其中的一个模块。
代码或者数据共享:Android 提供了基于签名的权限机制,那么一个应用程序就可以为另一个以相同证书签名的应用程序公开自己的功能。以同一个证书对多个应用程序进行签名,利用基于签名的权限检查,你就可以在应用程序间以安全的方式共享代码和数据了。
注意:一旦给Apk签名并上线后,签名文件和密码别名等一定不能丢失,否则就等着跑路吧。
方式一:参考文档 在 Android Studio 上为你的应用签名。
方式二:在命令行窗口运行如下的命令:
在 macOS 或者 Linux 系统上,执行下面的代码:
keytool -genkey -v -keystore ~/key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key
在 Windows 系统上,执行下述代码:
keytool -genkey -v -keystore d:\key.jks -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 -alias key
keytool -genkey -v -keystore:产生密钥
d:\key-keystore.jks :证书的存放路径和名字
keyalg RSA -keysize 2048 :使用 2048 位 RSA 算法对签名加密
validity 10000 :有效期时间,这里是 10000天
alias sign : 别名 key
该命令将会把
key.jks
文件储存到自己设置的存放路径里。 注意,请保证这个文件的私有性,不要将它提交到公共的代码管理空间。
注:
如果没有keytool命令可能没有配置java的环境变量,可进行环境变量配置或进入java安装目录下打开cmd,再生成签名文件
cd /d d:\java\bin
记好设置的秘钥库口令和秘钥口令,里面输入的信息可以改成一样的,比如android
提示
keytool 可能不在我们的系统路径中。它是 Java 的一部分,在安装 Android Studio 的时候会被一起安装。运行 flutter doctor -v,’Java binary at:’ 之后打印出来的就是它的路径,然后用 java 来替换以上命令中的 keytool,并加上 keytool 的完整路径即可。如果文件路径包含空格,类似 Program Files 这样的,请使用平台允许的命名规则。例如,在 Mac/Linux 上使用 Program\ Files,而在 Windows 上可以使用 “Program Files”。
只有 Java 9 或更高版本才需要 -storetype JKS 标签。从 Java 9 版本开始,keystore 类型默认为 PKS12。
这里新建一个key文件夹,导入上面创建好的key.jks
文件
/android/app/key/key.jks
创建 key.properties 文件
/android/app/key/key.properties
添加配置,可以复制已有的 properties 文件,修改名字和对应的内容
storePassword=xxxxxx
keyPassword=xxxxxx
keyAlias=key
storeFile=key/key.jks
storePassword=上一步骤中的密码
keyPassword=上一步骤中的密码(生成签名证书输入的密库口令)
keyAlias=sign(证书的别名)
storeFile=密钥库的位置
在以 release 模式下构建你的应用时,修改 [project]/android/app/build.gradle 文件,以通过 gradle 配置你的上传密钥。
这一步主要就是替换代码
[project]/android/app/build.gradle
路径下,android 代码块
上一行,添加密钥库信息代码
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('app/key/key.properties') // 上面放置的路径
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
...
}
将 key.properties
文件加载到 keystoreProperties
对象中。
找到 buildTypes 代码块,把如下代码进行替换
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.debug
}
}
将其替换为我们的配置内容:
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
现在我们 app 的release版本就会被自动签名了。
可以运行 flutter build apk
命令测试打包是否成功
Android应用程序可以发布到很多的平台,包括国内的平台和国外的Google Play
国内的应用市场非常多,包括360、百度、小米、应用宝等等
可以根据不同的应用市场相关的规则,上传对应的APK或者AAB文件,填写相关的信息审核即可
国外的应用市场通常只有一个Google Play
1.需要申请一个Google Play 开发者账号
需要支付25美元注册费用的信用卡,信用卡需要支持Visa, Master Amex, Discover, JCB。
Google 应用发布地址
2.进入到管理中心,创建应用发布即可