多渠道打包有什么用我就不說了,其實還不是上面提出的需求,為了這些需求,那我們也只能依法實現(xiàn)了。下面給大家介紹一下我平時寫的多渠道打包,
不過于深入研究其原理,因為在具體的我也說不出來,只是介紹實現(xiàn)的需求。
需求
產(chǎn)品:給我打四個包,我要這四個包應(yīng)用同時裝到一個手機(jī)上,每個應(yīng)用名不一樣,應(yīng)用圖標(biāo)不一樣,打開軟件后顯示的也不一樣。
碼農(nóng):。。。呵呵
新建項目
新建項目之后,修改工程最外層build.gradle文件,目的在于統(tǒng)一管理。
//所有的版本編譯工具在此定義
ext {
//SDK和編譯工具的版本
compileSdkVersion = 25
buildToolsVersion = '25.0.0'
minSdkVersion = 15
targetSdkVersion = 25
//項目依賴庫的版本
supportLibraryVersion = "25.0.0"
}
如圖:
添加之后,自然要用它了,不然改了干啥,在module層級的build.gradle文件里android大括號里面修改一下原有配置。
android{
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
applicationId "com.example.huangcl.manychannel"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode Integer.valueOf(VERSIONCODE)//VERSIONCODE,你會好奇這是哪里來的
versionName VERSIONNAME//VERSIONNAME這個也是
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
...
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile "com.android.support:appcompat-v7:$rootProject.ext.supportLibraryVersion"http://在這里用supportLibraryVersion
testCompile 'junit:junit:4.12'
}
代碼里面的兩個值,是通過在app層級下新建的一個文件名字叫g(shù)radle.properties,這里你也可以叫其他,但一定要.properties后綴,因為Java本身對.properties文件支持。
然后在文件里面寫:
//版本信息
VERSIONCODE=1
VERSIONNAME=1.0.0
得是.properties結(jié)尾。
多渠道步驟一:不同的應(yīng)用名和圖標(biāo)
在清單配置文件里application層級中meta-data接入
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.huangcl.manychannel">
<application
android:allowBackup="true"
android:icon="${app_icon}"http://圖標(biāo)不同不能寫死了
android:label="${app_name}"http://同
android:supportsRtl="true"
android:theme="@style/AppTheme">
//接入友盟
<meta-data
android:name="UMENG_CHANNEL"
android:value="${CHANNEL_ID}" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
接著在app層級下的build.gradle申明接入友盟的渠道。
//通用渠道映射項 def 表示申明
def flavorHash = [UMENG_APPKEY: UMENG_APPKEY];//UMENG_APPKEY友盟的Appkey,同樣寫在你新建的gradle.properties文件中
//渠道分析
//productFlavors,不同定制的產(chǎn)品
productFlavors {
//開發(fā)階段
manychannel_debug {
//冒號前邊的是清單文件里設(shè)置的鍵,后邊的是值,CHANNEL_DEBUG同樣寫在你新建的gradle.properties文件中,下面渠道的也一樣
manifestPlaceholders = [CHANNEL_ID: CHANNEL_DEBUG,
app_icon : "@mipmap/ic_launcher",
app_name : "測試版本"]
}
//內(nèi)部測試階段
manychannel_firim {
manifestPlaceholders = [CHANNEL_ID: CHANNEL_FIRIM,
app_icon : "@mipmap/ic_money",
app_name : "fir版本"]
}
//豌豆夾
manychannel_wandoujia {
manifestPlaceholders = [CHANNEL_ID: CHANNEL_WANDOUJIA,
app_icon : "@mipmap/ic_pay",
app_name : "豌豆莢版本"]
}
//360市場
manychannel_sanliuling {
manifestPlaceholders = [CHANNEL_ID: CHANNEL_SANLIULING,
app_icon : "@mipmap/ic_wechat",
app_name : "360版本"]
}
}
productFlavors背后的延伸
這樣簡單的多渠道就出來了,如圖:
多渠道步驟二:不同的應(yīng)用的包名
做完步驟二你會發(fā)現(xiàn)并不能把四個包裝到同一個手機(jī)上,那是你沒有對渠道進(jìn)行分析,配置,下面來分析渠道。
//映射渠道分析
// productFlavors.all{}表示遍歷上面定義的渠道,flavor ->flavor.manifestPlaceholders.putAll(flavorHash)(manifestPlaceholders 是上面定義的名字)這表示
//把flavorHash集合里面的值加到flavor里面在返還回去(Groovy語法),就等于抽出上面productFlavors的共性,其實app_icon,app_name也可以抽到flavorHash中.
productFlavors.all {
//遍歷
flavor ->
flavor.manifestPlaceholders.putAll(flavorHash);
//println flavor
if (flavor.name.equals("manychannel_debug")) {
flavor.versionCode = Integer.valueOf(VERSIONCODE_DEV);//設(shè)置版本號
flavor.versionName = VERSIONNAME_DEV;//設(shè)置版本名,同樣寫在你新建的gradle.properties文件中
flavor.applicationId = "com.example.huangcl.manychannel_debug"http://設(shè)置包名
} else if (flavor.name.equals("manychannel_firim")) {
flavor.versionCode = Integer.valueOf(VERSIONCODE);
flavor.versionName = VERSIONNAME;
flavor.applicationId = "com.example.huangcl.manychannel_fir"
} else if (flavor.name.equals("manychannel_wandoujia")) {
flavor.versionCode = Integer.valueOf(VERSIONCODE);
flavor.versionName = VERSIONNAME;
flavor.applicationId = "com.example.huangcl.manychannel_wandoujia"
} else if (flavor.name.equals("manychannel_sanliuling")) {
flavor.versionCode = Integer.valueOf(VERSIONCODE);
flavor.versionName = VERSIONNAME;
flavor.applicationId = "com.example.huangcl.manychannel_sanliuling"
}
}
多渠道步驟三:不同的應(yīng)用顯示不同的內(nèi)容
這塊就得在代碼里面實現(xiàn)了,思路很簡單,就是取道清單配置文件中的meta-data的值,注意是application層級的,取到之后判斷不同的值,不同的操作就行了。代碼:
public class MainActivity extends AppCompatActivity {
TextView infoTxt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
infoTxt = (TextView) findViewById(R.id.infoTxt);
ApplicationInfo appInfo = null;
try {
appInfo = this.getPackageManager()
.getApplicationInfo(getPackageName(),
PackageManager.GET_META_DATA);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
String msg=appInfo.metaData.getString("UMENG_CHANNEL");
Log.i("chun", msg);
//println flavor
if ("debug".equals(msg)) {
infoTxt.setText("manychannel_debug");
} else if ("fir.im".equals(msg)) {
infoTxt.setText("manychannel_firim");
} else if ("zhushou.#".equals(msg)) {
infoTxt.setText("manychannel_sanliuling");
}else if ("wandoujia.com".equals(msg)) {
infoTxt.setText("manychannel_wandoujia");
}
}
}
其它
打包的時候,需要簽名配置信息,密碼等等的,你可以把.jks文件放到app層級下面。如圖:
不多說了,下面貼我完整的build.gradle文件和新建的gradle.properties文件內(nèi)容。
-
build.gradle
apply plugin: 'com.android.application' android { compileSdkVersion rootProject.ext.compileSdkVersion buildToolsVersion rootProject.ext.buildToolsVersion defaultConfig { applicationId "com.example.huangcl.manychannel" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode Integer.valueOf(VERSIONCODE)//gradle.properties文件中 versionName VERSIONNAME testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } //聲明簽名信息 signingConfigs { release { keyAlias KEYALIAS//gradle.properties文件中 keyPassword KEYPASSWORD//gradle.properties文件中 storeFile file(STOREFILE)//gradle.properties文件中 storePassword STOREPASSWORD//gradle.properties文件中 } } buildTypes { //發(fā)行版 release { minifyEnabled true //gradle.properties文件中 proguardFiles getDefaultProguardFile(PROGUARD_ANDROID), PROGUARD_RULES //簽名信息 signingConfig signingConfigs.release } //debug版 debug { minifyEnabled false proguardFiles getDefaultProguardFile(PROGUARD_ANDROID), PROGUARD_RULES //簽名信息 signingConfig signingConfigs.release } } //渠道分析 productFlavors { //開發(fā)階段 manychannel_debug { manifestPlaceholders = [CHANNEL_ID: CHANNEL_DEBUG, app_icon : "@mipmap/ic_launcher", app_name : "測試版本"] } //內(nèi)部測試階段 manychannel_firim { manifestPlaceholders = [CHANNEL_ID: CHANNEL_FIRIM, app_icon : "@mipmap/ic_money", app_name : "fir版本"] } //豌豆夾 manychannel_wandoujia { manifestPlaceholders = [CHANNEL_ID: CHANNEL_WANDOUJIA, app_icon : "@mipmap/ic_pay", app_name : "豌豆莢版本"] } //360市場 manychannel_sanliuling { manifestPlaceholders = [CHANNEL_ID: CHANNEL_SANLIULING, app_icon : "@mipmap/ic_wechat", app_name : "360版本"] } } //通用渠道映射項 def flavorHash = [UMENG_APPKEY: UMENG_APPKEY]; //映射渠道分析 productFlavors.all { // flavor -> flavor.manifestPlaceholders.putAll(flavorHash); //println flavor if (flavor.name.equals("manychannel_debug")) { flavor.versionCode = Integer.valueOf(VERSIONCODE_DEV); flavor.versionName = VERSIONNAME_DEV; flavor.applicationId = "com.example.huangcl.manychannel_debug" } else if (flavor.name.equals("manychannel_firim")) { flavor.versionCode = Integer.valueOf(VERSIONCODE); flavor.versionName = VERSIONNAME; flavor.applicationId = "com.example.huangcl.manychannel_fir" } else if (flavor.name.equals("manychannel_wandoujia")) { flavor.versionCode = Integer.valueOf(VERSIONCODE); flavor.versionName = VERSIONNAME; flavor.applicationId = "com.example.huangcl.manychannel_wandoujia" } else if (flavor.name.equals("manychannel_sanliuling")) { flavor.versionCode = Integer.valueOf(VERSIONCODE); flavor.versionName = VERSIONNAME; flavor.applicationId = "com.example.huangcl.manychannel_sanliuling" } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile "com.android.support:appcompat-v7:$rootProject.ext.supportLibraryVersion" testCompile 'junit:junit:4.12' } -
gradle.properties
//混淆信息 PROGUARD_ANDROID=proguard-android.txt PROGUARD_RULES=proguard-rules.pro //版本信息 VERSIONCODE=1 VERSIONNAME=1.0.0 VERSIONCODE_DEV=2 VERSIONNAME_DEV=1.1.0 //友盟(值亂填的) UMENG_APPKEY=fdsgdffdfhsjfhdsifbdhjsf //渠道信息 CHANNEL_DEBUG=debug CHANNEL_DEBUG_NAME="測試版本" CHANNEL_FIRIM=fir.im CHANNEL_FIRIM_NAME="fir版本" CHANNEL_WANDOUJIA=wandoujia.com CHANNEL_WANDOUJIA_NAME="豌豆莢版本" CHANNEL_SANLIULING=zhushou.# CHANNEL_SANLIULING_NAME="360版本" //簽名配置信息(都不是秘密) KEYALIAS=hcl KEYPASSWORD=hs19931010 STOREFILE=./hcl.jks STOREPASSWORD=hs19931010
結(jié)果
- 同一手機(jī)
-
不同顯示
測試版
fir版
豌豆莢版

360版
