LoginSignup
1
1

More than 5 years have passed since last update.

【InstantApps】Feature moduleでprotobufが参照出来ない

Last updated at Posted at 2018-04-03

InstantApps対応をするにはmulti module化は必須である。
実はprotobufのpluginも最近InstantAppsに対応したばっかりなので、まだまだハマリポイントは多い。

1moduleなら問題はないのだが、複数のfeature moduleでprotobufを使うと
generatedのdirectoryが解決出来なくなってしまうので、gradle側でdirectoryを追加してあげる必要がある。
しかし面倒なことにgeneratedのdirectoryは、flavorとbuild typeによってpathが異なる。
1つのflavorでもdebug buildとrelease buildがあるだろうから対応は必須となる。

普通なら以下のようにapplicationVariantsを使って指定したいが

applicationVariants.all { variant ->

}

このコードはfeature moduleからは使えない。

そこで、各flavorとbuild type一覧を取得して指定してみる


sourceSets {
    def buildTypes = android.buildTypes.collect { type -> type.name }
    def productFlavors = android.productFlavors.collect { flavor -> flavor.name }

    productFlavors.each { productFlavorName ->
        buildTypes.each { buildTypeName ->
            // Create variant and target names
            def targetName = "${productFlavorName}${buildTypeName.capitalize()}"
            main.java.srcDirs += "build/generated/source/proto/${targetName}/grpc"
            main.java.srcDirs += "build/generated/source/proto/${targetName}/javalite"
        }
    }
}

しかし、これも動作はしない。
なぜなら、srcDirに他のbuildで作成したファイルも参照してしまうので、同じクラスが重複してしまう。
毎回cleanすれば良いのだが、そんな面倒な事をしたくはない…

ということで、泥臭くtaskから現在のflavorとbuild typeを取得してやることにした。
以下のメソッドを作成


/**
 * @return flavor + build type
 * e.g. prdRelease, devDebug
 */
def getCurrentTaskName() {
    String taskName = getGradle().getStartParameter().getTaskRequests().toString()
    Pattern pattern
    if (taskName.contains("assemble")) {
        pattern = Pattern.compile("assemble(\\w+)")
    } else if(taskName.contains("sideLoad")) {
        pattern = Pattern.compile("sideLoad(\\w+)InstantApp")
    } else if(taskName.contains("install")) {
        pattern = Pattern.compile("install(\\w+)")
    } else {
        pattern = Pattern.compile("generate(\\w+)")
    }

    Matcher matcher = pattern.matcher(taskName)
    if (matcher.find()) {
        return matcher.group(1).uncapitalize()
    } else {
        return "" // Not found
    }
}

gradleのtaskから正規表現でflavorとbuild typeを取ってきている。
sideLoad(\\w+)InstantAppというtaskは普段は見慣れないとは思うが、
InstantAppsのinstallを行ってくれるtaskである。

例えば、flavorがDev環境でbuild typeがDebugの時の
Installedのアプリのtask名は assembleDevDebugである。
InstantAppsのtask名は sideLoadDevDebugInstantAppsになる。
正規表現で取得した文字列は、そのままだとDevDebugのようになってしまうので、uncapitalized()で先頭を小文字にしている。
あとはsource setsにdirectoryを指定してあげれば良い


sourceSets {
        def targetName = getCurrentTaskName()
        main.java.srcDirs += "build/generated/source/proto/${targetName}/grpc"
        main.java.srcDirs += "build/generated/source/proto/${targetName}/javalite"
}
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1