【问题标题】:Android Studio: product flavor combination with more than two flavor dimensions (flavor groups)Android Studio:具有两个以上风味维度(风味组)的产品风味组合
【发布时间】:2016-08-29 13:28:37
【问题描述】:

我正在使用 Android Studio(v 2.1,gradle plugin v 2.1.0)开发一个 Android 应用程序。我的应用程序有各种版本,它们共享许多通用代码,因此我决定使用风味维度和产品风味来自定义代码和资源,何时何地需要。只要我只有两个风味维度,这就行了。例如,我的app.gradle

…
flavorDimensions "fruit", "color"

productFlavors {

    apple {
        dimension "fruit"
    }
    pear {
        dimension "fruit"
    }

    red {
        dimension "color"
    }
    yellow {
        dimension "color"
    }
}
…

我的src 文件夹是

src/
    appleRed/
    appleYellow/
    pearRed/
    pearYellow/

每个都有我的代码的自定义版本。再举个例子

src/
    appleRed/java/com/example/ExampleFragment.java
    appleYellow/java/com/example/ExampleFragment.java
    pearRed/java/com/example/ExampleFragment.java
    pearYellow/java/com/example/ExampleFragment.java

当然,src/main 中没有 ExampleFragment 的实例。

在开发过程中的某个时候,我不得不包含一个免费和一个付费版本的应用程序。我认为可以通过添加一个名为version 的新风味维度和两个名为freepaid 的产品风味来轻松实现:

 …
flavorDimensions "fruit", "color”, “version”

productFlavors {

    apple {
        dimension "fruit"
    }
    pear {
        dimension "fruit"
    }

    red {
        dimension "color"
    }
    yellow {
        dimension "color"
    }

    free {
        dimension "version"
    }
    paid {
        dimension “version”
    }
}
…

但是突然之间,由fruitcolor 组合生成的自定义代码不再被Android Studio 检测到。因此,appleRedappleYellowpearRedpearYellow 都不能用于自定义代码,而我能够重新获得配置的唯一方法是使用所有三个风味维度的所有组合:

  src/
      appleRedFree/java/com/example/ExampleFragment.java
      appleRedPaid/java/com/example/ExampleFragment.java
      appleYellowFree/java/com/example/ExampleFragment.java
      appleYellowPaid/java/com/example/ExampleFragment.java
      pearRedFree/java/com/example/ExampleFragment.java
      pearRedPaid/java/com/example/ExampleFragment.java
      pearYellowFree/java/com/example/ExampleFragment.java
      pearYellowPaid/java/com/example/ExampleFragment.java

这不好,因为ExampleFragment 在相同的fruitColor* 组合中重复(appleRedFreeappleRedPaid 具有相同的ExampleFragment)。资源(res 文件夹中的资源)也会出现同样的问题。

我的问题是:

1) 这是 Android Studio 中 gradle 的预期行为吗(ie,当具有两种以上的风味时,无法组合产品风味的子集,根据它们的维度遵循它们的优先级尺寸)?

2) 鉴于这是预期的行为,有没有另一种方法可以实现我的自定义,而无需重复代码或没有一个包含 if 语句 的单个文件(例如if (BuildConfig.FLAVOR_version == "free") ...) ?

请注意,我所说的自定义代码可能很复杂,因此我并不是要求进行基本的自定义,例如构建配置变量、变体过滤或类似的东西。

【问题讨论】:

    标签: android android-studio android-gradle-plugin android-productflavors android-flavordimension


    【解决方案1】:

    您想为某些口味使用相同的额外源目录;

    appleRedFree + appleRedPaid --> src/appleRed
    pearRedFree + pearRedPaid --> src/pearRed
    appleYellowFree + appleYellowPaid --> src/appleYellow
    pearYellowFree + pearYellowPaid --> src/pearYellow

    您可以根据自己的喜好设置sourceSet

    android {
    
        // Other stuff here
    
        flavorDimensions "fruit", "color”, “version”
    
        productFlavors {
    
            apple {
                dimension "fruit"
            }
            pear {
                dimension "fruit"
            }
    
            red {
                dimension "color"
            }
            yellow {
                dimension "color"
            }
    
            free {
                dimension "version"
            }
            paid {
                dimension “version”
            }
        }
    
        sourceSets {
            appleRedFree {
                java.srcDirs = ['src/main/java', 'src/appleRed/java']
            }
    
            appleRedPaid {
                java.srcDirs = ['src/main/java', 'src/appleRed/java']
            }
    
            appleYellowFree {
                java.srcDirs = ['src/main/java', 'src/appleYellow/java']
            }
    
            appleYellowPaid {
                java.srcDirs = ['src/main/java', 'src/appleYellow/java']
            }
    
            pearRedFree {
                java.srcDirs = ['src/main/java', 'src/pearRed/java']
            }
    
            pearRedPaid {
                java.srcDirs = ['src/main/java', 'src/pearRed/java']
            }
    
            pearYellowFree {
                java.srcDirs = ['src/main/java', 'src/pearYellow/java']
            }
    
            pearYellowPaid {
                java.srcDirs = ['src/main/java', 'src/pearYellow/java']
            }
        }
    
       // Other stuff here
    }
    

    【讨论】:

    • 不起作用。 Gradle 项目同步失败并出现错误:Error:(46, 0) Could not find method appleRedFree() for arguments [build_5p3mtjx0cpg9la7ms46x7bgzz$_run_closure2$_closure8@5d22a1be] on AndroidSourceSet container. 您是否忘记在某处包含apply plugin
    • @Vangaorth 我已经更新了我的答案。
    • 现在可以了!您还必须使用最新的(在撰写本文时)Gradle Android 插件 (2.3.0) 和 Gradle (3.3)。因此,在 Android Studio 中,文件 -> 项目结构 -> 项目选项卡,Gradle 版本为 3.3,Android 插件版本为 2.3.0
    • 如何为每种风味设置 resvalue?
    • @roghayehhosseini 只需使用 pearYellowPaid.res.srcDirs += 'src/pearYellow/res`
    【解决方案2】:

    我有一点改进,因为我真的不喜欢复制/粘贴 src 集:)

    所以你可以这样做:

    android {
        …
        applicationVariants.all { variant ->
            def flavors = variant.productFlavors
            def fruit = flavors[0].name
            def color = flavors[1].name
            def version = flavors[2].name
    
            def fruitColorSrcSet = fruit + color.capitalize()
            def srcSet = fruitColorSrcSet + version.capitalize()
            android.sourceSets."$srcSet".java.srcDirs += "src/$fruitColorSrcSet/java"
        }
    }
    

    我尚未对其进行测试,但它基于我当前的实现,另外还有 variant.buildType.name 用法


    附录-设置资源目录使用

    android.sourceSets."$srcSet".res.srcDirs = "src/$fruitColorSrcSet/res"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-10
      • 1970-01-01
      • 2013-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多