Android 開發--多渠道打包實現

背景

學習多渠道打包,用的 demo 來做一個簡單的演示。


多渠道是什麼

渠道就是指不同的安裝包發佈平臺:有應用寶、百度、小米、360、豌豆莢等應用發佈平臺。你打包後的 app 就可以發佈在這些平臺上供用戶自行下載體驗。


爲什麼要做多渠道打包

方便後臺統計 app 在各個平臺上的下載次數。


多渠道打包原理

一般,我們在清單配置文件中聲明一個 meta-data 標籤,裏面設置對應的 namevalue 屬性,我們可以在代碼中根據 name 獲取到對應的 value,這個 value 就是我們需要的渠道信息。


怎麼實現渠道信息的統計

這裏簡單說一下實現:例如用戶從豌豆莢市場下載了 app ,安裝後並打開使用。這個時候我們在代碼中就能獲取到 wandoujia 這個渠道信息,然後把這個信息通過調用接口統計到後臺。

不過目前有很多開發者平臺都提供了對應的 sdk 供我們集成使用,比如 友盟 這個大家族,集成友盟統計的功能我會在下期文章中提供。通過集成友盟的統計功能,我們可以很方便的在友盟開發者平臺上看到我們發佈後的 app 的一個下載使用情況,很實用的一個功能。


打包實現

清單配置文件添加 meta-data 標籤

<meta-data android:value="${MY_CHANNEL_VALUE}" android:name="MY_CHANNEL"/>

如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.fragmentdemo">

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:name=".application.MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <meta-data android:value="${MY_CHANNEL_VALUE}" android:name="MY_CHANNEL"/>

        <activity android:name=".activity.MainActivity"
            android:configChanges="orientation|screenSize|keyboardHidden">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

這裏簡單說明一下:value 值用了佔位符來表示,方便一次性打多個渠道包。


密鑰生成

使用簽名密鑰來生成 release 版 apk,這纔是正式生產使用的安裝包。所以我們需要先來生產簽名密鑰。

密鑰生成我在上一篇文章 Warning:JKS 密鑰庫使用專用格式。建議使用 “keytool -importkeystore -srckeystore…pkcs12” 遷移到行業標準格式 PKCS12 中有詳細的介紹,供同學們參考。


簽名配置

我們有了簽名密鑰,可以用來配置一個 release 版的簽名,方便打包,如下:

在這裏插入圖片描述

配置好後,app 模塊下的 build.gradle 文件會多出簽名信息配置,如下圖:

在這裏插入圖片描述

我這裏還用到了一個 keystore.properties 文件,如下圖示:

在這裏插入圖片描述

內容如下圖示:

在這裏插入圖片描述

app 模塊下 build.gradle 文件完整內容如下:

apply plugin: 'com.android.application'

def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))

android {

    compileSdkVersion 28
    buildToolsVersion "29.0.3"

    defaultConfig {
        applicationId "com.example.fragmentdemo"
        minSdkVersion 19
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    signingConfigs {
        release {
            storeFile file(keystoreProperties['storeFile'])
            storePassword keystoreProperties['storePassword']
            keyAlias keystoreProperties['keyAlias']
            keyPassword keystoreProperties['keyPassword']
        }
    }

    buildTypes {
        release {
            minifyEnabled false // 不啓用混淆
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
        }
    }

}


dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

}


創建風味維度與 Product 風味

什麼是風味維度,這裏暫不作說明,同學們可參考文章 Android Studio3.0 flavorDimensions多維度理解(版本差異化打包) 自行了解。

  • 打開 風味維度 創建窗口,如下圖示:
    在這裏插入圖片描述

  • 首先添加一個 風味維度,如下圖示:
    在這裏插入圖片描述

  • 輸入 風味維度 名稱,如下圖示:
    在這裏插入圖片描述

  • 風味維度 創建完成後如下圖示:
    在這裏插入圖片描述

  • Add Product Flavor
    在這裏插入圖片描述

  • 輸入 product flavor 名稱,如下圖示:
    在這裏插入圖片描述

  • product flavor 名稱創建完成後,選擇 release 簽名配置,如下圖示:
    在這裏插入圖片描述

  • 依次添加 baidu 和 yingyongbao 渠道,並點擊 apply ,如下圖示:
    在這裏插入圖片描述

  • 等待 gradle 同步完成後,我們再看 app 模塊下的 build.gradle 文件多出的風味配置項如下圖示:

在這裏插入圖片描述


風味配置項的一些優化

  • 佔位符使用,減少重複配置
    在這裏插入圖片描述

  • 可自定義打包後的 apk 名稱

在這裏插入圖片描述

最後給出完整的 build.gradle 文件內容,如下:

apply plugin: 'com.android.application'

def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))

android {

    compileSdkVersion 28
    buildToolsVersion "29.0.3"

    defaultConfig {
        applicationId "com.example.fragmentdemo"
        minSdkVersion 19
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    signingConfigs {
        release {
            storeFile file(keystoreProperties['storeFile'])
            storePassword keystoreProperties['storePassword']
            keyAlias keystoreProperties['keyAlias']
            keyPassword keystoreProperties['keyPassword']
        }
    }

    buildTypes {
        release {
            minifyEnabled false // 不啓用混淆
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
        }
    }
    flavorDimensions 'dimensionOne'
    productFlavors {
        wandoujia {
            dimension = 'dimensionOne'
            signingConfig signingConfigs.release
        }
        baidu {
            dimension = 'dimensionOne'
            signingConfig signingConfigs.release
        }
        yingyongbao {
            dimension = 'dimensionOne'
            signingConfig signingConfigs.release
        }
    }

    // 使用 佔位符 優化,減少重複風味配置寫法
    productFlavors.all{
        flavor -> flavor.manifestPlaceholders = [MY_CHANNEL_VALUE : name]
    }

    // 輸出文件配置,格式如下:app-{版本號}-{渠道名稱}.apk
    applicationVariants.all { variant ->
        variant.outputs.all { output ->
            def outputFile = output.outputFile
            if (outputFile != null && outputFile.name.endsWith('.apk')) {

                // 文件名修改
                def fileName = "app-v${defaultConfig.versionName}-${variant.productFlavors[0].name}.apk"

                // 重命名賦值
                outputFileName = fileName
            }
        }
    }

}


dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

}


使用 gradle 的build tasks 進行打包

  • 如下圖示:
    在這裏插入圖片描述
  • 打包成功後如下圖示:
    在這裏插入圖片描述

多渠道包查看

  • 我們打完多渠道包後,可在如下圖示位置查看一次性生成的多渠道包:

在這裏插入圖片描述


渠道信息驗證

  • 獲取渠道信息代碼如下:
// 獲取渠道信息
        try {
            ApplicationInfo applicationInfo = MainActivity.this.getPackageManager().getApplicationInfo(
                    MainActivity.this.getPackageName(), PackageManager.GET_META_DATA
            );

            String channel = applicationInfo.metaData.getString("MY_CHANNEL");
            Log.e("TAG", "metaData value is :" + channel);

            Toast.makeText(MainActivity.this, "當前應用的渠道爲:" + channel,
                    Toast.LENGTH_LONG).show();

        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
  • 我們依次安裝,打開獲取渠道信息如下圖示:

在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述
到此,我們就實現了多渠道打包。


技術永不眠,我們下期見!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章