1. 程式人生 > >Android Studio - 第四十五期 Gradle manifestPlaceholders

Android Studio - 第四十五期 Gradle manifestPlaceholders

android manifestplaceholders

最近在學習擼擼的代碼規範和寫法,有些心得,準備好好寫一寫~包括了多渠道打版(以前有寫過方法),工廠模式,mvp,以及最近剛封裝出來的多渠道多版本展示不同頁面的manifestPlaceholders的配置方法,大家應該也碰到過線上和線下環境的切換換地址,換私鑰的頭大問題,本篇就來解決這些問題。

先在androidmanifest文件配置一個節點,這裏以極光為例:

<meta-data
            android:name="JPUSH_APPKEY"
            android:value="${jush_appkey_value}" />

<meta-data
            android:name="SHOUCANG_CONFIG0"
            android:value="${SHOUCANG_CONFIG_VALUE0}" />

build.gradle:

buildTypes {
    release {
        //自定義buildconfig字段
        buildConfigField("boolean", "APP_ENV", "true")
        //指定簽名為release
        signingConfig signingConfig.release
        //是否開啟混淆
        minifyEnabled false
        proguardFiles getDefaultProguardFile(‘proguard-android.txt‘), ‘proguard-rules.pro‘
        //是否zip優化
        zipAlignEnabled true
        //刪除一些無用資源
        shrinkResources false
        //
        manifestPlaceholders = [
                "jush_appkey_value": "release key"
        ]

    }
    debug {
        //自定義buildconfig字段
        buildConfigField("boolean", "APP_ENV", "true")
        //指定簽名為release
        signingConfig signingConfig.release
        //是否開啟混淆
        minifyEnabled false
        proguardFiles getDefaultProguardFile(‘proguard-android.txt‘), ‘proguard-rules.pro‘
        //是否zip優化
        zipAlignEnabled true
        //刪除一些無用資源
        shrinkResources false
        //
        manifestPlaceholders = [
                "jush_appkey_value": "debug key"
        ]
    }
}

在bulidtypes節點下有release節點和debug節點,正式簽名時就會走release節點的下編譯腳本,調試簽名時就會走debug節點。主要點就是manifestPlaceholders的用法,jpush_appkey對應的就是之前在androidmanifest文件配置的${jush_appkey_value}的這個值。

在程序入口出打上log,用來輸出key的值:

/**
 * 在程序入口出打上log,用來輸出key的值bufen
 */
private void jpush_key_manifest_xml_string() {
    String jpush_appkey;
    try {
        ApplicationInfo appInfo = getPackageManager()
                .getApplicationInfo(getPackageName(),
                        PackageManager.GET_META_DATA);

        jpush_appkey = appInfo.metaData.getString("JPUSH_APPKEY");

        Log.e("jpush_appkey", "jpush_appkey=" + jpush_appkey);
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();

    }
}

接下來給大家介紹多版本多頁面多apk的配置切換方法:舉個例子:如果你要一次性打七個版本,而且七個版本都是不同的頁面,但是頁面各個模塊大體一樣,只是順序和大小不同,你要怎麽做,別告訴我寫七個頁面分別打版哈~太low了~you know~這裏就利用多版本打版和manifestPlaceholders來實現需求。

首先是build.gradle:

apply plugin: ‘com.android.application‘
apply plugin: ‘android-apt‘


def demo = ‘0000‘;//DemoAPK
def demo1 = ‘0001‘;//DemoAPK1
def demo2 = ‘0002‘;//DemoAPK2
def demo3 = ‘0003‘;//DemoAPK3
def demo4 = ‘0004‘;//DemoAPK4
def demo5 = ‘0005‘;//DemoAPK5
def demo6 = ‘0006‘;//DemoAPK6


android {

    signingConfigs {
        debug {
            keyAlias ‘****‘
            keyPassword ‘****‘
            storeFile file(‘簽名文件.jks路徑‘)
            storePassword ‘****‘
        }
        release {
            keyAlias ‘****‘
            keyPassword ‘****‘
            storeFile file(‘簽名文件.jks路徑‘)
            storePassword ‘****‘
        }
    }

    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    sourceSets {
        main {
            jniLibs.srcDirs = [‘libs‘]
        }
    }

    packagingOptions {
        exclude ‘META-INF/DEPENDENCIES‘
        exclude ‘META-INF/NOTICE‘
        exclude ‘META-INF/LICENSE‘
        exclude ‘META-INF/LICENSE.txt‘
        exclude ‘META-INF/NOTICE.txt‘
    }

    defaultConfig {
        applicationId "com.shining.p010_recycleviewall"
        minSdkVersion 18
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"

        multiDexEnabled true
        renderscriptTargetApi 19
        renderscriptSupportModeEnabled true
        ndk {
            moduleName "native-modbus-jni,libxmediaplayer"
            ldLibs "log", "z", "m", "android", "c"
            abiFilters "armeabi", "armeabi-v7a", "x86"
        }
        sourceSets.main {
            jni.srcDirs = []
            //LOCAL_LDFLAGS += -fuse-ld=bfd
            //jni.srcDirs ‘src/main/jni‘
            jniLibs.srcDir ‘src/main/libs‘

        }
        signingConfig signingConfigs.debug

        manifestPlaceholders = [
                SHOUCANG_CONFIG_VALUE0: ".shoucang.factorys.ShoucangFactory0"
        ]

    }
    buildTypes {
        release {
            minifyEnabled true
            zipAlignEnabled true
            shrinkResources false
            proguardFiles getDefaultProguardFile(‘proguard-android.txt‘), ‘proguard-rules.pro‘
            signingConfig signingConfigs.debug

        }
    }

    def int minSdk = 18;
    def int targetSdk = 23;
    def String appId = ‘com.shining.p010_recycleviewall‘;

    def int vCode = 1;
    def String vNameCode = vCode + "";

    productFlavors {
        //demo
        DemoAPK {
            minSdkVersion minSdk
            applicationId appId
            targetSdkVersion targetSdk
            versionCode vCode
            versionName "DemoAPK_" + "T_" + demo
            multiDexEnabled true
            renderscriptTargetApi 19
            renderscriptSupportModeEnabled true
            ndk {
                moduleName "native-modbus-jni,libxmediaplayer"
                ldLibs "log", "z", "m", "android", "c"
                abiFilters "armeabi", "armeabi-v7a", "x86"
            }
            sourceSets.main {
                jni.srcDirs = []
                jniLibs.srcDir ‘src/main/libs‘
            }
            signingConfig signingConfigs.debug
        }
        //demo1
        DemoAPK1 {
            minSdkVersion minSdk
            applicationId appId
            targetSdkVersion targetSdk
            versionCode vCode
            versionName "DemoAPK1_" + "T_" + demo1
            multiDexEnabled true
            renderscriptTargetApi 19
            renderscriptSupportModeEnabled true
            ndk {
                moduleName "native-modbus-jni,libxmediaplayer"
                ldLibs "log", "z", "m", "android", "c"
                abiFilters "armeabi", "armeabi-v7a", "x86"
            }
            sourceSets.main {
                jni.srcDirs = []
                jniLibs.srcDir ‘src/main/libs‘
            }
            signingConfig signingConfigs.debug
        }
        //demo2
        DemoAPK2 {
            minSdkVersion minSdk
            applicationId appId
            targetSdkVersion targetSdk
            versionCode vCode
            versionName "DemoAPK2_" + "T_" + demo2
            multiDexEnabled true
            renderscriptTargetApi 19
            renderscriptSupportModeEnabled true
            ndk {
                moduleName "native-modbus-jni,libxmediaplayer"
                ldLibs "log", "z", "m", "android", "c"
                abiFilters "armeabi", "armeabi-v7a", "x86"
            }
            sourceSets.main {
                jni.srcDirs = []
                jniLibs.srcDir ‘src/main/libs‘
            }
            signingConfig signingConfigs.debug
        }
        //demo3
        DemoAPK3 {
            minSdkVersion minSdk
            applicationId appId
            targetSdkVersion targetSdk
            versionCode vCode
            versionName "DemoAPK3_" + "T_" + demo3
            multiDexEnabled true
            renderscriptTargetApi 19
            renderscriptSupportModeEnabled true
            ndk {
                moduleName "native-modbus-jni,libxmediaplayer"
                ldLibs "log", "z", "m", "android", "c"
                abiFilters "armeabi", "armeabi-v7a", "x86"
            }
            sourceSets.main {
                jni.srcDirs = []
                jniLibs.srcDir ‘src/main/libs‘
            }
            signingConfig signingConfigs.debug
        }
        //demo4
        DemoAPK4 {
            minSdkVersion minSdk
            applicationId appId
            targetSdkVersion targetSdk
            versionCode vCode
            versionName "DemoAPK4_" + "T_" + demo4
            multiDexEnabled true
            renderscriptTargetApi 19
            renderscriptSupportModeEnabled true
            ndk {
                moduleName "native-modbus-jni,libxmediaplayer"
                ldLibs "log", "z", "m", "android", "c"
                abiFilters "armeabi", "armeabi-v7a", "x86"
            }
            sourceSets.main {
                jni.srcDirs = []
                jniLibs.srcDir ‘src/main/libs‘
            }
            signingConfig signingConfigs.debug
        }
        //demo5
        DemoAPK5 {
            minSdkVersion minSdk
            applicationId appId
            targetSdkVersion targetSdk
            versionCode vCode
            versionName "DemoAPK5_" + "T_" + demo5
            multiDexEnabled true
            renderscriptTargetApi 19
            renderscriptSupportModeEnabled true
            ndk {
                moduleName "native-modbus-jni,libxmediaplayer"
                ldLibs "log", "z", "m", "android", "c"
                abiFilters "armeabi", "armeabi-v7a", "x86"
            }
            sourceSets.main {
                jni.srcDirs = []
                jniLibs.srcDir ‘src/main/libs‘
            }
            signingConfig signingConfigs.debug
        }
        //demo6
        DemoAPK6 {
            minSdkVersion minSdk
            applicationId appId
            targetSdkVersion targetSdk
            versionCode vCode
            versionName "DemoAPK6_" + "D_" + demo6
            multiDexEnabled true
            renderscriptTargetApi 19
            renderscriptSupportModeEnabled true
            ndk {
                moduleName "native-modbus-jni,libxmediaplayer"
                ldLibs "log", "z", "m", "android", "c"
                abiFilters "armeabi", "armeabi-v7a", "x86"
            }
            sourceSets.main {
                jni.srcDirs = []
                jniLibs.srcDir ‘src/main/libs‘
            }
            signingConfig signingConfigs.debug
        }
    }

    // 自定義輸出配置
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def outputFile = output.outputFile
            if (outputFile != null && outputFile.name.endsWith(‘.apk‘)) {
//                def fileName = "UerbT_v${variant.versionName}_${releaseTime()}_${variant.flavorName}.apk"
                def fileName = "${variant.versionName}.apk"
                output.outputFile = new File(outputFile.parent, fileName)
            }
        }
    }

    productFlavors.all { flavor ->
        def currentMode = flavor.versionName.split("_")[2]
        def currentEnvironment = flavor.versionName.split("_")[1]
        def stValue = true
        // t == currentEnvironment 以前的判斷條件
        if (currentEnvironment.endsWith("T")) {//判斷是否為測試版 是否以T結尾
            stValue = false
        } else {
            stValue = true
        }
        if (currentMode == demo) {
            flavor.manifestPlaceholders = [SHOUCANG_CONFIG_VALUE: ".shoucang.factorys.ShoucangFactory", STATISTICS_VALUE: stValue]
        } else if (currentMode == demo1) {
            flavor.manifestPlaceholders = [SHOUCANG_CONFIG_VALUE: ".shoucang.factorys.ShoucangFactory1", STATISTICS_VALUE: stValue]
        } else if (currentMode == demo2) {
            flavor.manifestPlaceholders = [SHOUCANG_CONFIG_VALUE: ".shoucang.factorys.ShoucangFactory2", STATISTICS_VALUE: stValue]
        } else if (currentMode == demo3) {
            flavor.manifestPlaceholders = [SHOUCANG_CONFIG_VALUE: ".shoucang.factorys.ShoucangFactory3", STATISTICS_VALUE: stValue]
        } else if (currentMode == demo4) {
            flavor.manifestPlaceholders = [SHOUCANG_CONFIG_VALUE: ".shoucang.factorys.ShoucangFactory4", STATISTICS_VALUE: stValue]
        } else if (currentMode == demo5) {
            flavor.manifestPlaceholders = [SHOUCANG_CONFIG_VALUE: ".shoucang.factorys.ShoucangFactory5", STATISTICS_VALUE: stValue]
        } else if (currentMode == demo6) {
            flavor.manifestPlaceholders = [SHOUCANG_CONFIG_VALUE: ".shoucang.factorys.ShoucangFactory6", STATISTICS_VALUE: stValue]
        }

    }


}

dependencies {
    compile fileTree(include: [‘*.jar‘], dir: ‘libs‘)
    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:25.3.0‘
    compile ‘com.android.support:recyclerview-v7:25.3.0‘
    compile ‘com.android.support:design:25.3.0‘
    compile ‘com.android.support:cardview-v7:25.3.0‘
    // local jar file
    compile files(‘libs/alipay-sdk-java20161226110022.jar‘)
    compile files(‘libs/alipay-sdk-java20161226110022-source.jar‘)
    compile files(‘libs/commons-logging-1.1.1.jar‘)
    compile files(‘libs/commons-logging-1.1.1-sources.jar‘)
    //the third file
    compile ‘com.jakewharton:butterknife:8.2.1‘
    apt ‘com.jakewharton:butterknife-compiler:8.2.1‘
    testCompile ‘junit:junit:4.12‘
    compile ‘com.geeklx:library_hios:1.0.4‘

    compile project(‘:glin‘)
    compile ‘com.github.bumptech.glide:glide:3.7.0‘
    compile ‘com.alibaba:fastjson:1.2.17‘
    compile ‘com.squareup.okio:okio:1.9.0‘
    compile ‘com.squareup.okhttp3:okhttp:3.4.1‘
    compile ‘com.nineoldandroids:library:2.4.0‘
    compile files(‘libs/libammsdk.jar‘)


}

接著就是多版本的代碼判斷書寫:

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        //TODO 多版本切換 寫此方法bufen
        which_version();
//        ShoucangConfig0.config();//manifestPlaceholders的妙用
        super.onCreate(savedInstanceState);
    }
    
    
    private void which_version() {
    if (ConstantNetUtil.VERSION_APK == NetConfig.version_name0) {
        ShoucangConfig.config();
    } else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name1) {
        ShoucangConfig1.config();
    } else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name2) {
        ShoucangConfig2.config();
    } else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name3) {
        ShoucangConfig3.config();
    } else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name4) {
        ShoucangConfig4.config();
    } else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name5) {
        ShoucangConfig5.config();
    } else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name6) {
        ShoucangConfig6.config();
    }
}

    //TODO 多版本模式bufen
SparseArrayCompat<Class<? extends BaseFragment>> array = which_version_fragment_config();//demo

    private SparseArrayCompat<Class<? extends BaseFragment>> which_version_fragment_config() {
    if (ConstantNetUtil.VERSION_APK == NetConfig.version_name0) {
        return ShoucangConfig.getFragments();
    } else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name1) {
        return ShoucangConfig1.getFragments();
    } else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name2) {
        return ShoucangConfig2.getFragments();
    } else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name3) {
        return ShoucangConfig3.getFragments();
    } else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name4) {
        return ShoucangConfig4.getFragments();
    } else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name5) {
        return ShoucangConfig5.getFragments();
    } else if (ConstantNetUtil.VERSION_APK == NetConfig.version_name6) {
        return ShoucangConfig6.getFragments();
    }
    return ShoucangConfig.getFragments();
}

這樣跑完apk你會發現會有神奇的事情發生,如下圖:(不同的apk版本出來的頁面也是不同的,但是只用了一份代碼。)

圖1:

技術分享

圖2:

技術分享

這樣做的好處在於,如果你的apk版本很多,需要給很多合作廠商提供定制化頁面,就可以用上了~

臥槽,今天噴了好多,希望大家回去自己細化一下,能幫到你~

技術分享

地址:https://github.com/geeklx/MyApplication/tree/master/p027_daojishi_manifestPlaceholders


本文出自 “梁肖技術中心” 博客,請務必保留此出處http://liangxiao.blog.51cto.com/3626612/1951381

Android Studio - 第四十五期 Gradle manifestPlaceholders