How to use different package names between flavors? - android

I'm trying to create a single project with 2 flavors: free and pro (versions).
My app is already in PlayStore with different packages (E.g.: com.example.appfree and com.example.app)
This is my build.gradle:
defaultConfig {
applicationId "com.example.appfree"
}
productFlavors{
lite {
applicationIdSuffix 'lite'
}
pro {
}
}
And this is my manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".SplashScreenActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MainActivity"/>
</application>
</manifest>
I tried to upload a build apk for free and pro flavors. Pro flavor is ok, but free flavor isnt accepted by Google, because the package is incorrect. How can I solve this?
====== Solved: ======
applicationIdSuffix only works with buildTypes.

With the new Android Gradle build system, you can easily build multiple different versions of your app; for example, you can build both a "free" version and a "pro" version of your app (using flavors), and these should have different packages in the Google Play store such that they can be installed and purchased separately, both installed at the same time, and so on. Similarly, you may also build both "debug" and "alpha" and "beta" versions of your app (using build types) and these can also similarly contribute to unique package names.
app/build.gradle:
apply plugin: 'com.android.application'
android {
compileSdkVersion 19
buildToolsVersion "19.1"
defaultConfig {
applicationId "com.example.my.app"
minSdkVersion 15
targetSdkVersion 19
versionCode 1
versionName "1.0"
}
...
app/build.gradle:
productFlavors {
pro {
applicationId = "com.example.my.pkg.pro"
}
free {
applicationId = "com.example.my.pkg.free"
}
}
buildTypes {
debug {
applicationIdSuffix ".debug"
}
}
....
from Android Studio Project Site - ApplicationId versus PackageName

flavorDimensions "version"
productFlavors {
demo {
// Assigns this product flavor to the "version" flavor dimension.
// This property is optional if you are using only one dimension.
dimension "version"
applicationIdSuffix ".demo"
versionNameSuffix "-demo"
}
full {
dimension "version"
applicationIdSuffix ".full"
versionNameSuffix "-full"
}
}

Besides the basic gradle.build (app level) changes. Note that you only need to add the config you need to, not all of these:
productFlavors {
enterprise {
applicationId = "com.example.appname.enterprise"
}
consumer {
applicationId = "com.example.appname.consumer"
}
}
buildTypes {
debug {
applicationIdSuffix ".debug"
}
}
I wanted to add that if you are using Firebase and you are required to have a google-services.json file. You will see the following:
ERROR: No matching client found for package name "com.example.appname.debug"
To fix it, you will need to register the new package name in Firebase and download the new google-services.json which will have all your existing packages names. If not you will have a compile error saying no client was found for the new package name.

Related

Instant app, Try Now button does not appear in play store

i started with following github projects but these example are not working properly. I added missing parts as stated in the docs.
https://github.com/android/app-bundle-samples/tree/main/InstantApps/urlless
https://github.com/googlecodelabs/android-dynamic-features
Here is the docs i read.
https://developer.android.com/topic/google-play-instant/getting-started/instant-enabled-app-bundle
https://developer.android.com/topic/google-play-instant/feature-module-migration
https://developer.android.com/guide/app-bundle/instant-delivery
i try to implement a simple hello world instant app. I tried many things but try now button never appears in play store.
my app contains 2 module:
app
instant-app
build.gradle of app module :
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
android {
compileSdkVersion 30
defaultConfig {
minSdkVersion 21
targetSdkVersion 30
versionCode 61
versionName "61"
multiDexEnabled true
}
buildTypes {
release {
minifyEnabled true
shrinkResources false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
debuggable true
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
dynamicFeatures = [':instantapp']
}
dependencies {
...
implementation "com.google.android.gms:play-services-instantapps:17.0.0"
implementation "com.google.android.play:core:1.9.0"
...
}
build.gradle of my instant-app module
plugins {
id 'com.android.dynamic-feature'
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.2"
defaultConfig {
applicationId "com.test.myapp"
minSdkVersion 21
targetSdkVersion 30
versionCode 3
versionName "1.2"
}
}
dependencies {
implementation "com.google.android.play:core:1.9.0"
}
AndroidManifest.xml of my app module
<?xml version="1.0" encoding="utf-8"?>
<manifest >
<dist:module dist:instant="true" />
...
</manifest>
AndroidManifest.xml of my instant-app module
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:dist="http://schemas.android.com/apk/distribution"
package="com.test.instantapp"
android:targetSandboxVersion="2">
<dist:module dist:instant="true" dist:onDemand="false"
dist:title="Instant app title">
<dist:fusing dist:include="true" />
</dist:module>
<application android:usesCleartextTraffic="false">
<activity android:name=".InstantMainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
I generate a signed bundle and upload it in internal test in each of my try but it did not work. i tried it in prod environment too. Not work!
I tried to put applicationId "com.test.myapp" in both app module and instant-app module. I tried to made android:targetSandboxVersion="2" and android:targetSandboxVersion="1". Not work
.
Version code of my app is greater than version code of my instant-app as shown below.
I removed clearTextTraffic and added. Not work!
Some said me to take my instant app enabled code to take into production and upload a new upgraded instant app version. I did it, it did not work either.
I tried many many combinations which i cannot remember now. But try now button never appears. What is the missing part i cannot find ?
There are 3 different sayings for maximum size of instant-app module:
4 mb
10 mb
15 mb
Why the source codes and docs are conflicting too much and there is no working code in github ? If i didn't see working samples in play store, i would think instant apps are dead.
open play store -> select app-> open advanced settings -> add release type instant app
Then upload your instant app from instant apps only option:

wear apk is not deploying when there are product flavors

When I try to deploy with these productFlavors, wear debug apk won't built and it is not embedded into mobile release apk. But after I delete productFlavors from mobile and wear build.gradle file, it's working as it should.
productFlavors {
lite {
}
pro {
applicationId 'example.app.id.pro'
versionNameSuffix '.pro'
}
}
Try assigning applicationIdSuffix and versionNameSuffix values for each of your product flavors. See Configuration of Product Flavors for more information.
And if you haven't done yet, add publishNonDefault truein your Wear module's build.gradle file.
android {
publishNonDefault true
......
productFlavors {
trial {
applicationId "com.sample.myapp.trial"
versionName "3.0.1"
versionCode 301
}
full {
applicationId "com.sample.myapp"
versionName "3.0.1"
versionCode 301
}
}
}
See this related SO post and Packaging and Distributing Wear Apps for additional insights.

How to refer to a String var defined in build.gradle?

I hope to display different app name based free and pro version.
I define buildConfigField "String", "AppName", "\"Message Cleanup\"" in build.gradle, but I don't know how to apply to android:label in AndroidManifest.xml.
Could you help me ? Thanks!
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="info.dodata.messagecleanup" >
<application
android:allowBackup="true"
android:icon="#mipmap/clenupmessage"
android:label="AppName"
android:theme="#style/AppTheme" >
<activity android:name="ui.CleanupDelete"
android:label="AppName">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "info.dodata.messagecleanup"
minSdkVersion 9
targetSdkVersion 22
versionCode 7
versionName "1.07"
archivesBaseName = "MessageCleanup-V" + versionName
}
productFlavors {
free {
applicationId "info.dodata.messagecleanup"
buildConfigField "String", "AppName", "\"Message Cleanup\""
}
pro {
applicationId "info.dodata.messagecleanup.pro"
buildConfigField "String", "AppName", "\"Message Cleanup Pro\""
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.1.1'
compile 'com.google.android.gms:play-services:7.3.0'
}
To kcoppock
The manifestPlaceholders can do that.
productFlavors {
wandoujia {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"]
}
baidu {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "New"]
}
c360 {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "c360"]
}
uc {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "uc"]
}
}
In AndroidManifest.xml, I can use it as the following code
<meta-data
android:name="UMENG_CHANNEL"
android:value="${UMENG_CHANNEL_VALUE}" />
Assuming you are using the standard project structure (e.g. you have something like src/main/res/values/strings.xml), create additional directories for each flavor:
src/free/res/values/strings.xml
src/pro/res/values/strings.xml
And define the same string key (e.g. app_name) in both of those files, with the correct value for each variant. So you'd have something like:
src/free/res/values/strings.xml
<string name="app_name">Message Cleanup</string>
src/pro/res/values/strings.xml
<string name="app_name">Message Cleanup Pro</string>
The resource merger will merge in these strings based on which variant is being built. Now you can just refer to the app_name string in code, and know that it'll render correctly based on the currently built flavor.

Use package name in XML

I'm using Android Studio to build my application. I would like to use gradle buildTypes. I add a suffix to the package name with applicationIdSuffix to modify the package name for a test build type.
buildTypes {
debug {
runProguard false
proguardFile 'proguard-rules.txt'
applicationIdSuffix '.dev'
versionNameSuffix '-dev'
}
}
Is it possible to use this information in a xml file. My plan is to modify the account type:
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType=<<PACKAGE NAME HERE ??>>
android:icon="#drawable/icon"
android:label="#string/app_name"/>
Thanks!
Here's another temporary workaround until the Android Gradle plugin gets support for placeholders in resource files.
You can dynamically create a String resource via Gradle in the defaultConfig and/or buildTypes and/or productFlavors closure:
android {
defaultConfig {
applicationId 'com.foo.bar'
resValue 'string', 'package_name', applicationId
}
}
You can then reference it in your authenticator.xml file just like you do for the label:
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="#string/package_name"
android:icon="#drawable/icon"
android:label="#string/app_name"/>
While uou can use ${packageName} to fill in the generated package name in the Manifest:
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="${packageName}"
android:icon="#drawable/icon"
android:label="#string/app_name"/>
This currently (Android Gradle 0.11) doesn't work with resource files. :-(
Instead, you must create a separate version of the resource file for each build type / variant you want with a different account type:
src
debug/res/xml/authenticator.xml (with debug package name)
main/res/xml/authenticator.xml (with default package name)
On top of jenzz's answer, i had to do this, since my case is just like as question, i add applicationIdSuffix for debug version of app.
android {
...
defaultConfig {
applicationId "..."
...
}
....
buildTypes {
release {
...
resValue 'string', 'application_id', android.defaultConfig.applicationId
}
debug {
...
applicationIdSuffix '.debug'
resValue 'string', 'application_id', android.defaultConfig.applicationId + applicationIdSuffix
} 
}
Then in any xml resource, i can get application Id as like this: #string/application_id
I'm using ${applicationId} like follow for example:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.abnerescocio.embaixadordorei.presentation">
...
<application
...
>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.android.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths"/>
</provider>
...
</application>
</manifest>
I've just created a gradle plugin for this: com.inutilfutil.android-resource-placeholder
Just include it and placeholders will be replaced on all XML resources

How to change the Android app package name when assembling with Gradle?

Is it possible to change the package name of an Android application using Gradle?
I need to compile two copies of the same app, having a unique package name (so I can publish to the market twice).
As a simpler alternative to using product flavours as in Ethan's answer, you can also customise build types.
How to choose between the approaches:
If you need different package names to be able to have both debug and release apks installed on a device, then use the build type approach below, as Gradle plugin docs agree. In this case flavours are an overkill. (I think all projects should by default do this, as it will make life easier especially after you've published to the store and are developing new features.)
There are valid uses for product flavours, the typical example being an app with free and paid versions. In such case, check Ethan's answer and read the documentation too: Configuring Gradle Builds and Gradle Plugin User Guide.
(You can also combine the two approaches, which results in every build variant having distinct package name.)
Build type configuration
For debug build type, and all other non-release types, define applicationIdSuffix which will be added to the default package name.
(Prior to Android Gradle plugin version 0.11 this setting was known as packageNameSuffix.)
android {
buildTypes {
debug {
applicationIdSuffix '.debug'
versionNameSuffix '-DEBUG'
}
beta {
applicationIdSuffix '.beta'
versionNameSuffix '-BETA'
// NB: If you want to use the default debug key for a (non-debug)
// build type, you need to specify it:
signingConfig signingConfigs.debug
}
release {
// signingConfig signingConfigs.release
// runProguard true
// ...
}
}
}
Above, debug and release are default build types whose some aspects are configured, while beta is a completely custom build type. To build the different types, use assembleDebug, assembleBeta, etc, as usual.
Similarly, you can use versionNameSuffix to override the default version name from AndroidManifest (which I find very useful!). E.g. "0.8" → "0.8-BETA", as configured above.
Resources:
This example is straight from Xavier Ducrohet's "Google I/O 2013: The New Android SDK Build System" presentation.
Build Types in the User Guide.
Myself I've been using productFlavors so far for this exact purpose, but it seems build type customisation may be closer to my needs, plus it keeps the build config simpler.
Update (2016): I've since used this approach in all my projects, and I think it definitely is the way to go. I also got it included in Android Best Practices guide by Futurice.
You could so something like this
android {
...
defaultConfig {
minSdkVersion 8
versionCode 10
}
flavorDimensions "flavor1", "flavor2"
productFlavors {
flavor1 {
applicationId "com.example.flavor1"
versionCode 20
}
flavor2 {
applicationId "com.example.flavor2"
minSdkVersion 14
}
}
}
You can also change the field android.defaultConfig.applicationId if you want to do one-off builds.
Taken from: http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Product-Flavor-Configuration
With the gradle plugin version of 1.0.0+ you have to use applicationId as stated in the migration guide
Renamed Properties in ProductFlavors
packageName => applicationId
Thus in your build.gradle you would now use:
productFlavors {
flavor1 {
applicationId "com.example.flavor1"
}
flavor2 {
applicationId "com.example.flavor2"
}
}
From Ethan's answer, both flavorGroups and packageName both are not available anymore. Below works as of March 2015.
android {
...
defaultConfig {
minSdkVersion 8
versionCode 10
}
flavorDimensions "flavor"
productFlavors {
flavor1 {
flavorDimension "flavor"
applicationId "com.example.flavor1"
versionCode 20
}
flavor2 {
flavorDimension "flavor"
applicationId "com.example.flavor2"
minSdkVersion 14
}
}
}
I did not want to use Flavors, so I found a way to do so with buildTypes. I did this by changing my app/build.gradle file as follows:
defaultConfig {
applicationId "com" // See buildTypes.type.applicationIdSuffix
...
}
...
buildTypes {
debug {
applicationIdSuffix ".domain.name.debug"
...
}
releaseStaging {
applicationIdSuffix ".compagny.staging"
...
}
release {
applicationIdSuffix ".domain.name"
...
}
}
This allows me to have 3 apps next to each other on my devices.
I hope this helps others.

Categories

Resources