Android update checker

2 votes · 1 comment

Recently I've started to develop a few Android applications with some friends, and as soon as I started to make updates I faced a problem: how can I tell my beta testers to update to the latest test version? So I wrote UpdateChecker. It doesn't use the market, just a publicly accessible text file for version check.

For more details you can check it here: http://blog.fdev.eu/updatechecker/

raw ·
copy
· download
/** This is all you ned to be up and running **/ String VERSION_URL = "http://www.fdev.eu/sample_version.txt"; String REMOTE_APK_URL = "http://www.fdev.eu/sample.apk"; int ALERT_ICON = R.drawable.icon; UpdateChecker uc = new UpdateChecker(this, VERSION_URL, REMOTE_APK_URL, ALERT_ICON); uc.startUpdateChecker(); /** The class **/ /** * Version 1.0 - For latest version check here: http://blog.fdev.eu/updatechecker/ * @author Francesco Capano */ public class UpdateChecker { private String versionUrl; private String remoteApkUrl; private int alertIcon; private final String TAG_SUFFIX = "UpdateChecker"; private String TAG = TAG_SUFFIX; // The name of the saved file public String localApkName = "file.apk"; //The dialog that thells you to update public String alertTitle = "Update now"; public String alertMessage = "Download file and install"; //The dialog which notifies there was an error checking for updates public String alertTitleError = "Download error"; public String alertMessageError = "There was an error downloading the file"; //Download progress text public String progressMessage = "Downloading file..."; private Handler mHandler; private Context context; private Activity activity; private AlertDialog alertUpdate, alertError; private boolean enabled = true; /* This Thread checks for Updates in the Background */ private Thread checkUpdate; /** * Instantiates the update checker * @param c The activity to be used for displaying the messages * @param versionUrl The url of the file containing the version name * @param remoteApkUrl The url of the apk * @param alertIcon The icon to show in the dialog, usually the application icon */ public UpdateChecker(Activity c, String versionUrl, String remoteApkUrl, int alertIcon) { this.activity = c; this.context = c.getApplicationContext(); this.versionUrl = versionUrl; this.remoteApkUrl = remoteApkUrl; this.alertIcon = alertIcon; mHandler = new Handler(); } /** * Starts to check for updates */ public void startUpdateChecker() { if(!enabled) return; if(checkUpdate==null || !checkUpdate.isAlive() || checkUpdate.isInterrupted()) { checkUpdate = new Thread() { public void run() { checkupdate(); } }; checkUpdate.start(); } } /** * Interrupts update check */ public void stopUpdateChecker() { if(!enabled) return; if(checkUpdate.isAlive() && !checkUpdate.isInterrupted()) try { checkUpdate.interrupt(); } catch(Exception e) { Log.w(TAG, "checkUpdate.interrupt() exception"); // e.printStackTrace(); } } /* This Runnable creates a Dialog and asks the user to download the update */ private Runnable showError = new Runnable(){ public void run(){ alertError = new AlertDialog.Builder(activity) .setIcon(alertIcon) .setTitle(alertTitleError) .setMessage(alertMessageError) .setCancelable(true) .setPositiveButton("Ok", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { } }) .show(); } }; /* This Runnable creates an Error message*/ private Runnable showUpdate = new Runnable(){ public void run(){ alertUpdate = new AlertDialog.Builder(activity) .setIcon(alertIcon) .setTitle(alertTitle) .setMessage(alertMessage) .setCancelable(true) .setPositiveButton("Ok", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { Log.d(TAG, "TAG:Starting to download"); DownloadFilesTask downloadFile = new DownloadFilesTask(); downloadFile.execute(remoteApkUrl, localApkName); } }) .show(); } }; private void checkupdate() { if( alertUpdate!=null && alertUpdate.isShowing() ) { //(alertError!=null && alertError.isShowing()) || //There is already an download message return; } Log.v(TAG, "Checking updates..."); try { URL updateURL = new URL(versionUrl); URLConnection conn = updateURL.openConnection(); InputStream is = conn.getInputStream(); BufferedInputStream bis = new BufferedInputStream(is); ByteArrayBuffer baf = new ByteArrayBuffer(50); int current = 0; while((current = bis.read()) != -1){ baf.append((byte)current); } /* Convert the Bytes read to a String. */ final String s = new String(baf.toByteArray()); /* Get current Version Number */ String curVersion = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName; String newVersion = s; Log.d(TAG, "Current version is: " + curVersion + " and new one is: " + newVersion); /* Is a higher version than the current already out? */ if (!curVersion.equals(newVersion)) { /* Post a Handler for the UI to pick up and open the Dialog */ if(alertUpdate==null || !alertUpdate.isShowing()) { if(alertError!=null && alertError.isShowing()) alertError.dismiss(); mHandler.post(showUpdate); } } else Log.v(TAG, "The software is updated to the latest version: " + newVersion); } catch (Exception e) { e.printStackTrace(); // if(alertError==null || !alertError.isShowing()) // mHandler.post(showError); } } private class DownloadFilesTask extends AsyncTask<String, Integer, Integer> { private ProgressDialog mProgressDialog; private String outFileName; @Override protected void onPreExecute() { super.onPreExecute(); mProgressDialog = new ProgressDialog(activity); mProgressDialog.setMessage(progressMessage); mProgressDialog.setIndeterminate(false); mProgressDialog.setCancelable(false); mProgressDialog.setMax(100); mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); mProgressDialog.show(); } @Override protected Integer doInBackground(String... urls) { String inFileName = urls[0]; outFileName = urls[1]; try { //connecting to url URL u = new URL(inFileName); HttpURLConnection c = (HttpURLConnection) u.openConnection(); c.setRequestMethod("GET"); c.setDoOutput(true); c.connect(); //lenghtOfFile is used for calculating download progress int lenghtOfFile = c.getContentLength(); //this is where the file will be seen after the download OutputStream out = context.openFileOutput(outFileName, Context.MODE_WORLD_READABLE); // //file input is from the url InputStream in = c.getInputStream(); //here's the download code byte[] buffer = new byte[1024]; int readLenght = 0; long total = 0; int lastProgress = 0; while ((readLenght = in.read(buffer)) > 0) { total += readLenght; int cProgress = (int)((total*100)/lenghtOfFile); if(cProgress != lastProgress) { publishProgress((int)((total*100)/lenghtOfFile)); lastProgress = cProgress; } out.write(buffer, 0, readLenght); } out.flush(); out.close(); in.close(); Log.d(TAG, "Saved file with name: " + outFileName + " | Size: " + total); } catch (Exception e) { e.printStackTrace(); return 1; } return 0; } @Override public void onProgressUpdate(Integer... args){ mProgressDialog.setProgress(args[0]); } @Override protected void onPostExecute(Integer result) { mProgressDialog.dismiss(); if(result == 0) InstallFile(outFileName); else mHandler.post(showError); } } private void InstallFile(String fileName) { Log.d(TAG, "Installing file " + fileName); File file = new File(context.getFilesDir(), fileName); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); activity.startActivity(intent); } public boolean isEnabled() { return enabled; } public void disable() { enabled = false; } public void enable() { enabled = true; } public void setTagPrefix(String tagPrefix) { TAG = tagPrefix + " " + TAG_SUFFIX; } }
Add a comment

1 Comment

Reply · April 6, 2012, 10:18 a.m.