web-dev-qa-db-ja.com

buildTypeに応じてリソースをGradleでオーバーライドする

Res/strings.xmlの一部の文字列をgradleで上書きしたい。

私は知っています Android Gradle Plugin 0.7。+ 以降、バリアント固有のソースフォルダを作成する可能性があります。しかし、私のアプリには多くのフレーバーがあり、さらにバリアント固有のフォルダを追加したい。

UPDATE 2014-01-17

私が詳細に欲しいもの:

私のリソースには、buildTypeだけに依存するいくつかの変数があります(「リリース」など)。最初に、SOLUTION_1(リソースがマージされた後のデータのオーバーライド)は素晴らしいと思いました。なぜなら、これらの変数を変更する必要がある場合は、 build.config(1か所のみ)。しかし、Scott Bartaが以下のコメントで書いたように、この解決策が良い考えではない理由がいくつかあります。

だから私は このシャカラカのGitHubプロジェクト に基づいて別の解決策SOLUTION_2(ちょうど適切なリソースをマージする)を試しました。この方法はよりエレガントで、oneの場所で変数を変更するだけの利点があります!

SOLUTION_1(リソースのマージ後にデータを上書き):

AS 0.4.2で私がしたこと:

  • build.gradle文字列 "Hello World"を "OVERRIDE"に上書きしようとします( この投稿での私の回答に基づいて ):

    Android.applicationVariants.all{ variant ->
        // override data in resource after merge task
        variant.processResources.doLast {
            overrideDataInResources(variant)
        }
    }
    
    def overrideDataInResources(buildVariant){
        copy {
            // *** SET COPY PATHS ***
            try {
                from("${buildDir}/res/all/${buildVariant.dirName}") {
                    // println "... FROM: ${buildDir}/res/all/${buildVariant.dirName}"
                    include "values/values.xml"
                }
            } catch (e) {
                println "... EXCEPTION: " + e
            }
    
            into("${buildDir}/res/all/${buildVariant.dirName}/values")
            // println "... INTO: ${buildDir}/res/all/${buildVariant.dirName}/values"
    
            // --- override string "hello_world"
            filter {
                String line ->
                    line.replaceAll("<string name=\"hello_world\">Hello world!</string>",
                            "<string name=\"hello_world\">OVERRIDE</string>");
            }
    
        // *** SET PATH TO NEW RES *** 
        buildVariant.processResources.resDir = file("${buildDir}/res/all/${buildVariant.dirName}/values/values/values.xml")
        // println "... NEW RES PATH: " + "${buildDir}/res/all/${buildVariant.dirName}/values/values/values.xml"
        }
    }
    

コピーとフィルターのタスクは正常に機能しますが、「新しい」values.xmlを文字列リソースとして設定できませんでした。

SOLUTION_2(適切なリソースをマージするだけ)

  • 特定のbuildTypeのフレーバーを定義します(例: "releaseRes")
  • このリソースを、作成したいフレーバーとマージします。

    Android.applicationVariants.all{ variant ->
        variant.mergeResources.doFirst{
            checkResourceFolder(variant)
        }
    }
    
    def checkResourceFolder(variant){
        def name = variant.name;
        if(name.contains("Release")){
           Android.sourceSets.release.res.srcDirs = ['src/releaseRes/res']
           Android.sourceSets.flavor1.res.srcDirs = ['src/flavor1/res']
        }
    }
    
23
owe

ビルドファイルにカスタムコードを書くことを含まないソリューションを考え出すように努力する必要があります。特に、ソースセットをオンザフライで再割り当てすることでトリッキーなことを行うコードを作成する必要があります。カスタムGradleコードは少しファンキーで、デバッグと保守が困難です。新しいビルドシステムは非常に強力で、すでに多くの柔軟性を備えています。方法を学ぶだけの問題です。

特に、Android-Gradleプロジェクトの内外を学んでいるだけの場合(そして、それが私たち全員にとって非常に新しいため)、システムに組み込まれている機能を一生懸命に試してから、思い切って考えることをお勧めします。

いくつかの推奨事項:

  • ビルドタイプに基づいてリソースを変更する必要はほとんどありません。 Android-Gradleのビルドタイプは、デバッグやリリースのようなものであることが想定されており、デバッグ性、コンパイラーの最適化、または署名に違いがあります。ビルドタイプは、機能的には互いに同等であると想定されています。 Groovy DSLを通じてビルドタイプに設定できるプロパティ を見ると、インテントを確認できます:debuggablejniDebugBuildrenderscriptDebugBuildrenderscriptOptimLevelpackageNameSuffixversionNameSuffixsigningConfigzipAlignrunProguardproguardFileproguardFiles
  • それでもビルドタイプに基づいてリソースを変更したい場合は、現在のビルドシステムでこれを行う簡単な方法がすでにあります。ビルドタイプ固有のリソースディレクトリを作成し、そこにリソースを配置すると、ビルドシステムでマージされるリソースがビルド時に処理を行います。これは、Android/Gradleの強力な機能の1つです。これを機能させる方法については、 ビルドフレーバーの使用-ソースフォルダとbuild.gradleを正しく構造化する を参照してください。
  • ビルドタイプに基づいて何かを変更したい場合で、ニーズが非常に迅速でシンプルな場合は、リソースではなくビルドシステムではなく、Javaコードで切り替えることをお勧めします。その種のBuildConfigメカニズム-デバッグ/リリースビルドステータスに基づいてDEBUGフラグを定義するJavaクラスです。独自のカスタムJavaさまざまなビルドタイプのコードを使用して、より意味のあることを行います。BuildConfigは、デバッグビルドでより広範なデータ検証を行ったり、より詳細なデバッグログを作成したりするなど、開発を支援するための無駄な操作を実行します。これらの無駄なことは、リリースビルドから最適化されるのが最善です。
  • 今のところビルドタイプを使用しているものにフレーバーを使用することを検討してください。概念的には、フレーバーはビルドタイプのようなものであり、ビルドできるアプリケーションの別のバリアントです。ビルドシステムは、フレーバーとビルドタイプのマトリックスを作成し、すべての組み合わせをビルドできます。ただし、フレーバーは異なるユースケースに対応します。異なるフレーバーはほとんどのコードを共有しますが、機能に大きな違いがある場合があります。一般的な例は、アプリケーションの無料バージョンと有料バージョンです。アプリのさまざまなバリエーションのさまざまなリソースがさまざまな機能を表すので、異なるフレーバーの必要性を示している可能性があります。フレーバーには、ビルド構成と同じ方法でビルド時にマージされる異なるリソースディレクトリを含めることができます。詳細については、上記の質問を参照してください。
18
Scott Barta

あなたが望むものを達成するためにビルドスクリプトをカスタマイズする必要があるとはまったく思いません。私の読書によると http://tools.Android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants ;ビルドの実行時に、リソースが存在する場合、次のフォルダーからリソースがマージされます。

src/[flavour][buildType]/res
src/[buildType]/res
src/[flavour]/res
src/main/res

したがって、src/release/resにリソースを追加するだけで、希望どおりの結果が得られると思います。

ただし、本当に変更したい場合は、関連するsourceSets。[type] .res.srcDirsを指定してフォルダー名を微調整できます。

7
Jeremy Lakeman

誰かがこれにつまずいたら

  buildTypes {
        debug{
            buildConfigField "String", "Your_string_key", '"yourkeyvalue"'
            buildConfigField "String", "SOCKET_URL", '"some text"'
            buildConfigField "Boolean", "LOG", 'true'
        }
        release {
            buildConfigField "String", "Your_string_key", '"release text"'
            buildConfigField "String", "SOCKET_URL", '"release text"'
            buildConfigField "Boolean", "LOG", 'false'

        }
    }

ビルドバリアントを使用してこれらの値にアクセスするには:

 if(!BuildConfig.LOG)
      // do something with the boolean value

または

view.setText(BuildConfig.yourkeyvalue);
1