Flutter - Android打包与发版

本文介绍flutter项目,安卓端打包流程

Flutter官方文档:构建和发布为 Android 应用
Flutter中文网: 发布Android版APP
Android官方文档:发布应用

准备工作、检查

  • 版本号接口地址、包名、应用名称、应用图标、启动图等信息
  • 权限配置
  • 测试登录是否正常

一、Android 打包

1.1、打包apk文件

apk打包命令

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平台 说明

1.2、打包AAB文件

aab打包命令

flutter build appbundle // 运行 flutter build 默认构建一个发布版本

生成的 release bundle 文件位于:

项目所在文件夹下的 build/app/outputs/bundle/release/app.aab.

1.3、打包报错

1.3.1、lintOptions检查错误

报错

* 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 类型错误则会关闭)
    }

注:最好还是找到出问题的地方解决掉问题

1.3.2、 Failed to transform bcprov-jdk15on-1.68.jar

报错

* 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,没有测试降级是否可行

二、Android 发版准备工作:

2.1、版本号

Flutter官方文档-更新应用版本号
Android官方文档-对您的应用进行版本控制

每个应用默认的初始版本号是 1.0.0。若要更新它,请转到 pubspec.yaml 文件并更新以下内容:
version: 1.0.0+1
版本号由三个点分隔的数字组成,例如上面样例中的 1.0.0。然后是可选的构建号,例如上面样例中的 1,以 + 分隔。
版本号与构建号都可以在 Flutter 打包时分别使用 --build-name 和 --build-number 重新指定。
在 Android 中,build-number 被用作 versionCode, build-name 将作为 versionName 使用。更多信息请参考 Android 文档中的 为你的应用添加版本。
当重新构建 Android 应用后,任何在 pubspec 文件所做的版本号更新,都将会更新 local.properties 文件中的 versionName 和 versionCode。

pubspec.yaml

version: 1.0.0+1

在Android中,应用的版本分为 versionName & versionCode
versionName:用户显示的版本号
versionCode:内部管理的版本号

Flutter中我们如何管理这两个版本号呢?
通过修改pubspec.yaml文件中的version属性即可
下面1.0.0+1中用“+”号分割

version: 1.0.0+1

1.0.0:用户显示的版本
1:内部管理的版本

versionNameversionCode
1.0.01

2.2、应用图标

启动图标资源路径 :

/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 图标是否已经替换成我们自己的图标文件。

2.3、应用名称

/android/app/src/main/AndroidManifest.xml 目录中
更新 application 标签中的 android:label属性来更新APP名称

 <application
     android:label="XXX"> // APP的名称
 </application>

2.4、应用启动图片

启动图片资源路径 :

/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 启动图片是否已经替换成我们自己的图片文件。

2.5、应用包名(applicationId)

创建项目时就录入的有包名,一般不需要改动
同样的,在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;

2.6、用户权限配置

在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>

2.6.1 安卓常用权限

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

3.1、生成签名证书 .jks文件(生成秘钥库keystore)

Android系统在安装APK的时候,首先会检验APK的签名,如果发现签名文件不存在或者校验签名失败,则会拒绝安装,所以应用程序在发布之前一定要进行签名。

官方说明:

要想把 app 发布到 Play store,还需要给 app 一个数字签名。我们可以采用以下步骤来为 app 签名:
Android 中有两种签名密钥: 部署和上传。终端用户下载到的 .apk 文件是被部署密钥签名过的文件,上传密钥用于验证开发者上载到 Play 商店的 .aab 或 .apk 文件。上传密钥是给予部署密钥重新签名的密钥,上载 Play 商店时候需要用到。
严重推荐你选择云托管的方式来管理部署密钥,更多相关信息,请参阅官方文档 使用 Play 应用签名功能

使用签名的主要作用是:

应用程序升级:只有以同一个证书签名,系统才会允许安装升级的应用程序。如果你采用了不同的证书,那么系统会要求你的应用程序采用不同的包名称,在这种情况下相当于安装了一个全新的应用程序。如果想升级应用程序,签名证书要相同,包名称要相同!

应用程序模块化:Android 系统可以允许同一个证书签名的多个应用程序在一个进程里运行,系统实际把他们作为一个单个的应用程序,此时就可以把我们的应用程序以模块的方式进行部署,而用户可以独立的升级其中的一个模块。

代码或者数据共享:Android 提供了基于签名的权限机制,那么一个应用程序就可以为另一个以相同证书签名的应用程序公开自己的功能。以同一个证书对多个应用程序进行签名,利用基于签名的权限检查,你就可以在应用程序间以安全的方式共享代码和数据了。

注意一旦给Apk签名并上线后,签名文件和密码别名等一定不能丢失,否则就等着跑路吧。

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。

3.2、app中引用秘钥库

这里新建一个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=密钥库的位置

在这里插入图片描述

3.3、在 gradle 中配置签名

在以 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文件,填写相关的信息审核即可

4.1、Google Play

国外的应用市场通常只有一个Google Play
1.需要申请一个Google Play 开发者账号
需要支付25美元注册费用的信用卡,信用卡需要支持Visa, Master Amex, Discover, JCB。
Google 应用发布地址
2.进入到管理中心,创建应用发布即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值