Android Studio Gradle多渠道打包(动态设定App名称,应用图标,背景图片,状态栏颜色)、配置签名文件

动态设定App名称,应用图标

Module设置

build.gradle文件

apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"

    defaultConfig {
        applicationId "com.xuewei"
        minSdkVersion 17
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    /**
    * 多渠道配置:动态设定App名称,应用图标,背景图片,状态栏颜色。
     * 1.applicationId不一致,避免了覆盖安装;
     * 2.针对不同的商家 App名称,图标得使用manifestPlaceholders,manifestPlaceholders是一个类似HashMap的容器;
     *
     *
     */
    productFlavors{
        /**
         * QQ应用宝
         * http://open.qq.com/
         */
        QQ{
            applicationId "com.xuewei.qq"
            manifestPlaceholders=[app_name:"高清图解.穴位",icon:"@mipmap/logo"]
        }
        /**
         * 360手机助手
         * http://dev.360.cn/
         */
        _360{
            applicationId "com.xuewei.360"
            manifestPlaceholders=[app_name:"高清图解.穴位",icon:"@mipmap/logo"]
        }
        /**
         * 小米应用商店开发者平台
         * http://dev.xiaomi.com/console/
         */
        XIAOMI{
            applicationId "com.xuewei.xiaomi"
            manifestPlaceholders=[app_name:"高清图解.穴位",icon:"@mipmap/logo"]
        }
        /**
         * 百度-百度手机助手
         * http://app.baidu.com/serve/
         */
        BAIDU_ZHUSHO{
            applicationId "com.xuewei.baiduzs"
            manifestPlaceholders=[app_name:"高清图解.穴位",icon:"@mipmap/logo"]
        }
        /**
         * 百度-91市场
         * http://app.baidu.com/serve/
         */
        BAIDU_91{
            applicationId "com.xuewei.baidu91"
            manifestPlaceholders=[app_name:"高清图解.穴位",icon:"@mipmap/logo"]
        }
        /**
         * 百度-android市场
         * http://app.baidu.com/serve/
         */
        BAIDU_ANDROID{
            applicationId "com.xuewei.baiduandroid"
            manifestPlaceholders=[app_name:"高清图解.穴位",icon:"@mipmap/logo"]
        }
   }
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

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.2.0'
    compile 'com.android.support:design:25.2.0'
    compile 'com.android.support:cardview-v7:25.2.0'
    compile 'com.android.support:support-v4:25.2.0'
}

关键代码:

defaultConfig{} 默认配置,是ProductFlavor类型。它共享给其他ProductFlavor使用

 productFlavors{
    ...
 }

AndroidManifest.xml

在清单文件里,通过 ${icon},${app_name} 引用module中build.gradle文件的manifestPlaceholders 容器中设置 icon , app_name等值。


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.xuewei">

    <application
        android:name=".XWApplication"
        android:allowBackup="true"
        android:icon="${icon}"
        android:label="${app_name}"
        android:roundIcon="${icon}"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        
        <meta-data
            android:name="app_name"
            android:value="${app_name}"/>
        <meta-data
            android:name="icon"
            android:value="${icon}"/>
        <activity
            android:name=".activity.SplashActivity"
            android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout"
            android:label="@string/app_name"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

manifest>

关键代码:

    "${icon}"
        android:label="${app_name}"
        android:roundIcon="${icon}">
        "app_name"
            android:value="${app_name}"/>
        "icon"
            android:value="${icon}"/>
    

动态设定背景图片,状态栏颜色

和动态设定App名称、应用图标,基本一样,这里唯一不同的就是,需要在代码里获取manifestPlaceholders设置的值,进行动态改变。

注意:新增的配置同样需要在清单文件中添加 meta-data节点。

       data
            android:name="welcome_bg"
            android:value="${welcome_bg}"/>

        data
            android:name="tint_color"
            android:value="${tint_color}"/>

        data
            android:name="load_url"
            android:value="${load_url}"/>

通过 Java 代码获取到 meta-data节点下 Android:value的值。

一般在 MyApplication 获取节点的值:

    ApplicationInfo info = null;
    try {
        info = this.getPackageManager().getApplicationInfo(getPackageName(), PackageManager
                .GET_META_DATA);
        int tintColor = info.metaData.getInt("tint_color");
        String loadUrl=info.metaData.getString("load_url");
        String welcomePath = info.metaData.getString("welcome_bg");

    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }

注意:设置welcome_bg:”@mipmap/klg_welcome”,我这里以int welcomeRes = info.metaData.getInt(“welcome_bg”);去取值,每次都返回0,但tint_color的值就正常。按正常思维@mipmap/klg_welcome返回的是 int 值,后来我换成getString还真获取到了值:res/mipmap-hdpi-v4/sjyg_welcome.png。获取到路径值,背景的图片资源就不能直接使用。

那么我们把路径资源转换成int资源,这里就用到了 Java 的反射。具体代码如下:

   Class c = R.mipmap.class;
    Field[] fields = c.getFields();
    for (Field field : fields) {
        if (field.getName().equals(welcomePath.substring(welcomePath.lastIndexOf("/") + 1,
                welcomePath.lastIndexOf(".")))) {
            this.welcomeBgRes = (int) field.get(c.newInstance());
            break;
        }
    }

还有一种方式在Java代码中可以方便获取到gradle配置文件的数据

    productFlavors{
    ...
        /**
         * QQ应用宝
         * http://open.qq.com/
         */
        QQ{
            applicationId "com.xuewei.qq"
            manifestPlaceholders=[app_name:"高清图解.穴位",icon:"@mipmap/logo"]
            resValue("string","key","123")
        }
        ...
   }

关键代码:

resValue("string","key","123")

通过代码:context.getResources().getString(R.string.key);获取值。

注意通过此方式 strings.xml 文件下不能有同名的 key 属性。不然会报相同资源引用错误。

生成APK和配置签名文件

生成所有渠道的包

Terminal命令输入如下指令:

gradlew assembleRelease

Android Studio Gradle多渠道打包(动态设定App名称,应用图标,背景图片,状态栏颜色)、配置签名文件_第1张图片
或者不使用命令
Android Studio Gradle多渠道打包(动态设定App名称,应用图标,背景图片,状态栏颜色)、配置签名文件_第2张图片
注意:*-unsigned.apk,都是没有签名的
我们需要在build.gradle配置签名文件

关键代码signingConfigs、buildTypes>release>signingConfig:

    signingConfigs {
        release {
            storeFile file("G:\\android\\signed\\xuewei\\xw.jks")
            storePassword "......"
            keyAlias "陈科肇"
            keyPassword "......"
            v2SigningEnabled true
        }
    }
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
        }
    }

Android Studio Gradle多渠道打包(动态设定App名称,应用图标,背景图片,状态栏颜色)、配置签名文件_第3张图片

签名文件配置成功

完整build.gradle文件

apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"

    defaultConfig {
        applicationId "com.xuewei"
        minSdkVersion 17
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    /**
    * 多渠道配置:动态设定App名称,应用图标,背景图片,状态栏颜色。
     * 1.applicationId不一致,避免了覆盖安装;
     * 2.针对不同的商家 App名称,图标得使用manifestPlaceholders,manifestPlaceholders是一个类似HashMap的容器;
     *
     *
     */
    productFlavors{
        /**
         * QQ应用宝
         * http://open.qq.com/
         */
        QQ{
            applicationId "com.xuewei.qq"
            manifestPlaceholders=[app_name:"高清图解.穴位",icon:"@mipmap/logo"]
            resValue("string","key","123")
        }
        /**
         * 360手机助手
         * http://dev.360.cn/
         */
        _360{
            applicationId "com.xuewei.360"
            manifestPlaceholders=[app_name:"高清图解.穴位",icon:"@mipmap/logo"]
        }
        /**
         * 小米应用商店开发者平台
         * http://dev.xiaomi.com/console/
         */
        XIAOMI{
            applicationId "com.xuewei.xiaomi"
            manifestPlaceholders=[app_name:"高清图解.穴位",icon:"@mipmap/logo"]
        }
        /**
         * 百度-百度手机助手
         * http://app.baidu.com/serve/
         */
        BAIDU_ZHUSHO{
            applicationId "com.xuewei.baiduzs"
            manifestPlaceholders=[app_name:"高清图解.穴位",icon:"@mipmap/logo"]
        }
        /**
         * 百度-91市场
         * http://app.baidu.com/serve/
         */
        BAIDU_91{
            applicationId "com.xuewei.baidu91"
            manifestPlaceholders=[app_name:"高清图解.穴位",icon:"@mipmap/logo"]
        }
        /**
         * 百度-android市场
         * http://app.baidu.com/serve/
         */
        BAIDU_ANDROID{
            applicationId "com.xuewei.baiduandroid"
            manifestPlaceholders=[app_name:"高清图解.穴位",icon:"@mipmap/logo"]
        }
   }
    signingConfigs {
        release {
            storeFile file("G:\\android\\signed\\xuewei\\xw.jks")
            storePassword "......"
            keyAlias "陈科肇"
            keyPassword "......"
            v2SigningEnabled true
        }
    }
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
        }
    }
}

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.2.0'
    compile 'com.android.support:design:25.2.0'
    compile 'com.android.support:cardview-v7:25.2.0'
    compile 'com.android.support:support-v4:25.2.0'
}

针对某个渠道打包

方式一:
Android Studio Gradle多渠道打包(动态设定App名称,应用图标,背景图片,状态栏颜色)、配置签名文件_第4张图片

方式二:
在defaultConfig配置manifestPlaceholders就可以。

问题

Android Studio Gradle多渠道打包(动态设定App名称,应用图标,背景图片,状态栏颜色)、配置签名文件_第5张图片

打包是成功,但同环境下不能安装多个多渠道打包(不同的applicationId)的apk。

不知道问题出在哪了,有人知道吗?


我们来看看Gradle Console打印的信息

E:\0Develop\work\gitHub\XueWei>gradlew assembleRelease
NDK is missing a "platforms" directory.ject > Resolving dependencies ':classpath'
If you are using NDK, verify the ndk.dir is set to a valid NDK directory.  It is currently set to I:\sdk\ndk-bundle.
If you are not using NDK, unset the NDK variable from ANDROID_NDK_HOME or local.properties to remove this warning.

Incremental java compilation is an incubating feature.
:app:preBuild UP-TO-DATE
...
...
...

大概意思是,我项目使用了ndk,而android studio还没配置ndk环境。

好,接下来,我们配置好ndk环境再试试。

ndk配置:file>Project Structure…>SDK Location>Android NDK location
Android Studio Gradle多渠道打包(动态设定App名称,应用图标,背景图片,状态栏颜色)、配置签名文件_第6张图片

还是一样,不行。

我猜可能是三方包引用引起的问题,因为我另一个项目,完全可以。

Android Studio Gradle多渠道打包(动态设定App名称,应用图标,背景图片,状态栏颜色)、配置签名文件_第7张图片

最后,暂时设置applicationId一致吧。同环境不能安装两个或以上。

问题原因

终于找到原因了,原来是集成了有米移动广告的sdk造成的。
Android Studio Gradle多渠道打包(动态设定App名称,应用图标,背景图片,状态栏颜色)、配置签名文件_第8张图片

这是我用他们的demo做的测试。


有米广告的sdk是没有问题的,问题是我没注意人家有的文档说明
Android Studio Gradle多渠道打包(动态设定App名称,应用图标,背景图片,状态栏颜色)、配置签名文件_第9张图片

对了,就是android:authorities这个属性,包名.fileProvider。

所以每个渠道包,也需要不同的android:authorities

然后,就可以愉快地玩耍了。

Android Studio Gradle多渠道打包(动态设定App名称,应用图标,背景图片,状态栏颜色)、配置签名文件_第10张图片

注意

applicationId 每段的命名不要以全是数字方式命名,否则会有问题的。
比如:applicationId=“com.xuewei.360”这个。

安装时,会报解析包时出现问题
Android Studio Gradle多渠道打包(动态设定App名称,应用图标,背景图片,状态栏颜色)、配置签名文件_第11张图片

最终的build.gradle、AndroidManifest.xml文件配置

build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"

    defaultConfig {
        applicationId "com.xuewei"
        minSdkVersion 17
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }


    /**
    * 多渠道配置:动态设定App名称,应用图标,背景图片,状态栏颜色。
     * 1.applicationId不一致,避免了覆盖安装;
     * 2.针对不同的商家 App名称,图标得使用manifestPlaceholders,manifestPlaceholders是一个类似HashMap的容器;
     * 3.defaultConfig{}    默认配置,是ProductFlavor类型。它共享给其他ProductFlavor使用;
     *
     *
     */
    productFlavors{
        /**
         * QQ应用宝
         * http://open.qq.com/
         */
        QQ{
            applicationId "com.xuewei.qq"
            manifestPlaceholders=[app_name:"高清图解.穴位",icon:"@mipmap/logo",umeng_channel:"umeng_channel_qq",youmi_channel:"youmi_channel_qq",authorities:"com.xuewei.qq.fileProvider"]
        }
        /**
         * 360手机助手
         * http://dev.360.cn/
         */
        S360{
            applicationId "com.xuewei.s360"
            manifestPlaceholders=[app_name:"高清图解.穴位",icon:"@mipmap/logo",umeng_channel:"umeng_channel_360",youmi_channel:"youmi_channel_360",authorities:"com.xuewei.360.fileProvider"]
        }
        /**
         * 小米应用商店开发者平台
         * http://dev.xiaomi.com/console/
         */
        XIAOMI{
            applicationId "com.xuewei.xiaomi"
            manifestPlaceholders=[app_name:"高清图解.穴位",icon:"@mipmap/logo",umeng_channel:"umeng_channel_xiaomi",youmi_channel:"youmi_channel_xiaomi",authorities:"com.xuewei.xiaomi.fileProvider"]
        }
        /**
         * 百度-百度手机助手
         * http://app.baidu.com/serve/
         */
        BAIDU_ZHUSHO{
            applicationId "com.xuewei.baiduzs"
            manifestPlaceholders=[app_name:"高清图解.穴位",icon:"@mipmap/logo",umeng_channel:"umeng_channel_baiduzs",youmi_channel:"youmi_channel_baiduzs",authorities:"com.xuewei.baiduzs.fileProvider"]
        }
        /**
         * 百度-91市场
         * http://app.baidu.com/serve/
         */
        BAIDU_91{
            applicationId "com.xuewei.baidu91"
            manifestPlaceholders=[app_name:"高清图解.穴位",icon:"@mipmap/logo",umeng_channel:"umeng_channel_baidu91",youmi_channel:"youmi_channel_baidu91",authorities:"com.xuewei.baidu91.fileProvider"]
        }
        /**
         * 百度-android市场
         * http://app.baidu.com/serve/
         */
        BAIDU_ANDROID{
            applicationId "com.xuewei.baiduandroid"
            manifestPlaceholders=[app_name:"高清图解.穴位",icon:"@mipmap/logo",umeng_channel:"umeng_channel_baiduandroid",youmi_channel:"youmi_channel_baiduandroid",authorities:"com.xuewei.baiduandroid.fileProvider"]
        }
   }

    signingConfigs {
        release {
            storeFile file("G:\\android\\signed\\xuewei\\xw.jks")
            storePassword "......"
            keyAlias "陈科肇"
            keyPassword "......"
            v2SigningEnabled true
        }
    }
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
        }
    }
}

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.2.0'
    compile 'com.android.support:design:25.2.0'
    compile 'com.android.support:cardview-v7:25.2.0'
    compile 'com.android.support:support-v4:25.2.0'
}

AndroidManifest.xml


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.xuewei">
    
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <application
        android:name=".XWApplication"
        android:allowBackup="true"
        android:icon="${icon}"
        android:label="${app_name}"
        android:roundIcon="${icon}"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        
        <meta-data
            android:name="app_name"
            android:value="${app_name}"/>
        <meta-data
            android:name="icon"
            android:value="${icon}"/>
        <meta-data
            android:name="youmi_channel"
            android:value="${youmi_channel}"/>
        <meta-data
            android:name="authorities"
            android:value="${authorities}"/>

        <meta-data
            android:name="design_width"
            android:value="1080" />
        <meta-data
            android:name="design_height"
            android:value="1920" />
        <meta-data
            android:name="UMENG_APPKEY"
            android:value="......" />
        <meta-data
            android:name="UMENG_CHANNEL"
            android:value="${umeng_channel}" />

        <activity android:name=".activity.MainActivity"/>
        <activity android:name=".activity.XWEffectActivity" />
        <activity android:name=".activity.HDMapActivity" />

        
        <activity
            android:name=".activity.SplashActivity"
            android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout"
            android:label="@string/app_name"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            intent-filter>
        activity>
        <activity
            android:name="net.youmi.android.AdBrowser"
            android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout"
            android:theme="@android:style/Theme.Light.NoTitleBar"/>

        <service
            android:name="net.youmi.android.AdService"
            android:exported="false"/>

        <receiver android:name="net.youmi.android.AdReceiver">
            <intent-filter>
                <action android:name="android.intent.action.PACKAGE_ADDED" />

                <data android:scheme="package" />
            intent-filter>
        receiver>

        
        
        
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${authorities}"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_provider" />
        provider>

        
        <meta-data
            android:name="YOUMI_CHANNEL"
            android:value="${youmi_channel}" >
        meta-data >
        
        <activity
            android:name="net.youmi.android.normal.video.VideoActivity"
            android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout"
            android:resizeableActivity="false"
            android:screenOrientation="landscape"
            android:taskAffinity=""
            android:theme="@android:style/Theme.NoTitleBar" >
        activity >
        
    application>

manifest>

参考:http://blog.csdn.net/u012551350/article/details/62041833

你可能感兴趣的:(Android)