In an Android project, the resource ids are fully identified by the application id. For example, if my appid is com.mycompany.myapp, the resource id would be com.mycompany.myapp.R.blah.
In my case, I need to create two versions of the app - beta version and release version. Both the versions may be installed on the same device. This can happen only if the appids are not the same. My strategy is, during the nightly build, I will programmatically modify the manifest file and change the appid to com.mycompany.myappbeta. However, if I do this, I would need to touch a number of source files that are using the resource ids.
I am wondering if there is some token in the manifest file where I can explicitly say how the resource ids be qualified? Regards.
Edit
It turns out app id and package id are indeed two different concepts. I wanted to change the app-id but not the package-id. However, it seems this is not possible under Eclipse. As other posts have pointed out, Gradle build can handle changing the app-id but retaining the package id. I am moving over to Android Studio now.
the resource ids are fully identified by the application id
Technically, they are identified by the package name, from the package attribute in the root manifest.
My strategy is, during the nightly build, I will programmatically modify the manifest file and change the appid to com.mycompany.myappbeta. However, if I do this, I would need to touch a number of source files that are using the resource ids.
Which is why your nightly build should be using Gradle and the Gradle for Android plugin. Then, you skip all of what you described, and instead use build types. Two build types (debug and release) are pre-defined, and if you want to invent another one (e.g., beta), you can. Then, in the build type configuration in your build.gradle file, you use applicationIdSuffix to give non-release builds a distinct suffix. That will be added to the application ID for the purposes of unique installations, but your package name is unaffected, so your resources are unaffected.
For example:
android {
compileSdkVersion 19
buildToolsVersion "21.1.2"
defaultConfig {
versionCode 2
versionName "1.1"
minSdkVersion 14
targetSdkVersion 18
}
signingConfigs {
release {
storeFile file('HelloConfig.keystore')
keyAlias 'HelloConfig'
storePassword 'laser.yams.heady.testy'
keyPassword 'fw.stabs.steady.wool'
}
}
buildTypes {
debug {
applicationIdSuffix ".d"
}
release {
signingConfig signingConfigs.release
}
beta.initWith(buildTypes.release)
beta {
applicationIdSuffix ".beta"
debuggable true
}
}
}
Here I:
Give the debug build type an application ID suffix of .d
Leave the release build type along from the standpoint of an application ID suffix
Create a new beta build type, cloned from the release build type, where I give it a .beta application ID suffix and mark it as debuggable
However, if I do this, I would need to touch a number of source files that are using the resource ids.
No, you will not. You just need to change package id in your Manifest file only, ensuring however all services and activities listed in manifest file are using full class path, i.e.:
android:name="com.mycompany.myapp.MainActivity"
not just shortened notation:
android:name=".MainActivity"
as this make your app not working when package Id will not match with your code packages.
Related
I am setting up Firebase for my Android application and have run into a slight wrinkle/problem. I have multiple product flavors such as the standard dev, qa and prod. These product flavors share the same application id. However, I have one flavor where the application id is different:
productFlavors {
dev {
applicationId "com.acme.myandroidapp"
}
qa {
applicationId "com.acme.myandroidapp"
}
foo {
applicationId "com.acme.foo"
}
prod {
applicationId "com.acme.myandroidapp"
}
This is causing my gradle build to fail with a "No matching client found for package name 'com.acme.foo'" error.
I have looked at both: No matching client found for package name (Google Analytics) - multiple productFlavors & buildTypes and google-services.json for different productFlavors
Unfortunately, neither question deals with the wrinkle of having a different application id for a particular product flavor. I did try putting a copy of the google-services.json file at the base of each flavor but there was no joy.
Thoughts on how do you support different applicationIds with Google Services under Android?
You can Add app for both the application Ids in Project setting in Firebase Console.
By doing so the new google-services.json file will contain two client-info, 1 for each application ID.
Putting a copy of the google-services.json file at at the base of each flavor should solve the issue.
we know APK save data in /data/data/PackageName,if two different apk with same package name,will they cover other's data?(like sharepreference's data)
The Answer is No, Why? This is not possible, Play store will not let you to upload an apk with the same package,Package name at play store is important for many reasons, one of them is update detection, if you updated an application the first thing Google pay attention is the package name in order to know what is the current release version.
Somehow it will be happened by same developer at the DEVELOPMENT stage only then you can name your package whatever do you want.
As far as same package name is concerned it's not possible to have installed on same device it will be replaced.
But if we have different appliationId, yes another app can be installed on same device but in that case packageName will also be change.
Working Sample
Project 1
app/build.gradle
applicationId "com.test.sample"
Android Manifest
package="com.test.sample"
Result
When i print applicationId and package name, it was same:
applicationId: "com.test.sample"
package: "com.test.sample"
Project 2
I've added buildTypes/flavor but keeping applicationId and package name same, but in that case outpout of applicationId and package name will be changed.
build.gradle(app)
applicationId "com.test.sample"
buildTypes {
release {
applicationIdSuffix ".release"
}
debug {
applicationIdSuffix ".debug"
}
}
Android Manifest
package="com.test.sample"
Result
When i print applicationId and package name, it was different:
applicationId: "com.test.sample.debug"
package: "com.test.sample.debug"
So that is how two applications are installed due to change in buildType/flavors(pro/free).
And if you want to access sharedPreferences of each-other (assume free/pro version) than you need to create a ContentProvider to expose data you need and grant permissions to paid app.
I have an Android App, which has two flavors: Basic and Advanced.
The Basic is already on the AppStore, with a package name of form com.domain.something. I would like to publish the second as com.domain.something.advanced. Is it possible? Or is the fact that the second is a sub package of the first would cause trouble?
Yes, this is possible and will not cause any problems in the Play Store.
You will want to read the Configure Build Variants guide for more information on setting up a product flavor for your "advanced" version. You can use the applicationIdSuffix in your build types or product flavors to set a suffix on your application ID for that particular variant.
Your build.gradle will end up looking something like this:
android {
defaultConfig {
applicationId "com.domain.something"
}
buildTypes {...}
productFlavors {
basic {...}
advanced {
applicationIdSuffix ".advanced"
}
}
}
You can then either programmatically check your product flavor with the generated BuildConfig class, or put your code for the advanced version in the advanced product flavor's source folder (/src/advanced/java, /src/advanced/res, etc.).
I have defined a few flavors and buildTypes for my android app
productFlavors {
X {
applicationId = "com.x.xxxx"
}
Y {
applicationId = "com.y.yyyy"
}
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard_rules.txt'
}
debug {
applicationIdSuffix ".debug"
}
}
That does the job of creating different flavors/buildType combinations.
Now to make sure that ContentProviders works and I do not get a Failure [INSTALL_FAILED_CONFLICTING_PROVIDER] error, I have changed the android:authorities="${applicationId}" and AUTHORITY references in code to BuildConfig.APPLICATION_ID.
That makes the ContentProvider work fine i.e it does not throw an error when I install two different types on the same phone. It lets me install them.
Next step is where the error is. I use SyncAdapter and AccountManager to control a few things. I have modified the ACCOUNT_TYPE to use the APPLICATION_ID. Because of the issue with gradle not being able to use ${applicationId} in non-manifest xml resource files, I have created a different directory structure for each flavor and copied the syncadapter.xml and authenticator.xml with corresponding authority and account type strings.
I have also tried the technique described in this blog - http://blog.jensdriller.com/android-gradle-workaround-for-missing-placeholder-support-in-resource-files/
And the top voted answers on Using build types in Gradle to run same app that uses ContentProvider on one device but things don't seem to work.
Anyone been able to get this to work recently?
I just released my first Android Application through the market. I'm currently working on some new features for the next release and would like to install this "dev build" on my phone, without uninstalling the "production" version (among other things, this will stop future updates from the Market).
I'm especially interested in this because I'd like to give the APK to friends / "beta-testers" to try, but I don't want them to uninstall the released application first.
Is there anyway to have on one device two applications: "App (via market)" and "App (DEV)"
Would this involve using a different signing key or modifying the manifest in someway?
Thanks!
You can simply rename the package, so both apps are installed.
You need to change the package name in the manifest as well as in the source folder. Use Eclipse's refactoring for it and it will be done in a minute.
They don't need to be signed with the same key.
Using Gradle this is very easy. Here's an excerpt from one of my gradle files:
android {
// ...
defaultConfig {
resValue "string", "app_name", "<app name>"
// ...
}
buildTypes {
release {
// ...
}
debug {
resValue "string", "app_name", "<app name> (debug)"
applicationIdSuffix ".debug"
// ...
}
}
}
The key part for allowing another installation is using the applicationIdSuffix that is set in the debug build. Under the hood this basically does the same thing as proposed in Force's answer; it changes the application id of your app.
Setting the resValue app_name allows us to have different app names as well, this makes it much easier to keep track of which installation is which (since both application would get the same name otherwise).
Don't forget to remove the app_name from your strings.xml and fill in your own app name instead of <app name> if you decide to set the app_name in the gradle file like I did above.