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 https://github.com/geekyouup/ultimatestopwatch 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/Core.pm 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 -> android.support.v7.app.ActionBarActivity
    2. SherlockFragment -> android.support.v4.app.Fragment
    3. SherlockFragmentActivity -> android.support.v7.app.ActionBarActivity
    4. SherlockListFragment -> android.support.v4.app.ListFragment
    5. SherlockFragmentManager  -> android.support.v4.app.FragmentManager
  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 com.actionbarsherlock.app.ActionBar -> android.support.v7.app.ActionBar
  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.

Monday, July 01, 2013

Ultimate Stopwatch version 6.0.4


Fresh from being used to demo Android Studio at Google I/O, the Ultimate Stopwatch version 6.0.4 is rolling out with a couple more tweaks and bug fixes. This has also given me the opportunity to try the Google Play staged rollout feature.

First up, overdraw has been reduced again, this time by removing the background drawable for the window. 

    UltimateStopwatchActivity.onCreate(){
        getWindow().setBackgroundDrawable(null);
    }

Resulting in an almost totally green/blue layout, the only remaining red section is in the overlap of the minute and second hands. The screen was already drawing in a fraction of the time needed to maintain 60fps, so at this point it is really just optimizing for the sake of optimizing. Removing the window background had the side effect of a lap time screen without a background at all, leaving a hole in the UI and some freaky results. That was quickly resolved by setting a background color on that view.


I've gone one step further in an experimental version, which results in 0 overdraw for most of the app, but there are still a few margins left with no background color, so it needs a little more work and testing.

Another minor change in 6.0.4 was in the animation timing code. The animation runnable was already using postInvalidateOnAnimation() for JB+ devices, an optimization to cause redraws to happen on the next display frame:

    if(JELLYBEAN_OR_ABOVE) postInvalidateOnAnimation();
    else invalidate();


However, +ChrisBanes pointed out that there is a version of this in ViewCompat. ViewCompat is a backwards compatible helper provided in the Support Library for accessing View features introduced after API level 4. So, the custom view animation runnable now looks like this:


    //Stopwatch animation runnable
    private final Runnable animator = new Runnable() {
        @Override
        public void run() {
            updateWatchState(false);

            if(mIsRunning)
            {
                invalidate();
                removeCallbacks(this);
                ViewCompat.postOnAnimation(StopwatchCustomView.this, this);
            }
        }
    };

Which is more pleasing to the eye, easier to understand for devs reading the code and would benefit from any future advances in ViewCompat.

There are also a couple of other bug fixes in this release:

Issue #42: Fixed - Hands don't reset on Stopwatch when hand animations turned off.
Issue #47: Fixed - Ticking sounds go wrong during onPause onResume cycle.

As always the full source code to Ultimate Stopwatch is available at https://code.google.com/p/android-ultimatestopwatch

Saturday, February 23, 2013

Custom Paint Job: Accelerating the Ultimate Stopwatch

(Edit - 1st July 2013: Animator runnable updated again and one more layer of overdraw removed, details in new blog post)

Creating a custom Android view in 2013 isn't exactly breaking new ground, but the time was long overdue to relegate the old SurfaceView to history and move on; a task I was looking forward to but had kept putting off. Anyway, +Marie Schweiz's great new Ultimate Stopwatch designs deserved a hardware accelerated home.

The Android Developers training class breaks down the job of developing a Custom view into a few simple steps:
  1. Subclass a View
  2. Implement custom drawing
  3. Make the view interactive
In practice, when it came to the animations I also grabbed a couple of hints from Anders Ericsson's post at JayWay, as the mental model is also slightly different and I'd seen his related talk at Droidcon London 2012. In the SurfaceView I had a thread constantly looping to call the update/draw methods, however in a custom view it will redraw each time you call invalidate(). So, instead of a looping thread I can just call invalidate() after each cycle completes to start the next paint. This is done by posting a runnable to the View's message queue, I'm aiming for 15ms update cycles for just over 60fps.

    private Runnable animator = new Runnable() {
        @Override
        public void run() {
            updateWatchTime();
            invalidate();

            if (mIsRunning) postDelayed(this, 15);
        }
    };
The onDraw() methods from my SurfaceView and Custom view are identical, so just a copy and paste job there. The onTouch() and Activity communications handler also remained untouched. So in the end the Custom view is considerably simpler as there is no surface creation/destruction to worry about or separate thread to maintain.

A really nice feature of a Custom view is the ability to configure your own XML attributes. Previously I had to instantiate the SurfaceView and pass in details on whether it should represent the Stopwatch or Countdown view, with a Custom view I can add the following into attrs.xml

    <resources>
        <declare-styleable name="StopwatchCustomView">
            <attr name="watchType" format="enum">
                <enum name="stopwatch" value="1"/>
                <enum name="countdown" value="0"/>
            </attr>
        </declare-styleable>
    </resources>


Then by adding the name space xmlns:custom="http://schemas.android.com/apk/res-auto" in my layout, I can use the attribute custom:watchType="stopwatch" in the layout file and retrieve it in the code during instantiation. Being able to configure the custom view in XML can really simplify code and make the source easier to understand. Here is the code to retrieve the value:


    TypedArray a = context.getTheme().obtainStyledAttributes(
         attrs,
         R.styleable.StopwatchCustomView,
         0, 0);
    try{
        isStopwatch = a.getBoolean(R.styleable.StopwatchCustomView_watchType,true);
    }finally{
        a.recycle();
    }

That's it. The view is hardware accelerated where available and due to some optimizations the refresh rate has also increased when h/w acceleration is absent.

Some small improvements were gained by refactoring, but the main increases were delivered using the 'Show GPU overdraw' feature of Android's Developer Options, which is now available as I'm using the GPU to draw. It's immediately clear that before optimization there's excessive overdraw, highlighted by the red areas. This was almost entirely down to background colours being set on layers that weren't visible; the ViewPager, the layout of the custom view and also in the onDraw() of the Custom View. Eliminating these unseen, but still drawn, background colours reduced the graphics load and improved performance.


Now we have a wondrous, hardware accelerated Custom view we're in a much better position to add some final flourishes to improve the application. Later I'll write about some custom animations I've added, as suggested by +Nick Butcher to not only improve the perceived quality but also the usability.

The Ultimate Stopwatch and Timer is open source at android-ultimatestopwatch.googlecode.com, designed by +Marie Schweiz and makes use of the awesome ActionBarSherlock by Jake Wharton.

Friday, January 06, 2012

Ultimate Stopwatch & Timer finally updated!

Finally after almost a year of good intent, the updated version of Ultimate Stopwatch & Timer for Android has just gone live, v5.0.0. It'll be making its way through the interweb caches to an Android Market near you soon.

Thank you so much +Marie Schweiz (http://marie-schweiz.de/) for your awesome designs!

Updates:
- New clean design
- Action Bar on all versions (using ActionBarCompat)
- Touch feedback on all elements
- Light face for stopwatch, Dark face for countdown
- Lap Times separated out
- Built for Android 4.0 with support for versions 2.0+
- Portrait / Landscape layouts for all sceen sizes including QVGA and Tablets

Big fixes:
- Sporadic countdown alarm notifications fixed
- Galaxy Tab time appearance fixed
- QVGA layouts fixed
- Other minor issues resolved

Source available at http://android-ultimatestopwatch.googlecode.com
Comments and questions to the post on Google+ please so I can respond https://plus.google.com/u/0/115995639636688350464/posts/KhqUhC1ezB4

Monday, December 19, 2011

Android 4.0 ADB Backup / Restore

Android 4.0 ADB Backup/Restore
I switch phones quite a bit and the cloud is immensely useful for that, almost all of my #Android apps restore and most of the data is up there, even my wifi settings and wallpaper get reinstalled. But games are still lagging behind on this, they rarely keep their settings in the cloud or give a backup/restore option.

I really didn't want to lose my 'World of Goo' progress so I've just used adb backup/restore to pull it off one ICS device and push it onto another. Worked a treat.

The command lines I used:
> adb backup -f worldofgoo.bak com.twodboy.worldofgoofull
and a little dialog appears on the phone screen to confirm the backup and offer the chance to enter a password to protect.

> adb restore worldofgoo.bak
and another little dialog appears to confirm the restore

et voila, done. Other options on adb backup allow for full user data backups (-all), just type adb to see all options.


adb backup [-f ] [-apk|-noapk] [-shared|-noshared] [-all] [-system|-nosystem] []
- write an archive of the device's data to .
If no -f option is supplied then the data is written
to "backup.ab" in the current directory.
(-apk|-noapk enable/disable backup of the .apks themselves
in the archive; the default is noapk.)
(-shared|-noshared enable/disable backup of the device's
shared storage / SD card contents; the default is noshared.)
(-all means to back up all installed applications)
(-system|-nosystem toggles whether -all automatically includes
system applications; the default is to include system apps)
( is the list of applications to be backed up. If
the -all or -shared flags are passed, then the package
list is optional. Applications explicitly given on the
command line will be included even if -nosystem would
ordinarily cause them to be omitted.)

adb restore - restore device contents from the backup archive

Saturday, July 23, 2011

ViewPager example from PAUG

During a recent session at the Paris Android User Group (hi PAUG!) we did a live coding of a ViewPager example, it took around 5 minutes. What is a ViewPager? It is a tasty new class smothered in awesome sauce on a bed of rocking adapters, seriously I think I may use at least one in every Android app I make from now on. It was released as part of the updated Compatibility Package.

White on green was a great choice, right? very.... visible.

If you search for 'android view pager' you'll see many questions on how to implement smooth, finger tracking, horizontal view paging in Android, so it seems appropriate the solution is called ViewPager. ViewPager was launched at the end of last week as part of the updated Compatibility package and supports Android 1.6+.

Some of you may have been aware of the Workspace example open sourced with the I/O Sched app. An important difference between ViewPager and Workspace is that ViewPager pulls its views from an adapter, so like with a ListView as the items are slid off the screen they can be recycled and/or brought back in on the right side of the screen. The sample code for ViewPager shows this being done with a FragmentPagerAdapter, where each view is a fragment, giving you an amazing amount of control over your application.

In this example we are just sliding TextViews on and off the screen, here is the complete guide:

1) Download the update from Android SDK & AVD manager: Available Packages -> Android Repository -> Android Compatibility Package, revision 3. It will be installed in \extras\android\compatibility\v4

2) Create a new Android Project (I'm using Eclipse) and include the library. Properties -> Java Build Path -> Libraries -> Add External JARs -> android-support-v4.jar, it is in the install directory.
Update: As Thomas says if you're using the latest ADT you can now just right-click on your project -> Android Tools -> Add Compatibility Library

3) Your should now be able to use ViewPager in your Activity

4) If you use ViewPager in an xml layout, be sure to use the full reference, e.g.

<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/awesomepager"/>


5) Create a PagerAdapter to serve up your Views to the ViewPager. The key methods to implement are getCount(), instantiateItem(), destroyItem() and isViewFromObject() here are my implementations along with some JavaDoc from the source.

Note: It is up to the developer to add the views they are creating in instantiateItem() to the collection being passed in. The converse applies to destroyItem(), you must remove the item from the collection. The collection in this example is the ViewPager that is using the PagerAdapter.

The complete project source is at http://code.google.com/p/viewpagerexample/

A more professional and complete example can be found in the Compatibility Package samples (in the install directory), where a FragmentPagerAdapter implementation is provided. Using fragments inside a ViewPager can provide much better structure to an application as each view has its own FragmentActivity.

Tuesday, June 21, 2011

Supporting Honeycomb pt2: Updating the Ultimate Stopwatch

For most developers, taking advantage of the features of Honeycomb is also going to involve ensuring their app runs on tablets. It is one thing to do this right from the inception of an app or game, but often a much harder task to upgrade an already complete project to look great on larger screens.

If your app has multiple views then you can utilise fragments to show more than one of them at the same time. If not then you can think about any other data or views that may be able to augment it, or possibly increase the size of some elements.

In the case of the Ultimate Stopwatch the counting digits clearly need to be larger, then the remaining screen space can be used to include an easier to access list of lap times and split times. I mocked up some wire frames and settled on the following design.


So how do you make this magic happen? Well, as the Ultimate Stopwatch uses a SurfaceView and I spent so long getting the small screen UI right, I didn't really want to mess with it, so I'm going to leave it alone and just add new layouts for x-large devices. For many apps, especially those using standard layouts, it is less of an issue and the Android Compatibility package is the best option for a consistent application. I am however going to use fragments for the new layouts, to give me the best control over the larger screen whilst keeping my class files smaller. I'll have a fragment for the animated stopwatch view, one for the counter digits and one for the lap times.

1. In your project properties set the Android Build Target to 11

2. Tell Android that your app is optimised for Honeycomb by updating the androidmanifest.xml by adding <uses-sdk android:targetSdkVersion="11" /> as per my last post, which also shows how to enable hardware acceleration for good measure.

3. To totally segment my previous code I created a new Activity which decides which version of the app to launch based on OS version and screen size, not forgetting to update the AndroidManifest.xml.

4. I've done custom layouts for both landscape and portrait to give optimal experiences. As I'd used fragments it made the portrait view much easier, it only took a couple of minutes.

5. Another thing to remember is that your menu items will now appear in the Action Bar. It is good practice to let Android know which items it can hide under the overflow button if necessary by appending android:showAsAction="ifRoom" in to the item in your Menu.xml.

6. When building the layouts and activities, be mindful of the fragment lifecycle, making sure to inflate your views in the onCreateView() method.

7. To add a little more Honeycomb goodness I also used ObjectAnimator to do a 180 degree animation on the lap times fragment when switching to Countdown Mode and back again, this hides the times and informs the user of the mode the app is in. I also freshened up the Countdown time select dialog with the new NumberPicker.


Launching this update was also a great opportunity to refresh the Android Market listing, adding new screenshots, featured image and descriptions.

The full source of the Ultimate Stopwatch & Timer is available at http://code.google.com/p/android-ultimatestopwatch/

For those of you who want to know how USW looked in landscape on a tablet before this overhaul, prepare yourselves:


Follow me on twitter for further Android related updates.

Saturday, May 21, 2011

Supporting Honeycomb pt1: targetSdkVersion=11



Since the day I started at Google I've been trying to find the time to update all of my Android apps to support Honeycomb. However, I'm into my 3rd month and various distractions, like the awesome I/O, have meant that I haven't touched any of them.

So, here we go, part 1, Honeycomb support for 3 of the 9 apps I have live in the Android Market. I'll confess now that I've chosen the easiest 3, in fact they are all so easy that there is just one line to change. The apps are Auto Bright, Dimmer (Night Mode) and The Cleaner.

These apps all run in compatibility mode on Honeycomb, which means it shows the 'menu button' in the system bar to the right of the previous tasks, home and back buttons. To sort this out all you have to do is update the AndroidManifest to ensure it includes:

<uses-sdk android:targetSdkVersion="11"/>

Now that extra compatibility icon will vanish and technically these apps will support Honeycomb, perfect!

For the sake of completeness I've taken this opportunity to also furnish 'The Cleaner' with support for Honeycomb's Lights out Mode. This mode reduces the system bar elements on a Honeycomb device to small dots, making them less distracting. It is usually used for immersive experiences in games, video players, image galleries, etc...

To set Lights Out Mode on a view, just set the system UI visibility to STATUS_BAR_HIDDEN.

v.setSystemUiVisibility(View.STATUS_BAR_HIDDEN);


--- Updated 24/05/2011 ---
As WarGoth points out there is no need to use reflection to maintain backwards compatibility, simply wrapping the code in an android.os.Build.VERSION.SDK_INT>=android.os.Build.VERSION_CODES.HONEYCOMB check is sufficient. Clarification in the comments from Weeds that this only applies to Android 2.0+, the class loader would throw a java.lang.VerifyError on 1.5/1.6.

if(android.os.Build.VERSION.SDK_INT>=android.os.Build.VERSION_CODES.HONEYCOMB) {
    v.setSystemUiVisibility(View.STATUS_BAR_HIDDEN);
}

--- End ---

I did it slightly differently by using reflection to maintain compatibility with older versions of Android without duplicating classes:

Class classView = Class.forName("android.view.View");
Method methodSetSystemUIVisibility = classView.getDeclaredMethod("setSystemUiVisibility", int.class);
methodSetSystemUIVisibility.invoke(v,1);



The full source of these apps is available on Google Code

Part 2 of this series will take on converting one of my more complicated applications.

Tuesday, December 21, 2010

Android Nexus 1 Flashing - assert failed: write_raw_image("/tmp/boot.img", "boot") - solved

NOTE: I've since noticed that WiFi doesn't work with the method outlined below, however it does work with "fastboot boot boot.img" so further investigation is required. Some other users are saying that reflashing the hboot helps, but there are drawbacks to that as well.... Still if you are having this error and want to try gingerbread asap then the solution below is good:

It is a fun error isn't it, thousands of Nexus 1 users are happily flashing the latest ROMs onto their devices with no issues and when you try it you get something a little like this:

Installing update...
assert failed: write_raw_image("/tmp/boot.img", "boot")
E:Error in /sdcard/update.zip
(Status 7)
Installation aborted.


Same here, however there is light at the end of the tunnel. The problem is a lack of space to flash the new boot image, the cause could be one of two things:

1) You have some corrupted memory in the boot space, shrinking the size of the available boot partition and not allowing larger boot images to reside there.
2) This is a guess and I'd be interested in feedback: The Nexus 1 I use for custom ROMs is from the very very first Google seeding back in late 2009. I wonder if these devices had slightly smaller boot partitions.

Either way, there is a solution! The boot partition and the recovery partition are physically very similar, so after flashing the latest Gingerbread ROM (Gingerbread-Rooted-Gapps-v.06-signed.zip in this case, from the awesome XDA forums), I do this:

1) Extract boot.img from the ROMs zip file
2) Connect my N1 to my PC via USB
3) Boot the N1 into Fastboot by holding down the trackball when turning it on.
4) Flash the boot.img into the recovery partition:
"fastboot flash recovery boot.img" (fastboot is in the platform-tools directory of the SDK these days)

Now when I boot my Nexus 1 I hold down the trackball to get to Fastboot and then choose recovery mode, et voila Gingerbread launches.

If you need to get back to a real recovery mode you can either boot into Fastboot then boot a recovery image from your PC e.g. "fastboot boot recovery-RA-nexus-v2.0.0-CM.img"
Or reflash a recovery image, do your thing and then reflash the boot image.

I found this trick out at XDA Forums (where else?), here http://forum.xda-developers.com/showthread.php?t=731657

Wednesday, December 01, 2010

1 day into a relationship with the SonyEricsson LiveView

I absolutely love its geekiness. I'm running it with a stock Nexus 1 on 2.2.1. Yes It does disconnect all the time and I spend quite a lot of time turning it off and on again, re-pairing the bluetooth and generally willing it into life. But, I'll definitely knock a couple of apps up for it in the hope that SonyEricsson make a second generation device with a higher res screen, full touch support and a longer battery life. Some say the battery life is pathetic, but that is an understatement, a watch that doesn't get through half a day is crazy.

So far the best use for it is remote controlling the music players, i've had no problem with the built in Music remote control and my Nexus 1. It supports play/pause, volume control, next/previous track. The Where Am I plugin is ok, brings up a map of your current location on the LiveView. The GMail and SMS plugins don't seem particularly reliable, but I'll keep persisting.

Tuesday, August 24, 2010

Providing your Android Activity with a Theme

I've recently been asked a couple of times by new Android developers how 'Tech Buzz Widget' manages to overlay itself ontop of the desktop, allowing your wallpaper to show through. Assuming that it is easier to Google the answer than ask me, it may be somethiing that there isn't enough detail on already. So here is my 10 cents.

The main detail is to set the correct android:theme for your activity in the AndroidManifest.xml. For Tech Buzz Widget we used android:theme="@android:style/Theme.Translucent.NoTitleBar"

So the activity looked like this:

<activity android:name=".FullArticleView" class=".FullArticleView"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:configChanges="orientation|keyboardHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>


Once you've done that you you'll see that any elements of your layout that are transparent or unfilled will show through onto the underlying application or desktop. To make this more obvious in Tech Buzz we put a margin around the entire layout.

The exact details of all the activity themes available in the current Android platform are available in the Android source here: http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=core/res/res/values/themes.xml

Search for Theme.Translucent and you'll get the idea. There are fullscreen themes as well if you want to get rid of the notification bar. You can also define your own themes in a similar way.

Tuesday, June 15, 2010

1 Million Installs of Battery Widget for Android!!


As far as milestones go I'm thinking that this is a pretty big one. I've just returned from a trip to the Le Mans 24 hour race to find out that the first Android app that I submitted to the Market has shot through 1m installs. Fingers crossed that this is the one that gets you an E-mail from Mr Rubin ;)

Battery Widget is currently ranked 24th 'top free' application in the Productivity category in the UK and has been in the top 30 for over a year with a top 5 spot for a while. I'm thinking it may be time to revisit the app and sharpen it up for the higher res screens of today's Android devices and allow a few different colour combinations.

Although I'm super happy that Battery Widget is staying up the Android charts it is a double edged sword. As an Android fan-boi super-user fanatic there is definitely still an issue with freshness and churn in the top spots of the Free/Paid Android apps/games in the Market. The Market algorithm that is keeping Battery Widget up near the top for over a year is also making it hard for new apps to break through and for me as a user to find those exciting new applications. I'd 100% definitely sacrifice the popularity of this app for a more harsh ranking of older applications. I wonder what it would take now for a new application to enter the store and knock Battery Widget down a spot or two? It is still getting more new installs a day than all of my other apps combined.

You may say that the Market is favouring new Android users and making it easier for them to setup their devices with top apps, but there should be a better way for long time users of discovering new awesomeness without trawling through hundreds of pages of 'Just In' apps. The awesome apps are out there and I usually find multiple new great apps or games each time I have 15+ minutes to spare to 'trawl'. No doubt Google are fully aware of this and it'll just be a matter of time.

Thanks to all who have downloaded! Here's to the next Million.

Monday, April 12, 2010

Creating an Android Activity with no UI

Since I released 'Dimmer (Night Mode)' into the Android Market I've had a few Android devs asking how to create Activity based applications with no UI.
The answer is that you need to set the activity theme in the manifest, for dimmer I use:

android:theme="@android:style/Theme.Translucent.NoTitleBar"

like this in AndroidManifest.xml:

<activity android:name=".Dimmer"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>


The latest set of activity themes are defined in /res/values/themes.xml in the Android source here.

Which may not be particularly user friendly but it also demonstrates how you can create your own activity themes in your own /res/values/themes.xml if you so desire.

Note I'm not using the theme 'NoDisplay' as I do actually show notifications on the screen as the Activity is going about its business.

Sunday, February 21, 2010

Getting Started with a Nexus 1 - Apps, Hints & Tips

Quite a few of my friends, especially in the mobile industry, have aquired Nexus One's recently and more often than not it is their first foray into the world of Android.


Over the last couple of days I've been asked to help set several of them up with my preferred settings, applications, games, etc... So I'll maintain this post and from now on I can point people here.

First Boot
First and most importantly is that if you have multiple G-Mail and Google Apps accounts, make sure you sign in with your 'primary' one first. The N1 may have multiple GMail account support but it will only sync one calendar, the first one you enter. Also the first sync is going to use a whole bunch of data, so best to be on wifi.

If you received your Nexus 1 at MWC 2010 it will now inform you that a firmware update is ready. This update adds multi-touch support to the Browser, Gallery and Google Maps, go for it, it doesn't take long.

Android Usage Hints
Notification Bar - Top of the screen where the clock and battery level resides. New notifications from the apps on your phone will appear here. To see the detail of the notifications just drag the bar down.

Menu Button - On the N1 it is the second button in, above the trackball, with the 4 lines on it. Most apps have a Menu and this button makes it appear. Holding the button for a second also forces the On Screen Keyboard to appear, which can be a useful override at times.

Home Button - A bit like the button on the iPhone, always gets you back to your home screen. Hold it down to view the last 6 apps that you've run. These aren't necessarily still running.

Long Press - One of the interaction metaphors in Android, especially on items shown in a list. It is akin to the right click in Windows. Just touch and hold an item for a couple of seconds and sometimes a context sensitive menu will appear.

Stars - Look for small stars in the top right of UI's. They appear in G-Mail (you should know about them there for 'starring' mails), but they also appear on Google Maps for saving favourties if you long press on a location and touch the address bubble. Another place is in contacts, you can star a contact and then add a live-folder called 'Starred Contacts' to your home screen, keeping the most contacted people easy to access.

Widgets - Android allows Widgets to be displayed on all 5 of your N1's home screens. Press the 'Menu' button, then Add, Widgets. If the 'Add' button is greyed out then you probably don't have enough space on the current home screen to add another widget, try swiping to another one first.

Shortcuts - You can easily add shortcuts on your home screens, not only to apps but also Contacts, Bookmarks, etc. Go to Menu, Add, Shortcuts

Folders - Very handy at keeping related shortcuts together. I have a Games folder on my desktop with shortcuts to all my games in it. To change the name of a folder, open it then long press on the current name, a change name dialog will appear.

Google Search box / Search button: This little box or button can do a whole lot. It searches contacts, applications and the internet. Try it out, also supports voice search.

Settings
You can find your Nexus's settings by pressing the 'Menu' button, then selecting 'Settings'. For example I go into Settings -> Wireless & Networks -> Wi-Fi Settings -> Press 'Menu' Button -> Advanced -> Wi-Fi sleep policy, and set it to Never as I have issues with the N1 failing to reconnect to our office Network. Then I manage when wifi is on or off with the pre-installed 'Power Control' home screen widget.

Auto Screen Brightness is useful at getting the best out of the N1's OLED screen and battery life, it is in Settings -> Sound & Display -> Brightness -> Automatic brightness

Allow non-market application downloading/side-loading by going to Settings -> Applications -> Unknown sources

Add a little security to your N1 by setting an unlock pattern in Settings -> Locations & Security -> Set unlock pattern. If you enter the wrong pattern too many times the phone locks up until you re-enter your G-Mail password.

Check for System updates from time to time in Settings -> About Phone -> System Updates

Also in 'About Phone' there is an item 'Battery use' which shows you a breakdown of which apps are using the most battery.

Applications
Market: This is your app-store now, get used to it. All the following apps are in there somewhere. NOTE: If you don't have a SIM card in your phone, or if the Android Market doesn't support payments in your country you will not see any paid apps. It's a feature.

Google Maps: Updates to this are delivered via the Market, the latest update right now includes Multi-Touch and Google Buzz.

Google Listen: Number 1 podcasting app for Android, search for your podcasts or import them and let it get on with it.

beebPlayer: iPlayer for UK Android users, awesome, amazing, thank you.

Weather Widget - Free by Android Apps: In my opinion the best looking weather widget in the Market, I use the 2x1 'Weather Small' varient.

Barcode Scanner: QR Codes are a decent way of transferring data between devices, if this is installed you can not only scan QR Codes but also create them from Contacts, Clipboard, Bookmarks or Applications.

Seesmic: My current fave Twitter client for Android

Flickr Droid: One of several Flickr uploaders, does a decent enough job and adds a Share to Flickr intent into the Gallery sharing options.

London City / London Tube: Both very valuable for someone who uses the London Underground frequently. Between them you get a decent map, line status's, routing and live departure boards (as widgets!)

Qik: If you're into Qik'ing, then the Android client is solid.

gTasks: Syncs with your G-Mail tasks lists if you have any.

Battery Widget: (Yes it is one of mine) I like to know the exact battery level so I have this widget on one of my screens.

Tech/News/Gossip/Gaming Buzz Widgets & Buzz Deck: A set of Widgets/Apps from us at Mippin to keep you upto date with the latest news in your chosen category.

Astro: My favourite file manager for Android, always in beta but works well.

MP3 Store: The Amazon MP3 store is preinstalled on the N1, has previews, special offers and can be a tad dangerous when drunk.

Shazam, Ultimate Stopwatch (me again), Compass, Urban Spoon, i-Music, Google Googles are all also worth checking out

Games
Tower Defence games have taken off well on Android and there are quite a few around. The original was Plox, it is a year old now but worth a bash, the most popular is Robo Defence.

There are also many 'Flight Control' style games, my fave right now is 'Air Control', smooth gameplay, online scores and suitably difficult.

My top 3D games right now are Raging Thunder, Iron Sight, Breakout Legend

I still also like a good card game, there are loads.

Live Wallpapers
The Nexus 1 is the first Android device to support animated, interactive Wallpapers. Check out the preinstalled ones by pressing the 'Menu' Button, then Wallpaper, and Live wallpapers.

There are quite a few new ones now in the market including the 'Digital Rain' from the Matrix and my favourite 'Starfield 3D' which includes double tap for Hyper-space! I've knocked up 'Duck Paper' which is a Duck Hunt based Live Wallpaper, also available in the Market. We're intending on knocking a few more of these out over the next few weeks.

Rooting / Jail breaking

If you're top of your techy game and fancy being able to perform some more advanced functions on your Nexus 1 you need to get root access. Once done you'll be able to install apps for wired tether, wireless tether, screenshot, strobe light, boot animations, Apps to SD, no limits. You'll have super-user root access to your device in the terminal as well. The first stage of gaining root access is to unlock your bootloader, enabling the install of custom ROMs. Google were very clever about this and provided a simple method for doing it, but it warns you it will invalidate your warrenty and place an open padlock onto your boot screen.

I followed the guide over at Android & Me: http://androidandme.com/2010/01/hacks/video-how-to-unlock-and-root-a-nexus-one/

Thanks for reading and happy Android'ing

Wednesday, January 27, 2010

Android App Optimization: Using Reflection to test if an Android device is using 'Live Wallpapers'

I agree this may be a a pretty rare usecase, but I've just spent an hour figuring the details out so I thought it only polite to share them. Oneday, someone, somewhere may benefit.

What is Reflection?
It's been around almost as long as Java, described here and examples from Sun here

Why bother?
We've been receiving complaints that our Buzz Widgets are lagging on the Google Nexus One when Live Wallpapers are enabled. A little testing showed that this was down to the apps blurring out the desktop and rendering the content on top of it. If the desktop has a Live Wallpaper running on it, then blurring it eats some serious processor cycles. I understand that Reflection is more costly than directly calling the APIs, but this is just one simple call.

Why use reflection, not the actual API?
I'd much prefer to only have one version of each of our apps in the Android Market and the APIs for this only became available in the 2.1 SDK. Reflection enables us to use the APIs where available, whilst still letting the app run on devices with older firmwares.

How?
Well to get to the point we want to perform the test

if(WallpaperManager.getInstance(this).getWallpaperInfo() != null){//Live Paper, don't blur}

To do this with Reflection we have to use the methods Class.forName(""), Class.getDeclaredMethod() and Object.invoke() a little like this:


boolean blurBackground = true;
//get the WallpaperManager Class
Class classWallpaperManager = Class.forName("android.app.WallpaperManager");
if(classWallpaperManager != null)
{
//find its .getInstance(this) method
Method methodGetInstance = classWallpaperManager.getDeclaredMethod("getInstance", Context.class);
//invoke the WallpaperManager's .getInstance(this) method to get one
Object objWallpaperManager = methodGetInstance.invoke(classWallpaperManager, this);

//discover the WallpaperManager Object's .getWallpaperInfo() Method
Method methodGetWallpaperInfo = objWallpaperManager.getClass().getMethod("getWallpaperInfo", null);
//invoke it
Object objWallPaperInfo = methodGetWallpaperInfo.invoke(objWallpaperManager, null);
if(objWallPaperInfo!=null)
{
Log.d("WidgetDroid","WallpaperInfo not null");
blurBackground=false;
}
}

Also to ensure it is only run on Android 2.1+ devices I also wrap it in a quick Android Version check and a try/catch block for future safety:
if(Double.parseDouble(android.os.Build.VERSION.RELEASE)>=2.1){...}

Job done, now if the device is using a Live Wallpaper the apps background isn't blurred and all is well again in our Widget World.

Monday, January 25, 2010

The Android Market sweet spot & USW hits the 'final milestone'


The Ultimate Stopwatch & Timer for Android has just made it passed the 'final milestone' of 250,000 installs, great stuff. It's my second app to have reached the dizzy heights so far, the next is a couple of months away yet at around 150k. Seems like new device sales are keeping the install rates strong. Reaching 250k has a bizarre effect of dramatically increasing install rates. It is apparently a far more complelling proposition to install an app with >250k installs, almost as if the user starts believing they're missing out on something great. Battery Widget has rocketed from 250k to 450k installs in less than 2 months.




It seems, even though the Android Market is getting pretty busy these days, that if you focus on users desires it is still possible to get decent traction. Live Wallpapers are the sweet spot at the moment, they are being searched for by Nexus 1 users and a decent one will get thousands of downloads in the first week. I spent an hour creating 'Duck Paper' last week and it is now at 3,500 downloads. Content apps are a little trickier, especially if you don't have a recognised brand behind you, make them specific and easy to use, then update weekly.

Tuesday, January 12, 2010

Creating an Android 2.1 Live Wallpaper

Quick disclaimer: this isn't a tutorial, but a brief guide of what Live Wallpapers actually are and how I went about creating 'Duck Paper' - my first Android 2.1 Live Wallpaper. There are tutorials here, from Arno den Hond and here, from AndroGames.net

The Android 2.1 SDK was released today and the only major update was Live Wallpapers, so I thought I'd better find out what they are all about. What I found was quite surprising, I'd imagined that they would be some sort of animation or video playing on the desktop, a bit like MS DreamScene, but actually they are more akin to a an Android application open as the desktop. Live Wallpapers extend the WallpaperService class and the animations and interactions are handled in code, just like in a game. Realising this it seemed reasonable to try and port the only game I've written for Android, Duck Hunt, into a Live Wallpaper.

After less than an hour the first version of 'Duck Paper' was ready - as the ducks fly past in the background you can touch them to shoot them, then they fall off the screen.



Fortunately there is an example Live Wallpaper in the 2.1 SDK called CubeLiveWallpaper. This is definitely the starting point for anyone looking to create their own Live Wallpaper. I opened up this sample project, played with CubeLiveWallpaper1 and merged its Engine with Duck Hunt's SurfaceView code, et voila we have a Live Wallpaper.

Unfortunately I don't have an Android 2.1 device to try it on and it runs pretty slowly in the emulator. Once I've had it tested on a real device I'll put it in the Android Market.

Update: I've had it tested by a friend with a Nexus One and all seems well, so it is now live in the Android Market

Wednesday, December 16, 2009

Activate Motorola Droid / Milestone Multimedia Dock Mode with a magnet, Save £30

Some chap, not me, has figured out that the Motorola Multimedia Dock has a magnet in it which activates 'multimedia mode' on the Motorla Droid / Milestone Android devices, and guess what? it works!

Just put a magnet to the back of the device in the top left corner, like in the image below and it instantly says 'Multimedia Dock Connected', queue lots of cheap cardboard homebrew docs. You can even use your $$$$ phone as a digital picture frame.





Alternatively download DockRunner from the Android Market.

Monday, November 23, 2009

The Final Milestone?

From humble beginnings in a post on this blog in May the Battery Widget for Android has become a little more popular. The post from May shows it had 3061 installs and today I'm really rather chuffed to say it has just broken 250,000!!! In Android speak that's 'the final milestone'. The Android Market now lists Battery Widget as having '>250k' installs! Yay.

The install brackets are:
<50,
50 - 100
100 - 500
500 - 1,000
1,000 - 5,000
5,000 - 10,000
10,000 - 50,000
50,000 - 250,000
>250,000

You can get through the first 4 bands pretty quickly, but the last one has taken a while. Battery Widget is now high up in the Productivity Category and is receiving around 1,000 - 2,000 installs a day. Also with just under a 60% retention rate, it is still installed on around 150k devices.

The question that remains though, is whether or not 250k is actually the final milestone. Or is there a some secret next level, like >1,000,000 installs, accompanied by a letter from Andy Rubin maybe?

Friday, October 09, 2009

Buzz Deck reviewed on App Judgment

Being a fan of all things Revision 3, you can understand how shockingly happy I was when App Judgment reviewed Buzz Deck!



Now to work on those Cons... a new version is due today with custom web cards, and a faster UI!