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
Application
object 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:versionCode
of the updated APK available for downloadgetUpdateURL()
returns aString
that 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 returnfalse
fromconfirm()
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:
-
ImmediateConfirmationStrategy
simply returnstrue
fromconfirm()
and is to be used in cases where we do not need user input to continue. For example, if you are usingAlarmManager
to 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. -
NotificationConfirmationStrategy
raises aNotification
that you supply. If the user taps on theNotification
in 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