3/15/2011

Lessons Learned Maintaining Multiple Versions of an Android App

Since I've been trying to maintain both my GPSMap Pro and GPSMap Android applications, I've had to either refactor GPSMap Pro to be based upon updated code developed for GPSMap, or refactor GPSMap to be based upon code developed for GPSMap Pro. Tonight, I will be attempting the latter.

The first thing I do is back up and verify my backup of both applications. I've not had to restore from the backup yet, but this is just something that would be foolish to not do. A mistake or two and possibly either one or both of my applications could be damaged or gone, and should this occur, I can simply restore my backup(s). I use the Eclipse editor to do my development. It is easy to create a backup with the following choice from the menu:

File -> Export -> General -> Archive File -> Next -> Select Project -> Select To Archive File Path -> Finish.

To restore, you can delete the damaged project, and then import the archived file.

Second, I delete the project that is to be based upon the other project. In this case, I right clicked on the GPSMap project in Eclipse and choose Delete. Since, this only removes the project from Eclipse, and I want to keep all my projects in the same workspace, I then rename the directory for the project.

Third, I create a new project of the name that I want to be based upon the other project. Tonight, this is again the GPSMap project.

File -> New -> Android Project
Project Name: GPSMap
Selected Create New Project in Workspace
Either use default location, or use the Browse button to locate where to put the project
Select the Build target to match what API the applications use.
Enter the Package Name: com.appspot.wrightrocket.GPSMap
Unselect Create Activity
Click Finish

Fourth, I begin copying and pasting the various source files from the base project to the derived project. If someone knows an easier way, then I would gladly embrace it. I've tried importing, and creating a new project based upon an existing project. It seems what stops me from doing this is that I already have a project of that name in my workspace.

Shift click all in this directory, copy and then paste into this directory:
src/com.appspot.wrightrocket.GPSMapPro/* -> src/com.appspot.wrightrocket.GPSMap
src/com.android.vending.licensing -> src/ (Package doesn't exist so whole package pastes)
src/com.android.vending.licensing.util -> (Package doesn't exist so whole package pastes)
res/drawable -> res/ (The drawable directory doesn't exist so the whole directory pastes)
res/layout/* -> res/layout/ (Overwrite existing files)
res/values/* -> res/values/ (Overwrite existing files)
res/xml -> res/ (The xml directory doesn't exist so the whole directory pastes)
lib/* -> lib/ (Create lib directory with File -> New -> Folder)

Right Click GPSMap -> Build Path -> Add Jars -> GPSMap -> lib/GoogleAdView.jar -> OK

Fifth, I clean up any errors that might exist in the code. With the remaining source files that had errors, all that I had to do was delete some of the imports that referenced non-anonymous listeners in the code, and still referred to the base project (GPSMapPro instead of GPSMap).

This step went a lot smoother this time, since I have taken the following actions:

No class has public variables that are referenced by another class. Instead variables that need to be shared, are set or get using a SharedPreferences object. This was something that I had to refactor. It was a problem especially when the default activity for the application was the class that other classes referenced the public variables.

The class that is the default activity for the application is not named based upon the application name.

I'm thinking I should try to get rid of all non-anonymous listeners, and this step could be eliminated. For some reason, I can't seem to make an anonymous listener for the spinners...

Sixth, the res/values/strings.xml file needs to be edited so the app_name string is set correctly. Tonight, I just had to delete the word Pro. It was easy to search and manually replace GPSMapPro with just GPSMap.

Seventh, the PRO preference has to be changed to false. I set this in my main activity, but other activities can get this preference. This is how I can determine in my code whether the user is using the PRO version and alter the presentation of the application.

Eighth, I uncomment the code that displays the ads in the non-Pro version. Ouch! I just got my first glitch. The layout of the PRO version main activity does not have a R.id.adview, so I've got to either remember where I want to put that in the xml file, or I could restore the layout for that activity from the backup... In the future, this won't be necessary, as I set the layout now based upon the PRO variable.

Ninth, the AndroidManifest.xml file had to be updated. The package name in this case needed to be modified to remove the word Pro off the end. Also the permission for checking the license is not allowed in the free version.

About Me - WrightRocket

My photo

I've worked with computers for over 30 years, programming, administering, using and building them from scratch.

I'm an instructor for technical computer courses, an editor and developer of training manuals, and an Android developer.