Gradle实现编译差异

时间:2021-06-16 14:56:50

今天开发组长问了这么一个问题,如何实现通过gradle编译动态设置代码里的一些值。可能这么说不太明白,下面说依稀具体需求。

开发中有两个服务器:一个用于测试版本、一个用于线上版本发布,这两个服务器地址不同。现在想通过在编译版本的时候,不去手动更改服务器地址,而是编译测试版本时,代码中使用的地址就是测试服务地址,编译线上版本时,使用线上服务地址。如何实现? 实现原理和多渠道打包是一样的。下面展示代码:

(1) 在App的AndroidManifest.xml文件中Application节点下添加:

<meta-data
            android:name="DATA_NAME"
            android:value="${DATA_NAME_VALUE}" />

(2)在App的build.gradle文件中添加:

defaultConfig {
        applicationId "com.gradle.asdemo"
        versionCode Integer.parseInt(project.VERSION_CODE)
        versionName project.VERSION_NAME
        minSdkVersion Integer.parseInt(project.ANDROID_MIN_SDK)
        targetSdkVersion Integer.parseInt(project.ANDROID_TARGET_SDK_VERSION)
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        manifestPlaceholders = [DATA_NAME_VALUE: "http://www.mamami.com"] //设置默认的值
    }

    productFlavors {
        ol {
            manifestPlaceholders = [DATA_NAME_VALUE: "http://www.mamami.com"] //线上服务地址
        }
        test {
            manifestPlaceholders = [DATA_NAME_VALUE: "http://192.168.58.38"] //测试服务地址
        }
    }

 (3) 在代码中获取服务地址的值

public static String getAppMetaData(Context context, String meta_name) {
        try {
            ApplicationInfo appInfo = context.getPackageManager()
                    .getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
            return appInfo.metaData.getString(meta_name);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

public static String getHost(Context context) {
        String hostURL = getAppMetaData(context, "DATA_NAME");
        if (hostURL != null) {
            return hostURL;
        }

        return DEFUALT_HOST;
    }

  这样在编译时通过选择不同的Flavor就可以动态改变服务地址。这里说一下,在我们平时开发debug开发编译获取到的地址并不是默认值,而是好像在按照Flavor中设置的name的字典顺序拿到的。

(4)可能遇到的问题:Error:(74, 13) Attribute meta-data#xxx@value at AndroidManifest.xml:74:13 requires a placeholder substitution but no value for <YOUMI_CHANNEL_VALUE> is provided

Gradle实现编译差异

解决方案:(两处取证说明正确)——其实我遇到这个问题不是这个原因,这是意外收获。后续我会说明我的那种情况造成这个问题的原因

http://www.tuicool.com/articles/BRNfeiU

http://*.com/questions/37368124/gradle-manifest-requires-a-placeholder-substitution-error-but-manifestplacehol

(5)拓展:

  使用manifestPlaceholders的这种配置,同样适用于manifest的其他配置。比如你需要在不同渠道发布的apk里面,指定不同的启动Activity。比如在豌豆荚里面发布的,启动的Activity显示的是豌豆荚首发的界面,应用宝里面启动的是应用宝首发的界面,你就可以对你的activity的值使用${activity_name}的方式,然后在productFlavors里面配置这个${activity_name}的值。

 

(6)参考:

http://blog.csdn.net/mynameishuangshuai/article/details/51783303

http://blog.csdn.net/maosidiaoxian/article/details/42000913