Using build types in Gradle to run same app that uses ContentProvider on one device

后端 未结 14 1029
小蘑菇
小蘑菇 2020-11-28 00:22

I have set up Gradle to add package name suffix to my debug app so I could have release version that I\'m using and debug version on one phone. I was referencing this: http:

14条回答
  •  攒了一身酷
    2020-11-28 00:58

    While Cyril's example works great if you only have a few build types, it quickly gets complicated if you have many build types and/or product flavors as you need to maintain lots of different AndroidManifest.xml's.

    Our project consists of 3 different build types and 6 flavors totaling 18 build variants, so instead we added support for ".res-auto" in ContentProvider authorities, which expand to the current packagename and removes the need to maintain different AndroidManifest.xml

    /**
     * Version 1.1.
     *
     * Add support for installing multiple variants of the same app which have a
     * content provider. Do this by overriding occurrences of ".res-auto" in
     * android:authorities with the current package name (which should be unique)
     *
     * V1.0 : Initial version
     * V1.1 : Support for ".res-auto" in strings added, 
     *        eg. use ".res-auto.path.to.provider"
     *
     */
    def overrideProviderAuthority(buildVariant) {
        def flavor = buildVariant.productFlavors.get(0).name
        def buildType = buildVariant.buildType.name
        def pathToManifest = "${buildDir}/manifests/${flavor}/${buildType}/AndroidManifest.xml"
    
        def ns = new groovy.xml.Namespace("http://schemas.android.com/apk/res/android", "android")
        def xml = new XmlParser().parse(pathToManifest)
        def variantPackageName = xml.@package
    
        // Update all content providers
        xml.application.provider.each { provider ->
            def newAuthorities = provider.attribute(ns.authorities).replaceAll('.res-auto', variantPackageName)
            provider.attributes().put(ns.authorities, newAuthorities)
        }
    
        // Save modified AndroidManifest back into build dir
        saveXML(pathToManifest, xml)
    
        // Also make sure that all strings with ".res-auto" are expanded automagically
        def pathToValues = "${buildDir}/res/all/${flavor}/${buildType}/values/values.xml"
        xml = new XmlParser().parse(pathToValues)
        xml.findAll{it.name() == 'string'}.each{item ->
            if (!item.value().isEmpty() && item.value()[0].startsWith(".res-auto")) {
                item.value()[0] = item.value()[0].replace(".res-auto", variantPackageName)
            }
        }
        saveXML(pathToValues, xml)
    }
    
    def saveXML(pathToFile, xml) {
        def writer = new FileWriter(pathToFile)
        def printer = new XmlNodePrinter(new PrintWriter(writer))
        printer.preserveWhitespace = true
        printer.print(xml)
    }
    
    // Post processing of AndroidManifest.xml for supporting provider authorities
    // across build variants.
    android.applicationVariants.all { variant ->
        variant.processManifest.doLast {
            overrideProviderAuthority(variant)
        }
    }
    

    Example code can be found here: https://gist.github.com/cmelchior/6988275

提交回复
热议问题