Reading this article, thought having the same problem - One code base, two applications on Android
I have created an application testApp that has items like topics, splash screens, logos, charts, rules, statuses and/or events.
Now, I want different applications (testApp_USA, testApp_Canada, testApp_Australia)from the same code base and put them on Google Play Store so that if user downloads the application, say, testApp_USA, then only the specific items to that region should be shown like splash Screen of USA, USA logos, etc..
So I want to configure multiple applications according to countries and then set the items as defaults according to which application the user has downloaded.
Presently, I have a single application which is for all regions and I am imposing multiple conditions to distinguish or change the items according to the regions.
For example:
(In many Java files, I used)
if(rule.contains("USA"))
{
//Show splash screen of USA
}
(Similarly, In many Java files, I used)
if(rule.contains("Australia"))
{
//Show splash screen of Australia
}
This is just a one item out of many repeated throughout code. Considering all, it will be lot more.
There should be a better way to create multiple applications in android with different names and settings.
I know, iOS allows me to easily change the application name and profile to allow multiple apps to be created. But I don't know or this is not easy to do on the Android code.
My question:
Is it possible to create different applications with the same source code in android with different settings of items and publish them to Google Play Store ? If YES, How to set such configuration ?
UPDATE:
Read this Post - multiple-android-application-package-apk-files-from-single-source-code
Then I came up with the same idea -
1) Taking some string variable that holds values about which application type you want to create.
public static final String app_Name = "testApp_CANADA" ;
2) Have multiple AndroidManifest.xml files for multiple apps you need to create .apk for.
3) Create corresponding launcher activities for each manifest.
But then how to have multiple AndroidManifest.xml files in a single app ?
UPDATE:
My first AndroidManifest.xml is in main project folder (application root folder) as usual that we have. Consider this for testApp_USA.
My second AndroidManifest.xml is in separate package under main project. Consider this for testApp_CANADA.
Both AndroidManifest.xml have different launcher activities with corresponding splash screens, icons defined. The package names are given different in both so that they will create different .apk files as per requirement.
Now, how to switch code between testApp_USA/testApp_CANADA provided my main app has setting:
public static final String app_Name = "testApp_CANADA" ;
OR
More clearly,
How to call a particular AndroidManifest.xml according to the value of app_Name ?
With the current setup that I have, only first AndroidManifest.xml is called always.
I had similar problem with putting project to different markets - Google Play, Samsung, Amazon. All code base is the same, difference only in billing code.
The best solution I found is creating separate project for each market and pushing common code into library project.
In more detail, you need to leave common code in main project, make it library project and enable manifest merger for library and child projects.
Add following lines to project.properties of main project:
android.library=true
manifestmerger.enabled=true
and this to project.properties of every child project:
android.library.reference.1=../testApp //absolute or relative path to your main project
manifestmerger.enabled=true
Also you need to attach main project as library in ADT plugin (in Eclipse - project properties -> Android) to all child projects.
Main project manifest should not contain any launcher activity, it will be ignored, same thing with appWidget xml's and config activities, if you have some.
In child projects you can configure whatever you want and use main code by extending or just using needed classes as normal Java library. Also, you can use main project activities, services, broadcast receivers, etc just as they are in your child project without any duplication of manifest of child projects.
After all configured, you can just build needed project for needed country as usual single project and you would have different apk's for different countries, as you want.
Here is more detail description of manifest merging http://www.platoevolved.com/blog/programming/android/merging-android-manifest-files/
Note, this feature was added in ADT version 20 preview 3.
Hope this helps.
I had this same question. Maybe you have found the answer at this point, but some searching finally led me to this website, which explains Gradle.
It seems to explain all the basics really well. For the answer to your specific question, look for the section Product Flavors under Build Variants.
As the website explains, part of the purpose behind this design was to make it more dynamic and more easily allow multiple APKs to be created with essentially the same code, which sounds exactly like what you're doing.
I probably didn't explain it the best, but that website does a pretty good job.
The way to have multiple apps from a common code base is to have the common code as a library project, and have each app use the library project (see http://developer.android.com/tools/projects/index.html).
Each project can override strings.xml, and the common come can check the package id.
In your case it seems that this is against the Google Play policy (cookie cutter apps), so it may be better to create one app and let the user choose a country.
For this you have to use App Localization concept. For this you have to create different resources, durables. Let say You want to run your application in japan, you have to create drawable folder like "res/drawable-ja". This is same as you create different layouts to support tablet and small devices.
here is reference link:
http://developer.android.com/guide/topics/resources/localization.html
http://developer.android.com/distribute/googleplay/publish/localizing.html
I am not sure what you want exactly. But at my point of level, you can able to get the geo location, there you can find-out where you app currently running out, or in more easier get the location from locale, once you find the locale or geo-location, you can navigate the source according to that.
Related
My situation is that I want both free and full versions of the same Google Play Store (GPS) app. To satisfy GPS, I had the choice of figuring out GPS API for in-app purchases or creating a second package. I chose the latter path since the former was far from easy to follow (couldn't implement after trying for parts of 3 days).
Before realizing that a second package would be necessary, I had designed the app so that merely changing two imports (package names), one boolean assignment (FREE: true or false), and a couple of lines of AndroidManifest.xml (icon and app name) I could easily change the code from free to full and back again.
All well and good. Then came first bug: actionbar overflow "dashes" didn't appear on a tablet.
So I have two hunks of 99%-identical java and xml code. When I find the need to change code in future, I don't want to have to make two probably-identical changes. And figuring out the GPS API is not likely to penetrate my brain anytime soon.
In trying to answer my own question before posting, I just ran across this here, without further explanation:
I was using Android Libraries to build Free/Paid versions of my app. [With] the new Gradle Build Variants concept... you can now automatically build different signed APKs out of the same code.
It received an upvote, but that doesn't make it credible.
Is it?
If it is, I'm also not sure if it applies to me. The message from GPS when I made the changes alluded to earlier within the same package was that I needed different package names for the free and full versions, and that quote doesn't mention packages, although maybe it's a way around separate packages. I wish I knew.
If the quote applies to having ONE package upload TWO versions of an app to GPS, what do I have to do to make gradle do so?
EDIT--
I was sure there was no way until I found this. Is this a way to avoid near-duplicate apps and packages?
Yes, Build Variants are the answer to your problem.
First, I recommend reading the Build Variants documentation on the Android tools site.
What you want in the end is two product flavors. Inside each product flavor closure you can specify the applicationId (formerly packageName) for that flavor. Your build.gradle will look something like this:
productFlavors {
paid {
applicationId "com.example.paid"
}
free {
applicationId "com.example.free"
}
}
When you build your app, you will now get an APK with every possible combination of product flavor and build type. These are called build variants. For your app, you will probably end up with something like debugFree, debugPaid, releaseFree, and releasePaid variants.
You just upload the releaseFree and releasePaid APKs to Google Play (as separate apps) when you want to release.
As for your issue of having duplicated code:
When you create a new product flavor or build type, you can create a set of source files (resources, Java classes, etc.) to go along with that flavor.
By default, all your code goes into the main source set (this is the main folder in your project).
If you want to add some Java classes that provide different functionality for your free variant, you can put those classes in <project root>/app/src/free/java instead of <project root>/app/src/main/java.
For example, you might put a FlavorConstants class containing your boolean flag in both the free and the paid folders. Whenever you reference FlavorConstants in your code, it will be the correct FlavorConstants for whichever flavor is currently running on your device.
I am working on an android group project in college and this is the first big project many of us have worked on.
We worked on implementing several pieces of the project as completely separate projects and now are having trouble putting all of them in one application with a main page.
On the main page of the application we would have a bunch of buttons that would then go to the implemented project that we've completed (example, I click on BMI calculator on the app homepage and it goes the the bmi calculator screen).
Any efficient way of going about this that can be explained in an easy to follow manner? I'm still a newbie programmer :)
Just to clarify, I don't want it so that it just launches a BMI calculator app from the main app, the entire code base is supposed to exist under one app.
Thanks
You can have a main project and several other projects declared as library projects.
In build time, library projects are pulled into the main project and only one apk will exist as the output.
The library projects are almost the same as an usual android project. You can have java packages, res folder, lib folder, etc.
Check here for the official description.
Check here for a tutorial.
Look into making the other applications as Android Library-projects, and listing all necessary components on your AndroidManifest.xml on your parent project.
Another way would just give the option for the user to install these applications as separate and have a logice (PackageManager) check if specific application exists or is installed and then enabling navigation buttons or disabling components and invoke them via Intents.
While writing Android manifest some configuration I must put inside "application" section (eg. list of activities) and some outside it (eg. uses-sdk). Why? Is there any general rule what goes inside "application" section and what outside? Or was it pure random arbitrary decision by Android creators?
Not really a programming question. If you follow commit history of AOSP you might get an answer. Or track down Andy Rubin and ask him :)
With the current layout, you could theoretically have multiple applications inside the same APK. Stuff that is common to all applications will got at the highest level (uses-sdk, etc.), everything else inside the corresponding <application>.
Definitely it is not a random decision.
The Format is something like you have define the configurations pertaining to any application such as its activities and services inside tag because ofcourse they are related to your application.
And General libraries you use and Permissions outside of the tag which complement your application.
Take a note of the structure of the manifest file here
To get concept in detail try here.
check whether the Amazon or the samsung market or the google play that installed android app in device.
Say if i have app named ABC installed in my android phone. In my application i list down all the apps installed in my phone and need to list the market from where they where downloaded.
How can this be done?
Quoting an answer from Detect if app was downloaded from Android Market
Starting with API 5, you can use
PackageManager.getInstallerPackageName(String). From the
documentation:
Retrieve the package name of the application that installed a package.
This identifies which market the package came from.
To get the package of the Android Market, this post may help.
I guess with the appropriate devices, you could build an app to output the package names of each market you want to recognise.
One option is to package them individually. If at some point you decide to use any marketplace specific features, such as licensing or in-app payments, you'll need to do that anyway.
A manageable way of doing so is a library project containing almost everything and a number of mini-projects that rerference it and contain only the specifics.
The drawback: multiple projects instead of one. The benefits: manageability, maintainability.
Edit: if you still prefer using the certificates for that, this example can help: thomascannon.net/misc/android_apk_certificate/ .
Please post the solution you eventually come up with.
I did it this way(a single src and res folder for all projects, different LauncherActivities for each market):
Copy your res and src folder somewhere like /sharedsources/
Make a three new projects for Google/Amazon/Samsung.
Delete the res and src folder from each project
In each project link to /sharedsources/res and .../src
Now make a three new activities:
e.g. GoogleLicensing,AmazonLicensing,SamsungLicensing
Google Project Manifest: set GoogleLicensing as Launcher Activity
Samsung Project Manifest: set SamsungLicensing as Launcher Activity
Amazon Project Manifest: set AmazonLicensing as Launcher Activity
Google Project: remove SamsungLicensing and AmazonLicensing activities from build(dont delete)
Samsung Project: remove GoogleLicensing and AmazonLicensing activities from build(dont delete)
Amazon Project: remove SamsungLicensing and GoogleLicensing activities from build(dont delete)
Done.
Export each Project.
Keep in mind that you have three AndroidManifests now, which need to be edited accordingly.
Also keep in mind that you should only have one project open at a time.
There is no reason for opening more than one anyway, since they share the same source...
Actually i did this to be able to swap between Linux and Windows (my sharedsources folder is on a shared hdd) only for 1 project, but it worked out very well for the different markets aswell.
I have developed one Android app in one project with Eclipse - it's structured (coming from iPhone) so one constant defines whether it's the demo or the full version.
Now I have the problem that everytime I want to create the demo version I need to change the constant but also need to make a copy of the project with a different package name.
Obviously changing code in the original full version needs to be copied over to the demo or I would have to redo the creation of the demo app everytime I submit my app.
I see three possible approaches:
1.
While I have looked into library projects it is still unclear to me how this really provides a good solution in this case.
For example if I have the full version with an activity structure:
A1
A2
A3
using utility classes U1,U2
Certainly U1 and U2 can be in a library project and referenced from both projects - but the activities, strings.xml, graphics, layouts need to be duplicated (or is there another way that I don't see?) This does not seem to be a good way forward and unfortunately has not been explained in similar questions on this topic when this approach was suggested.
2.
The other way would be to create different package names based on different build settings (similar to iPhone), however, this does not seem to be possible in Eclipse rather than by using some external scripts (which - honestly - i rather avoid since it seems rather error prone) while also the compilation has to be invoked outside Eclipse
3.
The probably most straight forward approach (and also currently with smalles effort) is to just manually copy the project, change the one constant, rename the package and compile/export every time I submit. This - however - seems to be rather "basic" and certainly does not look professional (as compared to iPhone/xCode build setting/target solution)
What would be the best approach (requiring minimum amount of changes and still being stable and easy to use) ?
Many thanks!
EDIT
For everyone who tried tim's solution - it works fine, however I ran into a problem with custom attributes.
Check this: How to solve Android Libraries custom attributes and package name remapping during build?
it will solve the isse for libraries
I'm doing this currently in eclipse, and it is not difficult.
Convert existing source to library project.
Create two new projects, free and paid.
Include the library project in the free and paid projects.
It's not necessary to have a single Activity or resource inside the free/paid projects. All you need is a manifest for each which referenes the activities from your library. My free and full projects do not currently have a single java, resource, or layout file of any kind, it's just a manifest which references activities from the library.
I use the exact same code for both projects, and I differentiate them by saying :
if(getApplicationContext().getPackageName().equals("full version package name")) {
//do full stuff
} else {
//do free stuff
}
Some gotchas I've hit, especially if you've already released your app on the market:
If you change the full name/path of any activity, it will disappear from your homescreen. Therefore if your library has a different package name than the existing version, you will lose any homescreen icons. They can be replaced by the user but it's not ideal.
Similar for appwidgets, if you change their receiver name, they will disappear on upgrade.
You may not under any circumstance change the package name of a released application.
If you've already released a free and pro version, it's somewhat unfortunate, because the activity path will need to change to a common library path, and you can't rename the released package to match the library path. So somebody will have to lose their existing icons.
In my case I had only released a free version before splitting them, and I was able to name the library with the same package name as the free version. I was skeptical that you'd be allowed to include a library with the same package name as the wrapper package, but apparently it's possible to do so (working fine for me).
So in my case I've got three projects:
Core Library: package name : com.myname.myapp
Free Version: package name : com.myname.myapp
Pro Version: package name : com.myname.myapp.Pro
And the free and full version manifests add activities which are named com.myname.myapp.ActivityA or com.myname.myapp.ActivityB, which exist only in the library project.
I see the simplest approach would be to have three projects:
demo
full
library
The demo and full projects will each have their own unique package name as defined in their respective Manifest file. Their Activities are merely ports that send information in a bundle to the primary Activity in the library project. The Activity in the library project will read the Bundle passed in for the necessary parameters that determine whether it was launched by the demo Activity or the full Activity. Then it will proceed accordingly.
So the logic is like this:
User launches the demo Activity -> The demo Activity creates a Bundle with the information that says it's the demo Activity -> The demo Activity launches the library Activity which then executes the rest of the program in demo mode.
OR
User launches the full Activity -> The full Activity creates a Bundle with the information that says it's the full Activity -> The full Activity launches the library Activity which then executes the rest of the program in full mode.
It's very simple by using build.gradle in Android Studio. Read about productFlavors. It is a very usefull feature. Just simply add following lines in build.gradle:
productFlavors {
lite {
packageName = 'com.project.test.app'
versionCode 1
versionName '1.0.0'
}
pro {
packageName = 'com.project.testpro.app'
versionCode 1
versionName '1.0.0'
}
}
In this example I add two product flavors: first for lite version and second for full version. Each version has his own versionCode and versionName (for Google Play publication).
In code just check BuildConfig.FLAVOR:
if (BuildConfig.FLAVOR == "lite") {
// add some ads or restrict functionallity
}
For running and testing on device use "Build Variants" tab in Android Studio to switch between versions: