如何按照构建类型和产品口味分割源代码

3

我有一个应用,对于debug/release两种buildTypes和两个productFlavors,它们有不同的包名。

我的build.gradle文件的有趣部分如下:

android {
    buildTypes {
        debug {
            packageNameSuffix ".debug"
        }

        release {
            signingConfig signingConfigs.release
        }
    }

    productFlavors {
        flavor1 {
            packageName "com.example.app.flavor1"
        }

        flavor2 {
            packageName "com.example.app.flavor2"
        }
}

因此,这里有四种软件包名称:

com.example.app.flavor1 com.example.app.flavor1.debug com.example.app.flavor2 com.example.app.flavor2.debug

代码是正确的。但是由于修改的软件包名称在合并清单时出现问题,我需要手动为每个有效的软件包设置一些东西,如GCM权限和内容提供者授权。

但我该怎么做呢? 无论我将 AndroidManifest.xml 放在 src/falvor{1,2} 或者 src/{debug,release} 中,我最终只得到两个配置。 我试过像 flavor1Debug 这样的东西,但没有成功。

1个回答

6

没有官方的方法来设置“flavorBuildType”(如flavor1Debug)组合的资源文件,因此您需要在这里进行一些小技巧。

首先定义AndroidManifest.xml的新路径:

project.ext.flavor1 = [
    debugManifest: 'src/flavor1Debug/AndroidManifest.xml',
    releaseManifest: 'src/flavor1Release/AndroidManifest.xml'
]

project.ext.flavor2 = [
    debugManifest: 'src/flavor2Debug/AndroidManifest.xml',
    releaseManifest: 'src/flavor2Release/AndroidManifest.xml'
]

其次,告诉Gradle在processManifest任务中使用新的AndroidManifest.xml。现在的问题是:sourceSet.manifest.srcFile是只读的,我们不能直接替换它。由于我们为每个风味(debug和release)使用不同的资源,因此我们可以将新的AndroidManifest.xml复制到原始风味文件夹中,Gradle将使用正确的设置构建APK文件。

android.applicationVariants.all { variant ->
    variant.processManifest.doFirst {
        if (project.ext.has(variant.productFlavors.name)) {
            if (project.ext[variant.productFlavors.name].debugManifest != null &&
                project.ext[variant.productFlavors.name].releaseManifest != null) {
                def manifestDirectory = android.sourceSets[variant.productFlavors.name].manifest.srcFile.parentFile
                if (variant.buildType.name.equals("debug")) {
                    copy {
                        from project.ext[variant.productFlavors.name].debugManifest
                        into manifestDirectory
                    }
                } else if (variant.buildType.name.equals("release")) {
                    copy {
                        from project.ext[variant.productFlavors.name].releaseManifest
                        into manifestDirectory
                    }
                }
            }
        }
    }

    variant.processManifest.doLast {
        if (project.ext.has(variant.productFlavors.name)) {
            project.delete android.sourceSets[variant.productFlavors.name].manifest.srcFile
        }
    }
}

至于AndroidManifest.xml文件,只需保留与GCM相关的设置:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.example.free.debug"
    android:versionCode="1"
    android:versionName="1.0" >

    <permission
        android:name="com.android.example.free.debug.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="com.android.example.free.debug.permission.C2D_MESSAGE" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

</manifest>

您可以在这里获取示例代码:https://github.com/shakalaca/learning_gradle_android/tree/master/07_tricks 它支持Google Maps API v2和GCM场景,但我认为只需进行轻微的代码更改即可支持内容提供程序。

看起来只有在单独构建调试和发布版本时才能正常工作。或者使用 gradle assemble 一次性构建所有内容也可以吗? - flx
是的,由于主要内容位于android.applicationVariants.all中,它将使用gradle assemble一次性处理所有内容 :) - shakalaca
processManifest已经移动: https://dev59.com/rV4d5IYBdhLWcg3wAedX - Yoel Gluschnaider

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接