Creating demo and full version app based on one code base/project - android

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:

Related

How to create packages in Android Studio for different gradle flavors

I am new to android programming. I just released my app. All works well and everything. However I was thinking of making a new flavor (free) version of the app by using the flavor feature of gradle.
Now all the tutorials and example of flavors that i see tell about storing exclusive classes of different flavors separate, for instance
com.example.myapp.free
com.example.myapp.paid
and keep the common files in main. Now my issue is, since i have already released the app, I cannot change the package name of my app to the .paid name as mentioned above. However my free version will implement the same class with different logic. If I do this, I get the duplicate class:com... error
How do i get around this situation?
Finally got the solution:
defined gradle config like this:
productFlavors {
free {
applicationId "com.blah.blah.free"
}
paid {
applicationId "com.blah.blah"
}
This allowed me to keep the release package same, and at the same time, I added learned the hard way to design and modularize app properly. I had make copies of my activity classes in both flavors and delete from main. Resource overriding automatically handles everything except the classes.

Google Play Store free and full app versions are in separate packages; how do I avoid duplicating future changes?

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.

how to install two instances by one apk?

I developed an app for android, but I need to install two instances of it, one for my daily use, another for debug/development, I don't have too many phones for debug, just have one phone, and don't want to debug on emulator, because it's too slow compare to real phone.
Or is there any thing we can change on APK file, then we can install it as another app, e.g. change it's package name ?
Currently, I changed the package name in code then make them to two apps, which can be installed on the same phone, but this way is not convenient. seek for simple way.
Update: is there any tool to modify package name in androidmanifest.xml directly after packaged(apk file)? then we just need unzip the apk, modify the androidmanifest.xml, zip the apk again.
You've answered the question yourself. You have to change the package name in the manifest, otherwise Android will override the old app (or can't install it, if the certificate differs).
Try changing the the name of the app in strings.xml from resource folder #string/app_name to have multiple instances of the same app. And package name must be changed so that the existing app is not overridden.
You can copy your project and change the package name in the copy.
You can use the same SVN path to apply the changes on the two projects.
Or you could automate the different builds using an ANT build.xml file with parameters. There are several examples on how to do this for Android in Google.
ref: One android application, one startup view, two icons
I would make the original app a library project and create a new project which uses the library project.
Advantage:
you can have both running as your new project should have a different package name
easily identification by overriding the app name in your new project (just add "beta" to it)
both versions can be installed on one device/emulator parallel
pretty good setup if you try to verify the update process of your app
no confusion with a version control system - renaming packages results in awful non-real changes on your development branches
Disadvantage:
you need to "uncheck" the library setting before you can release the original project
you might need to change some stuff in both manifest files which will increase the maintainability in a small manner
If you really need a market version of your app on your device, this method is the easiest one as a package rename will very probably result in worse maintainability.
edit:
You can mark a project as a library project in project preferences -> Android. After that you can link add that library project to another normal android project at the same spot, just click on the add button.

How to have different versions of an android project on the device?

I need to have different versions of my code on my device when I'm developing my android application. I want to have a copy of my latest code once in a week or so. The reason is that sometimes you make changes to the code and make it worse for a while, then after that you polish your code to include the features. So I need to have a copy of latest correctly running version of my code on the device.
I tried to change the app name, to see whether the ide deploys a new copy of my code, but it didn't work and the ide seems to be smarter than that and it replaces the app with the new name. I suspect that I need to change the package which is a little bit frustrating/risky. Anyone knows the solution?
Right now, I'm using Intellij to implement my android project but I think this doesn't matter.
You need to change the package name.
I use ant build script to do this easily. I created an ant task to rename the package name and make a build.
Typically I use svn to keep track of changes and label which ones are the ones that work then add features and use svn merge commands to combine new features with working code. Then if you want to undo something you can just roll back a revision.
The way I achieved that goal is:
- configure the original project as library
- create another project specifying a different package name in the manifest
- you also need to declare all the activities, receivers, etc with the full name in the new manifest
In that way switching the code of the original project through different branches you can create different apks and have different version of the app installed at the same on your device.
You need to change the package name, not the app name, it's pretty easy in Eclipse.
If your package name now is 'com.sina.perch', so just rename it to 'com.sina.perch1' or something else whatever in file 'AndroidManifest.xml' , which looks like:
It will be work.

Maintaining both free and pro versions of an application

I want to create a PRO version of my application for Android and was wondering how to structure my repository.
For know I have a trunk and feature branches. I'd like to put a pro version in another branch but maybe there is a better way? For example, maybe I should create two branches - one for free version, the other for pro?
Pro version will have additional features and will be ads-free, so eg. I don't want to include AdMob libraries in the pro version.
Do you have any experience or suggestions as to what would be the best way to structure the repository in this case?
EDIT:
I think I've found the best solution (for my app) in this thread: http://groups.google.com/group/android-developers/browse_thread/thread/4ad3d67f735f16d7/948b4f9eee2490a3
The trick discussed there is about having another application that only serves the purpose of unlocking PRO functionality in the actual application. The unlocking app is paid in the market and the actual app merely checks for the existence of it on the device.
I know you have already made your decision, but I have another suggestion that might help others.
I use git for my repository. Creating and maintaining branches is very easy. I have my master "pro" repository, and a "free" branch. I make all code changes to the master. My "free" branch only differs by whatever changes trigger the "free" behavior.
Whenever I'm done making changes to the code, I commit it to the master branch, then switch over to the free branch and use the "rebase" command to catch it up with the master.
It rolls back the change that makes it behave as the "free" version, applies the changes I made to master, then re-applies the "free" changes.
I don't have to maintain two versions. I don't have to remember to toggle some switch, or make the same changes back and forth. It's pretty slick, and I like it better than a second app that triggers the pro behavior because I can strip out libraries that aren't needed for the version in question.
I would suggest not maintaining two branches, but have either runtime or compile time switches to disable the PRO functionality for the free version. You could even remove not required DLL's when building.
Maintaining two branches means fixing problems in two places, which will become more of a problem as the branches inevitably diverge.
I found an easy way to do this in eclipse. I was quite surprised at how easy it was once I discovered it.
In project properties for com.app.free check the "Is Library" as true (you must have compiled the project at least once before changing this otherwise you get an error saying that library projects cannot be compiled, if you do get this error simply un-check it, compile, then re-check.
create new project com.app.pro
add com.app.free project as a library in the project settings in the android section of the pro porject
create new class MyApplication in com.app.pro and extend Application
override onCreate() NOTE: For those fellow copy/paste'ers this is NOT the same as the onCreate(Bundle savedInstanceState) bundle of an activity. You must remove the Bundle argument as this is an application not an activity.
Then add or set the static variable which will be read in the validation method to validate license. EX: IS_PRO = true; then validation method reads variable and returns true if IS_PRO is true.
Copy manifest contents form com.app.free to com.app.pro
add android:name="MyApplication " to the application tag in the com.app.pro manifest
append com.app.free in front of name attribute for all activities. (this makes the application know that your activities are to be found in the library package which is the free version) EX: android:name=".MainActivity" => android:name="com.app.free.MainActivity"
Now compile and you have a pro version
This method assumes you are using a global validation method. For example I created a class that connects users to a DB hosted on my domain which determines when the user first installed the app. For any pro only activities I check LicenseClass.isValidLicense() which compares dates and return true if its been less than the desired number of days. in the isValidLicense() function I check if Application.IS_PRO is set to true and return true if it is.
So now you can make as many changes however often and all you have to do is recompile both. The only thing to keep in mind is what ever changes you make in the com.app.free manifest have to be reflected in the pro. But this is the case with any application because android apps require you to declare which activities you are going to use no matter what.
NOTE: You may delete all assets and resources(dont't delete the res folder itself though) that are auto generated at project creation as they will not be used. Also, the only class file needed is the MyApplication file from step 3. Which means you may also delete the MainActivity.class that is auto generated as well since it is also never used. You may also remove any tags that are not used in the used in the pro version. EX: I have a BuyPro activity which opens if validation fails. Since validation will never fail in pro version it is not required. Of course all these deletions are optional just letting you know what I've learned.
CONS: The only con I found so far is that you can't use switch statements with your resource variables because they are no longer constants. So when you use a project as a library any variable you create in your strings.xml file for example are automatically overridden if you declare a variable of the same name in the pro version. For me this is not a con because I don't like using switch states in java because they limit you to switching on int type only and they require constant values. Which means in java I usually have to us if ... else staments anyway. Plus Eclipse will actually help convert switch statements if you put your cursor on the switch key word and press Ctrl+1 then click convert to if else. Also, I find it pretty useful that the resources are overridden because you can do things like change app_name from "app free" to "app pro" or upload a new drawable for say the app icon simply by creating the new version in the location where it exists in the free app. EX: if the res/values/string.xml contains say 100 string variables but all you need or want to change in the pro version is the app_name simply recreate the res/values/string.xml (NOT copy) and add the app_name variable. Now the app_name variable in the free version will be overridden which means the string.xml file in the pro version only needs to contain the 1 variable instead of 100 since its the only variable that changed. Easy Peasy. :-)
EDIT: I found out eclipse doesn't let yo export .apk's for libraries so you have to un-check the "Is Library" option in the free version after you've added it as a library in the pro version. As far as I can tell the only thing this does is causes eclipse not to warn you about the switch statement issue. Other than that it seems to work just fine.
Have a single version with public static final boolean IS_PRO that would determine free/pro behavior.
EDIT:
The package thing. Say, all your classes reside under com.myapp.android.free.
Then, in AndroidManifest.xml you declare package="com.myapp.android" for the paid version and package="com.myapp.android.free" for the free one.
If you use full names for activities, services, etc., you won't have to change anything else.
I wouldn't bother removing unused libs from the paid version. If you do, you'll have to do this manually.

Categories

Resources