Flutter 如何釋出安卓應用?

島上碼農發表於2021-05-10

設定應用的名稱,包名、應用圖示和啟動

安卓的應用資源配置在main/AndroidManifest.xml中設定,檔案內容如下:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.gesture_demo">
    <!-- io.flutter.app.FlutterApplication is an android.app.Application that
         calls FlutterMain.startInitialization(this); in its onCreate method.
         In most cases you can leave this as-is, but you if you want to provide
         additional functionality it is fine to subclass or reimplement
         FlutterApplication and put your custom class here. -->
    <application
        android:name="io.flutter.app.FlutterApplication"
        android:label="gesture_demo"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>
</manifest>

複製程式碼

Flutter生成的檔案建議是大部分內容可以保留不動,但是可以根據需要進行修改。
具體可能要修改的內容如下:

屬性名用途說明
package應用包名安卓應用的唯一識別符號,一般為com.xxxx.xxx格式
android:label應用顯示名稱預設為工程名,需要根據實際情況修改
android:icon應用圖示替換指定的圖示檔案即可
meta-data
   android:name
資源名稱不可更改,用於Flutter生成安卓外掛
meta-data
  value
資源值不可更改,用於Flutter生成安卓外掛

替換應用圖示

安卓提供瞭如下尺寸的圖示配置檔案,在Flutter專案下的android/app/src/main/res對應尺寸目錄下可以應用圖示檔案。

尺寸別名圖示大小螢幕尺寸
mipmap-mdpi48x48320×480
mipmap-hdpi72x72480×800,480×854
mipmap-xhdpi96x961280*720,720p
mipmap-xxhdpi144x1441920*1080,1080p
mipmap-xxxhdpi192x1923840×2160,4k

替換啟動頁

應用啟動頁圖片在Flutter專案下的android/app/src/main/drawable下的launch_background.xml配置檔案中,預設是一個白色底,xml問卷如下所示:

<?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:gravity="center"
            android:src="@mipmap/launch_image" />
    </item> -->
</layer-list>

複製程式碼

註釋掉的部分可以用來設定啟動頁圖片,需要注意部分機型的尺寸未必和啟動頁圖片一致,因此可以設定啟動頁的背景色與啟動頁圖片邊緣一致。

<?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" />
		
  	<!-- 啟動頁圖片,也可以新增其他元素 -->
    <item>
        <bitmap
            android:gravity="center"
            android:src="@mipmap/launch_image" />
    </item>
</layer-list>

複製程式碼

設定訪問許可權

在android/app/src下的AndroidManifest.xml(注意不是src/profile資料夾下的AndroidManifest.xml檔案)檔案中設定應用許可權,如訪問網路,相簿,攝像頭等。開發環境是在android/src/debug的AndroidManifest.xml中設定。下面是一個示例的檔案:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.animation_demo">

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    
    <application
        android:name="io.flutter.app.FlutterApplication"
        android:label="動畫演示"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>
</manifest>

複製程式碼

配置版本釋出引數

在android/app/build.gradle檔案檢查配置是否正確:

  1. applicaitonId:應用唯一AppId,如com.lios.helloworld
  2. versionCode:應用程式版本號
  3. versionName:版本號字串
  4. minSdkVersion:指定最低的API級別
  5. targetSdkVersion:指定應用程式設計執行的API級別

如下所示:

android {
    compileSdkVersion 28

    sourceSets {
        main.java.srcDirs += 'src/main/kotlin'
    }

    lintOptions {
        disable 'InvalidPackage'
    }

    defaultConfig {
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
        applicationId "com.example.animation_demo"
        minSdkVersion 16
        targetSdkVersion 28
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    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
        }
    }
}
複製程式碼

這裡面可以看到versionCode和versionName是從flutterVersionCode和flutterVersionName中引入的,其中這兩個變數在build.gradle上面有定義。先從local.properties中讀取,若沒有再在該檔案中定義,因此可以在localProperties中設定或在build.gradle中設定(優先取local.properties中的值)。

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
    flutterVersionCode = '1'
}

def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
    flutterVersionName = '1.0'
}
複製程式碼

生成應用簽名

建立keystore,如果之前建立過了,在key.properties中引入即可。

#其中~/key.jks是將keystore檔案key.jks儲存在~/目錄下
keytool -genkey -v -keystore ~/key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key

複製程式碼

按提示輸入密碼和組織資訊即可。

輸入金鑰庫口令:  
再次輸入新口令: 
您的名字與姓氏是什麼?
  [Unknown]:  lag
您的組織單位名稱是什麼?
  [Unknown]:  island-coder
您的組織名稱是什麼?
  [Unknown]:  RD
您所在的城市或區域名稱是什麼?
  [Unknown]:  Coder
您所在的省/市/自治區名稱是什麼?
  [Unknown]:  Island
該單位的雙字母國家/地區程式碼是什麼?
  [Unknown]:  CN
CN=lag, OU=island-coder, O=RD, L=Coder, ST=Island, C=CN是否正確?
  [否]:  Y

正在為以下物件生成 2,048 位RSA金鑰對和自簽名證照 (SHA256withRSA) (有效期為 10,000 天):
	 CN=lag, OU=island-coder, O=RD, L=Coder, ST=Island, C=CN
[正在儲存/Users/lag/key.jks]

複製程式碼

在android目錄下建立一個key.properties檔案,用於引用金鑰庫資訊:

storePassword={金鑰庫密碼} #
keyPassword={證照密碼}
keyAlias=key    #對應命令列的-alias後的別名
storeFile=/Users/lag/key.jks  #對應命令生成的key.jks的據對路徑
複製程式碼

修改配置檔案

在build.gradle檔案中,在android下增加以下內容:

	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.
            signingConfig signingConfigs.release
            
        }
    }
複製程式碼

打包

在專案目錄下,執行下面的命令:

flutter build apk
複製程式碼

預設按release打包,生成的apk在build.app/outputs/apk/app-release.apk下。

注意事項

修改AndroidManifest.xml檔案後,flutter打包可能存在快取,此時執行下面的命令,清除掉快取再次打包即可。

flutter clean
複製程式碼

相關文章