androidgradleandroid-gradle-3.0android-flavordimension

Gradle Building Schema dynamically from combined flavor dimensions


We have two different flavor dimensions like in this example and we want to dynamically generate applicationId like

com.company.apple

instead this script will generate an applicationId of

null.company.apple

I believe this is because the function at the bottom iterates over the full productFlavor list and not the combined list.

flavorDimensions "product", "license"

productFlavors.all {
    ext.scheme = null
    ext.scheme_tail = ""
    ext.kind = null
    ext.license = null
}

productFlavors {
    apple {
        dimension "product"
        kind = "apple"
        scheme = "companyapple"
    }

    orange {
        dimension "product"
        scheme = "companyorange"
        kind = "orange"
    }

    kiwi {
        dimension "product"
        scheme = "companykiwi"
        kind = "kiwi"
    }

    com {
        dimension "license"
        license = "com"
        scheme_tail = ''
    }

    eu {
        dimension "license"
        license = "eu"
        scheme_tail = "eu"
    }

    uk {
        dimension "license"
        license = "uk"
        scheme_tail = "uk"
    }

}

productFlavors.all {
    applicationId license + ".company." + kind
    ext.fileProvider = applicationId + ".fileprovider"
    manifestPlaceholders = [scheme: "$scheme$scheme_tail", fileProvider: "$fileProvider"]
    buildConfigField("String", "FILE_PROVIDER", "\"$fileProvider\"")
    buildConfigField("String", "SCHEME", "\"$scheme$scheme_tail\"")
    buildConfigField("String", "KIND", "\"$kind\"")
    buildConfigField("String", "LICENSE", "\"$license\"")
}

How can I iterate over the combined list to build my buildConfig fields and applicationIds?

The manifestPlaceholders are consumed like this:

    <activity android:name=".FruitViewerActivity">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />

            <data android:scheme="${scheme}" />

            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
        </intent-filter>
    </activity>

    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="${fileProvider}"
        android:grantUriPermissions="true">

        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />

    </provider>

Thanks, Rory


Solution

  • I found a solution that accomplishes my goals, and then improved upon it with information from this post by David Medenjak.

    Firstly use applicationId and applicationIdSuffix to build the applicationId. Build the file provider separately for BuildConfig and for AndroidManifest. Publish the scheme_prefix and scheme_suffix separately for the AndroidManifest and concatenate them later. Build the scheme from it's components in the ApplicationVariant.

    flavorDimensions "product", "license"
    
    productFlavors.all {
        ext.scheme_prefix = null
        ext.scheme_suffix = ""
        ext.license = null
    }
    
    productFlavors {
        apple {
            applicationId = "apple.company"
            dimension "product"
            scheme_prefix = "companyapple"
            manifestPlaceholders = [scheme_prefix: "$scheme_prefix"]
    
            buildConfigField("String", "KIND", "\"apple\"")
        }
    
        orange {
            applicationId = 'orange.company'
            dimension "product"
            scheme_prefix = "companyorange"
            manifestPlaceholders = [scheme_prefix: "$scheme_prefix"]
    
            buildConfigField("String", "KIND", "\"orange\"")
        }
    
        kiwi {
            applicationId = "kiwi.company"
            dimension "product"
            scheme_prefix = "companykiwi"
            manifestPlaceholders = [scheme_prefix: "$scheme_prefix"]
    
            buildConfigField("String", "KIND", "\"kiwi\"")
        }
    
        com {
            dimension "license"
            license = "com"
            applicationIdSuffix = "$license"
    
            scheme_suffix = ''
            manifestPlaceholders = [scheme_suffix: "$scheme_suffix"]
        }
    
        eu {
            dimension "license"
            license = "eu"
            applicationIdSuffix = "$license"
    
            scheme_suffix = "eu"
            manifestPlaceholders = [scheme_suffix: "$scheme_suffix"]
        }
    
        uk {
            dimension "license"
            license = "uk"
            applicationIdSuffix = "$license"
    
            scheme_suffix = "uk"
            manifestPlaceholders = [scheme_suffix: "$scheme_suffix"]
        }
    
    }
    
    android.applicationVariants.all {
        variant ->
            ext.fileProvider = variant.applicationId + ".fileprovider"
            buildConfigField("String", "FILE_PROVIDER", "\"$fileProvider\"")
    
            def product = variant.productFlavors[0]
            def license = variant.productFlavors[1]
            variant.buildConfigField("String", "LICENSE", "\"${license.license}\"")
            variant.buildConfigField "String", "SCHEME", "\"${product.scheme_prefix}${license.scheme_suffix}\""
    }
    

    Here are the corresponding Manifest changes:

        <activity android:name=".FruitViewerActivity">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
    
                <data android:scheme="${scheme_prefix}${scheme_suffix}" />
    
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
            </intent-filter>
        </activity>
    
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:grantUriPermissions="true">
    
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
    
        </provider>