android系統(tǒng)應(yīng)用的平臺(tái)化開發(fā),一種開發(fā)思路,旨在方便平臺(tái)開發(fā)。
在android操作系統(tǒng)中,源碼編譯生成app,加入帶系統(tǒng)簽名的app,這些應(yīng)用都帶有系統(tǒng)權(quán)限,統(tǒng)一放在了system/app或者system/priv-app目錄下??梢哉f(shuō)這類應(yīng)用的開發(fā)相對(duì)獨(dú)立且功能有一致性的,最大的區(qū)別還是UI是多變的。
平臺(tái)化的開發(fā)就是可以把開發(fā)的應(yīng)用放在不同的android 平臺(tái)下,同時(shí)兼容android不同版本。不同平臺(tái)當(dāng)然對(duì)應(yīng)不同項(xiàng)目,也對(duì)應(yīng)著不同的UI需求。雖然UI不同,但本質(zhì)是一樣的,都是某個(gè)應(yīng)用,功能一樣,底層邏輯基本不會(huì)變化太大,即使接口不同,也可以采取兼容的舉措,盡量繼承為一個(gè)通用的module。根據(jù)這種場(chǎng)景衍生出下面的開發(fā)方式。將應(yīng)用與底層(framework層或者驅(qū)動(dòng)層)交互的邏輯繼承在一個(gè)lib庫(kù)下,UI則統(tǒng)一在App的主Module開發(fā),可以在中間夾雜一層develp的module模塊進(jìn)行串聯(lián)lib和UI,來(lái)達(dá)到解耦或者多平臺(tái)兼容性的處理。同時(shí)可以封裝通用的base庫(kù),供各個(gè)應(yīng)用層依賴。下圖為大概的參考架構(gòu):

在不同的平臺(tái)下,framework適配了不同的修改,此時(shí)可以區(qū)分不同平臺(tái)的framework.jar,供應(yīng)用調(diào)用不同的接口。

首先需要在app的build.gradle下,配置多平臺(tái)的方式如下:
flavorDimensions("platform")
productFlavors {
platform1 {
dimension "platform"
buildConfigField "Integer", "PLATFORM", "1"
resValue "string", "platformType", "platform1"
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs.add("-Xbootclasspath/p:$rootProject.rootDir/syslibs/platform1/framework.jar")
}
}
}
platform2 {
dimension "platform"
buildConfigField "Integer", "PLATFORM", "2"
resValue "string", "platformType", "platform2"
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs.add("-Xbootclasspath/p:$rootProject.rootDir/syslibs/platform2/framework.jar")
}
}
}
platform3 {
dimension "platform"
buildConfigField "Integer", "PLATFORM", "3"
resValue "string", "platformType", "platform3"
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs.add("-Xbootclasspath/p:$rootProject.rootDir/syslibs/platform3/framework.jar")
}
}
}
其中配置了android studio編譯時(shí)不同平臺(tái)的framework.jar, 同時(shí)需要配置不同平臺(tái)的framework.jar依賴,jar包方式如下:
dependencies {
platform1CompileOnly files("$rootProject.rootDir/syslibs/platform1/framework.jar")
platform2CompileOnly files("$rootProject.rootDir/syslibs/platform2/framework.jar")
platform3CompileOnly files("$rootProject.rootDir/syslibs/platform3/framework.jar")
}
同理,其他的jar依賴也可通過上述方式配置區(qū)分不同平臺(tái)。
app簽名在不同平臺(tái)下是不一致的,此時(shí)需要配置不同的簽名,配置平臺(tái)簽名方式:
signingConfigs {
platform1 {
storeFile file(project.rootDir.absolutePath + "/sign/platform1/sign.jks")
storePassword "123456"
keyAlias "sign"
keyPassword "123456"
}
platform2 {
storeFile file(project.rootDir.absolutePath + "/sign/platform2/sign.jks")
storePassword "123456"
keyAlias "sign"
keyPassword "123456"
}
platform3 {
storeFile file(project.rootDir.absolutePath + "/sign/platform3/sign.jks")
storePassword "123456"
keyAlias "sign"
keyPassword "123456"
}
}
簽名路徑放在根目錄下的sign目錄下:

當(dāng)應(yīng)用還需區(qū)分一些權(quán)限申請(qǐng)、組件聲明時(shí),可以通過sourceSets區(qū)分平臺(tái)的AndroidManifest.xml文件。
sourceSets {
platform1 {
main {
manifest.srcFile 'src/main/platform1/AndroidManifest.xml'
}
}
platform2 {
main {
manifest.srcFile 'src/main/platform2/AndroidManifest.xml'
}
}
platform3 {
main {
manifest.srcFile 'src/main/platform3/AndroidManifest.xml'
}
}
}
之后可以通過Build Variants選項(xiàng)生成不同平臺(tái)的apk了。

在應(yīng)用代碼中需要區(qū)分平臺(tái)時(shí),可通過BuildConfig來(lái)獲取配置的平臺(tái)屬性。
int platform = BuildConfig.PLATFORM;
if (platform == 1) {
//Todo do something for platform1
Log.d(TAG, "current platform is 1");
} else if (platform == 2) {
//Todo do something for platform2
Log.d(TAG, "current platform is 2");
} else if (platform == 3) {
//Todo do something for platform3
Log.d(TAG, "current platform is 3");
}
上面的屬性為build.gradle的buildConfigField配置的Integer值當(dāng)然可以通過BuildConfig.FLAVOR來(lái)獲取當(dāng)前平臺(tái)的String值抑或通過其他手段如系統(tǒng)屬性獲取。
如果開發(fā)的應(yīng)用需要在源碼中編譯,則可根據(jù)源碼配置的屬性來(lái)區(qū)分不同平臺(tái),并編譯不同的模塊。
ifeq ($(PLATFORM_NAME), platform1)
LOCAL_MANIFEST_FILE := src/main/platform1/AndroidManifest.xml
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := syslibs/platform1/framework.jar
else ifeq ($(PLATFORM_NAME), platform2)
LOCAL_MANIFEST_FILE := src/main/platform2/AndroidManifest.xml
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := syslibs/platform2/framework.jar
else ifeq ($(PLATFORM_NAME), platform3)
LOCAL_MANIFEST_FILE := src/main/platform3/AndroidManifest.xml
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := syslibs/platform3/framework.jar
else
LOCAL_MANIFEST_FILE := src/main/AndroidManifest.xml
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := syslibs/framework.jar
endif
如上是一套系統(tǒng)平臺(tái)化開發(fā)的思路,可參考作為系統(tǒng)應(yīng)用開發(fā)的模式,當(dāng)然也有著千變?nèi)f化,可以定義適配自己項(xiàng)目的平臺(tái)化開發(fā)路線,后續(xù)將方便平臺(tái)遷移和提高應(yīng)用的開發(fā)效率。