Work on this project has been suspended — please seek alternative solutions at this time
You might not be distributing your app through an online market
like the Android Market Google Play.
Perhaps your app is for internal-use
within a business, non-profit, or other organization. Perhaps
you are distributing a beta release to power users. Perhaps you
are selling your app directly to users rather than having a hunk
of your revenue go to markets.
In any of those cases, you will need to handle updating your app yourself, as no market will do that work for you.
Updater is a library designed to allow your app to be self-updating.
While the library ships with a stock implementation of things
like detecting a new version and downloading that new APK, you can
plug in your own implementations (e.g., do all this over the
corporate VPN).
This is available as a JAR file from the downloads area of this GitHub repo. The project itself is set up as an Android library project, in case you wish to use the source code in that fashion. Note that if you use the JAR, you will also need the JARs for the dependencies, listed later in this document.
Compared to many CWAC components, this one requires a fair of
explaining, even if the actual implementation is not that
difficult. You will see a sample implementation in the demo/
sub-project, and portions of that sample will be referenced here.
The Updater library uses a pluggable strategy approach, to allow
you to extend the library with your own implementations. There
are three types of strategies presently in use:
- a strategy for determining if there is an update available
- a strategy for downloading the update
- a strategy for confirming with the user if an update should be downloaded or if the downloaded update should now be installed
We will get into more details of the actual strategy interfaces, the stock implementations, and how you can write your own later in this document.
You will need to add the INTERNET, WAKE_LOCK, and
WRITE_EXTERNAL_STORAGE permissions to your manifest. In theory,
the latter one might not be required, if you implement your
own download strategy.
You will also need to add com.commonsware.cwac.updater.UpdateService
as a <service> to your manifest — no <intent-filter> is
required.
And, if you intend on using the NotificationConfirmationStrategy,
where the user will be prompted via a Notification to move to the
next phase of the update, you will also need to add
com.commonsware.cwac.updater.WakefulReceiver as a <receiver>
in your manifest. Once again, no <intent-filter> is
required.
The sample application demonstrates checking for updates from
onCreate() of an activity. That's certainly possible in production.
Other possibilities that should be supported (and represent bugs if they don't work) include:
-
Kicking off the update check from a custom
Applicationobject or a static data member, to basically check every time the process starts -
Scheduling an update check using
AlarmManager, either at a user-defined time/frequency or something likely to be reasonable (e.g., daily at 4am) -
Using C2DM to alert devices of an available update and starting the update process that way (though you should have some sort of fallback mechanism, as C2DM is not 100% reliable)
To have Updater check for new versions of your app and install
them, you need to create an instance of UpdateRequest.Builder
(in the com.commonsware.cwac.updater package), fill in the
strategies you want to use for the different phases, and tell
the Builder to execute() the work. The actual execution will all be done
on background threads, so it should be safe to do this work from
the main application thread if that is convenient.
For example, here is a sample Builder configuration and invocation:
UpdateRequest.Builder builder=new UpdateRequest.Builder(this);
builder.setVersionCheckStrategy(buildVersionCheckStrategy())
.setPreDownloadConfirmationStrategy(buildPreDownloadConfirmationStrategy())
.setDownloadStrategy(buildDownloadStrategy())
.setPreInstallConfirmationStrategy(buildPreInstallConfirmationStrategy())
.execute();You will need to supply the Builder with an implementation
of the VersionCheckStrategy interface. This object will be
responsible for determining if an update is available. This
interface requires two methods:
getVersionCode()returns theandroid:versionCodeof the updated APK available for downloadgetUpdateURL()returns aStringthat provides information on where to download the update from, with the typical implementation being an HTTP URL
Note that getUpdateURL() will not be called until after
getVersionCode() is called and returns. Hence, if you are
downloading information to determine update availability, do the
download in getVersionCode(), saving the URL for the update
in the VersionCheckStrategy object to return later via
getUpdateURL(). These methods are called on a background thread,
so they can take whatever time is needed and should return their
results synchronously.
There is a stock implementation of this interface, SimpleHttpVersionCheckStrategy,
that takes a URL of a JSON file to download. This JSON file needs
to be a JSON object (i.e., {}) with a versionCode integer and an
updateURL string property.
You will need to supply two ConfirmationStrategy objects to
the Builder. One will be used if getVersionCode() of the
VersionCheckStrategy indicates that there is an update available.
The other will be used once the DownloadStrategy has downloaded
the update.
The job of a ConfirmationStrategy is to confirm that we should
indeed move to the next phase of the work:
-
If an update is available, the
setPreDownloadConfirmationStrategy()will be used to confirm we should continue and download the update -
If the update has been downloaded, the
setPreInstallConfirmationStrategy()will be used to confirm that it is OK to go ahead and do the install
The only method required on ConfirmationStrategy is
confirm(). This returns a boolean, true indicating to go
ahead, false indicating that we don't know yet whether to go
ahead. confirm() is supplied two parameters:
- a generic
Context - a
PendingIntent, suitable for asynchronously triggering the next phase of the update process — use this if you returnfalsefromconfirm()and later determine that we should go ahead
confirm() is called on a background thread from a service,
so take that into account if you create a ConfirmationStrategy
that, say, wants to use a dialog — you will need to use
a dialog-themed Activity instead.
There are two stock implementations of ConfirmationStrategy
supplied:
-
ImmediateConfirmationStrategysimply returnstruefromconfirm()and is to be used in cases where we do not need user input to continue. For example, if you are usingAlarmManagerto check for updates in the middle of the night, it is usually safe to just go ahead and download now, without waiting for user input. -
NotificationConfirmationStrategyraises aNotificationthat you supply. If the user taps on theNotificationin the notification drawer, the process will continue. If the user clears theNotification, the process is abandoned.
You will need to supply an instance of a DownloadStrategy to
the Builder. This object is responsible for taking the "update URL"
from the VersionCheckStrategy and downloading the update APK
to a local file.
The only method required on DownloadStrategy is downloadAPK().
This returns a Uri to the downloaded APK. downloadAPK() receives
two parameters
- a generic
Context - the "update URL" from the
VersionCheckStrategy
There are two stock implementations of DownloadStrategy supplied
by the library: SimpleHttpDownloadStrategy, which downloads
the APK to external storage, and InternalHttpDownloadStrategy, which
downloads the APK to a world-readable file on internal storage.
Presently, neither clean up the
APK, though they will get rid of the old APK before downloading a
fresh update.
Ideally, use InternalHttpDownloadStrategy only for small APK files or
on API Level 11 or higher (where internal and external storage share the
same data partition, so space concerns fall away).
This project relies upon the CWAC WakefulIntentService project.
A copy of compatible JARs can be found in the libs/ directory
of the project, though you are welcome to try newer ones, or
ones that you have patched yourself.
This library at present requires Android 2.2 (API Level 8) or higher. To build the library, you will need API Level 14, as the library conditionally uses various newer APIs.
This is version v0.0.2 of this module, meaning it hasn't been laughed into oblivion just yet.
In the demo/ sub-project you will find
a sample activity that demonstrates the use of Updater.
The code in this project is licensed under the Apache Software License 2.0, per the terms of the included LICENSE file.
If you have questions regarding the use of this code, please post a question
on StackOverflow tagged with commonsware and android. Be sure to indicate
what CWAC module you are having issues with, and be sure to include source code
and stack traces if you are encountering crashes.
If you have encountered what is clearly a bug, or a feature request, please post an issue. Be certain to include complete steps for reproducing the issue.
Do not ask for help via Twitter.
Also, if you plan on hacking on the code with an eye for contributing something back, please open an issue that we can use for discussing implementation details. Just lobbing a pull request over the fence may work, but it may not.
- v0.0.2: added
InternalHttpDownloadStrategy - v0.0.1: initial release
