Case study of online update for Android
I. Preparation for updating software
To update software online, we need a signed application. We need to put the software that has been signed into the server. My example is as follows:
Apk is an updated version with a signature!
The updateinfo.html code is as follows:
{Version: 2.0, description: all new versions are available. Please download them !, Apkurl: hhtp: // 172.23.252.89: 8080/MobileSafe2.0.apk}
II. Implementation of specific client software
The project structure is as follows:
The main business logic here is SplashActivity. java <喎?http: www.bkjia.com kf ware vc " target="_blank" class="keylink"> VcD4KPHByZSBjbGFzcz0 = "brush: java;"> Package com. xuliugen. mobilesafe; import java. io. byteArrayOutputStream; import java. io. file; import java. io. IOException; import java. io. inputStream; import java.net. httpURLConnection; import java.net. malformedURLException; import java.net. URL; import net. tsz. afinal. finalHttp; import net. tsz. afinal. http. ajaxCallBack; import org. json. JSONException; import org. json. JSONObject; import android. app. activity; import Droid. app. alertDialog; import android. app. alertDialog. builder; import android. content. dialogInterface; import android. content. intent; import android. content. dialogInterface. onCancelListener; import android. content. dialogInterface. onClickListener; import android. content. pm. packageInfo; import android. content. pm. packageManager; import android. content. pm. packageManager. nameNotFoundException; import android. ne T. uri; import android. OS. bundle; import android. OS. environment; import android. OS. handler; import android. OS. message; import android. view. view; import android. view. animation. alphaAnimation; import android. widget. textView; import android. widget. toast;/*** functions of the splash interface ** 1. display the product Logo; * 2. initialize the application; * 3. Check the version of the application; * 4. Check whether the current application is legally registered. *** use the signature * @ author xuliugen **/public class SplashActivity ext to update and install the application. Ends Activity {protected static final int SHOW_UPDATE_DIALOG = 0; protected static final int ENTER_HOME = 1; protected static final int URL_ERROR = 2; protected static final int NETWORK_ERROR = 3; protected static final int JSON_ERROR = 40; private TextView TV _splash_version; private TextView TV _update_info; // update progress private String description; // description of version information private String apkurl; // version update address @ Override pr Otected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_splash); TV _splash_version = (TextView) this. findViewById (R. id. TV _splash_version); TV _update_info = (TextView) findViewById (R. id. TV _update_info); TV _splash_version.setText (Version: + getVersionName (); // check for update checkUpdate (); // set the animation AlphaAnimation alphaAnimation = new AlphaAnimation (0.2f, 1.0f); alphaAnimation. setDuration (3000); // set the animation duration // execute the animation findViewById (R. id. rl_root_splash ). startAnimation (alphaAnimation);}/*** handler can be used because the updated interface is operated in the main thread, when the sub-thread ends, you can notify the main thread to perform related operations */private Handler handler = new Handler () {@ Override public void handleMessage (Message msg) {super. handleMessage (msg); // get the message sent by handler to process switch (msg. what) {case SHOW_UPDATE_DIALOG: // display the upgraded Dialog Box showUpdateDialog (); break; case ENTER_HOME: // enter enterHome (); break; case URL_ERROR: // URL error enterHome (); Toast. makeText (getApplicationContext (), URL error, 0 ). show (); break; case NETWORK_ERROR: // network exception enterHome (); Toast. makeText (SplashActivity. this, network exception, 0 ). show (); break; case JSON_ERROR: // JSON parsing error enterHome (); Toast. makeText (SplashActivity. this, JSON parsing error, 0 ). show (); break; default: break ;} };/*** Check whether a new version exists ** requires a network request. Generally, use */private void checkUpdate () {new Thread () {public void run () in the Child Thread () {// URL: http: // 172.23.252.89: 8080/updateinfo. json Message message = Message. obtain (); // get an existing information, used to store the updated information long startTime = System. currentTimeMillis (); try {URL url = new URL (getString (R. string. serverurl); // URL url = new URL (http: // 172.23.252.89: 8080/updateinfo. json); // HttpURLConn Ection httpURLConnection = (HttpURLConnection) url. openConnection (); httpURLConnection. setRequestMethod (GET); // sets the Request Method httpURLConnection. setConnectTimeout (4000); // set the timeout time int code = httpURLConnection. getResponseCode (); // get the response code if (code = 200) {// success InputStream inputStream = httpURLConnection. getInputStream (); // converts a stream to a String type ByteArrayOutputStream baos = new ByteArrayOutputStream (); byte [] buffer = New byte [1024]; int len = 0; while (len = inputStream. read (buffer ))! =-1) {baos. write (buffer, 0, len);} inputStream. close (); String result = baos. toString (); // obtain the string-type data baos. close (); // json parses JSONObject jsonObj = new JSONObject (result) because the obtained data is a json string ); // obtain the server version String version = (String) jsonObj. get (version); description = (String) jsonObj. get (description); apkurl = (String) jsonObj. get (apkurl); // check whether there is a new version if (getVersionName (). equals (version) {// consistent version, enter the main interface message. what = ENTER_HOME;} else {// There is a new version. A message is displayed in the upgrade dialog box. what = SHOW_UPDATE_DIALOG ;}} catch (MalformedURLException e) {message. what = URL_ERROR; e. printStackTrace ();} catch (IOException e) {message. what = NETWORK_ERROR; e. printStackTrace ();} catch (JSONException e) {message. what = JSON_ERROR; e. printStackTrace ();} finally {long endTime = System. currentTimeMillis (); long dTime = endTime-startTime; // time spent // 3 seconds in the interface if (dTime <3000) {try {Thread. sleep (3000-dTime);} catch (InterruptedException e) {e. printStackTrace () ;}} handler. sendMessage (message); // send the message }}}. start ();}/*** get the version name in the application layer order ** @ return */private String getVersionName () {// used to manage installed apk and uninstalled apk PackageManager packageManager = getPackageManager (); try {// get the apk function list file: to prevent errors, use getPackageName () method to obtain the package name // packageManager. getPackageInfo (com. xuliugen. mobilesafe, 0); PackageInfo packageInfo = packageManager. getPackageInfo (getPackageName (), 0); // return the version name return packageInfo. versionName;} catch (NameNotFoundException e) {e. printStackTrace (); return ;}}/*** the upgrade dialog box */protected void showUpdateDialog () {AlertDialog. builder builder = new Builder (this); builder. setTitle (upgrade prompt); // builder. setCancelable (false); // force upgrade: prevents the user from canceling the builder. setMessage (description); // set the information builder for dialog. setOnCancelListener (new OnCancelListener () {// @ Override public void onCancel (DialogInterface dialog) {// enter enterHome (); dialog on the home page. dismiss (); // cancel the display dialog box}); builder. setNegativeButton (next time, new OnClickListener () {// cancel @ Override public void onClick (DialogInterface dialog, int which) {// enter enterHome (); dialog. dismiss (); // cancel the display dialog box}); builder. setPositiveButton (upgrade now, new OnClickListener () {// confirm @ Override public void onClick (DialogInterface dialog, int which) {// download the APK and replace if (Environment. getExternalStorageState (). equals (Environment. MEDIA_MOUNTED) {// get the SD card status // sdcard exists // use afnal to download the apk file FinalHttp finalhttp = new FinalHttp (); // get the sdcard path String SDCARD_PATH = Environment. getExternalStorageDirectory (). getAbsolutePath () +/mobilesafe2.0.apk; finalhttp. download (apkurl, SDCARD_PATH, new AjaxCallBack () {@ Override public void onFailure (Throwable t, int errorNo, String strMsg) {t. printStackTrace (); Toast. makeText (getApplicationContext (), download failed, 1 ). show (); super. onFailure (t, errorNo, strMsg);}/*** count: total size * current: current download size */@ Override public void onLoading (long count, long current) {// download super. onLoading (count, current); TV _update_info.setVisibility (View. VISIBLE); // current download percentage int progress = (int) (current * 100/count); TV _update_info.setText (download progress: + progress + % );} /*** file t: indicates the File path */@ Override public void onSuccess (file t) {super. onSuccess (t); // install apk installAPK (t) when successful;}/*** install APK * @ param t: file Download path */private void installAPK (File t) {Intent intent = new Intent (); intent. setAction (android. intent. action. VIEW); intent. addCategory (android. intent. category. DEFAULT); intent. setDataAndType (Uri. fromFile (t), application/vnd. android. package-archive); startActivity (intent) ;}});} else {// sdcard does not have Toast. makeText (getApplicationContext (), no sdcard, please install it in the trial, 0 ). show (); return ;}}); builder. show ();}/*** enter the main interface */protected void enterHome () {Intent intent = new Intent (this, HomeActivity. class); startActivity (intent); // close the current page finish ();}}
The method used to convert data to a String type can be encapsulated as a tool class:
StreamTools. java
Package com. xuliugen. mobilesafe. utils; import java. io. byteArrayOutputStream; import java. io. IOException; import java. io. inputStream; /*** convert the stream to a String type ** @ author xuliugen **/public class StreamTools {/*** @ param is input stream * @ return String returned String * @ throws IOException */public static String readFromStream (InputStream is) throws IOException {ByteArrayOutputStream baos = new ByteArrayOutputStream () ; Byte [] buffer = new byte [1024]; int len = 0; while (len = is. read (buffer ))! =-1) {baos. write (buffer, 0, len);} is. close (); String result = baos. toString (); baos. close (); return result ;}}
Note: our signature must be kept in mind, but if you forget it, you can solve it as follows:
(1) Change the signature: this will not cover the installation. This is the case where the package name remains the same. This requires the user to uninstall the previous application first and the experience is poor!
(2) Change the package name: re-sign. This is equivalent to installing two applications on the mobile phone, but you can uninstall the first application using technology.