Monday, August 04, 2014

USW-SVN+Git-ABS+ABC-ADT+Gradle = The Ultimate Refresh

The Ultimate Stopwatch is a pretty long running project in the Android scheme of things and when I kicked it off I had the source code in a CVS repo on a private server with regular(ish) backups.

In 2011 I relinquished the server and migrated to an SVN repo hosted on Google Code. But, setting up Subversion with any sort of IDE support is somewhat unpleasant, so I've decided to migrate again, this time to Git on GitHub. But SVN->Git isn't enough, so at the same time I'm throwing in a migration from ActionBarSherlock (thank you Jake Wharton) to ActionBarCompat and finally migrating the build from the Ant based Android Dev Tools to Gradle for good measure. Sometimes you just need to spring clean a project and sweep away the barriers holding back progress into new features like Custom Notifications, Cast and Android Wear.

There is more testing to do, but the new repo/build/actionbar are all in at and the new features will be coming soon.

By far the easiest step of the migration was getting from SVN to Git, although it should have been even easier. The 'git svn ...' command does a great job of reading every commit from the SVN repo and playing it back into the new Git repo, so you keep all the history. However git-svn didn't work on my Mac, all I achieved was the error "Can't locate SVN/ in @INC". Fortunately I wasn't the first and Victor Quinn's guide to fix the fact that git-svn is broken on Mavericks and Mountain Lion was most useful. After that it was plain sailing, creating the GitHub project and syncing the repo.

ActionBarSherlock to the Android Support Library AppCompat Action Bar was a little more painful and the only reason I voluntarily dived in was to gain access to MediaRouteProvider to later add Cast Support. A solid first step in using ActionBarCompat is to check out the G+ post and video by Chris Banes to pick up the basics.

Then I plugged through the following steps:
  1. Add a project dependancy on support-v7-appcompat, official guide
  2. Switch Activity/Fragment/Manager classes from:
    1. SherlockActivity ->
    2. SherlockFragment ->
    3. SherlockFragmentActivity ->
    4. SherlockListFragment ->
    5. SherlockFragmentManager  ->
  3. Switch the packages of a number of imports throughout the project:
    1. import com.actionbarsherlock.view.Menu -> android.view.Menu
    2. import com.actionbarsherlock.view.MenuItem -> android.view.MenuItem
    3. import com.actionbarsherlock.view.MenuInflater -> android.view.MenuInflater
    4. import com.actionbarsherlock.view.ActionMode -> android.view.ActionMode
    5. import ->
  4. Replace some Sherlock specific function calls:
    1. getSupportMenuInflater() -> getMenuInflater()
    2. getSherlockActionBar() -> getSupportActionBar()
    3. getSherlockActivity() -> getActivity()
    4. invalidateOptionsMenu -> supportInvalidateOptionsMenu()
  5. Update the menu.xml files to use the AppCompat implementation of app:showAsAction="" instead of android:showAsAction=""
  6. Fortunately I'd generated my ActionBarSherlock theme using Jeff Gilfelt's ActionBarStyleGenerator, so it was relatively simple to go back and generate the style for AppCompat and replace the theme in my project. I also has a couple of custom themes that were based on Sherlock styles e.g. '@style/Sherlock.Widget.ActionBar.Title', which needed switching to the AppCompat equivalent '@style/Widget.AppCompat.ActionBar.Title'
I was also using NineOldAndroids for the ValueAnimator backwards compatibility, but unfortunately there isn't a Support library version, so for project cleanliness I decided to deprecate the animations support for pre-ICS, add a little API-gating around those methods and remove the option from settings.

Part 2 will cover the migration from ADT to Gradle.


mwiththeat said...

Nice one Rich - Why not add transifex support next to crowd source the localisations.

Unknown said...

well I'd never heard of transifex before, have you used it?

Unknown said...

Thank you. This makes it much easier to take a look at it from inside Android Studio!