[Android] the Android program is automatically updated and the android program is automatically updated.
The steps for automatic App update are as follows:
The following three steps will be explained, with the corresponding code interspersed. The three steps of automatic App update are encapsulated into a separate Updater class and can be used directly, I will post the source code github address at the end of the article.
Updater example
Through a single classUpdater
You can easily automatically check updates, download installation packages, and install automatically. You can monitor the download progress and customize update prompts. The storage path can be freely written. If a directory in the path does not exist, it is automatically created, and the stream API interface is easy to use. The following is an example of using a line of code to handle Automatic Updates:
String savePath = Environment.getExternalStorageDirectory() + "/whinc/download/whinc.apk";String updateUrl = "http://192.168.1.168:8000/update.xml";Updater.with(mContext) .downloadListener(mListener) .update(updateUrl) .save(savePath) .create() .checkUpdate();
Step 1: Check for updates
This step requires the cooperation of the server. The server stores a configuration file in XML format (JSON or other formats can also be used) and provides it to the client to check for updates. The update. xml format is as follows:
<? Xml version = "1.0" encoding = "UTF-8"?> <Info> <version> <code> 4 </code> <name> 1.0.4 </name> </version> <url> http: // 192.168.1.168: 8000/test.apk </url> <description> Update the file. Fix the file and add the file to the file. </description> </info>
<version>
Tag specifies the server version number and version name. The version number and version name correspond toversionCode
AndversionName
(The Eclipse ADT project can be found in the tag in AndroidManifest. xml, and the Android Studio project is found in defaconfig config in module build. gradle ).
<url>
Tag specifies the APK,
<description>
Tag to specify the update content.
The client sends an HTTP request to the server for update. xml file, and then parse update. xml: Compares the server version with the local version. If the server version is later than the local version, it indicates that there is an update. download the latest APK specified in xml.
The following code checks for updates:
/*** Check the App version ** @ return returns true if a new version exists; otherwise, false */private boolean checkVersion () {URL url; HttpURLConnection httpConn = null; try {url = new URL (mCheckUpdateUrl); httpConn = (HttpURLConnection) url. openConnection (); httpConn. setConnectTimeout (200000); httpConn. setReadTimeout (200000); httpConn. setUseCaches (false); // disable cache for current http connection httpConn. connect (); if (httpConn. g EtResponseCode () = HttpURLConnection. HTTP_ OK) {InputStream inputStream = httpConn. getInputStream (); // Parse XML data if (! ParseXml (inputStream) {return false;} // compare the local version with the server version PackageInfo packageInfo = mContext. getPackageManager (). getPackageInfo (mContext. getPackageName (), 0); if (packageInfo. versionCode <mRemoteVersionCode) {return true ;}} else {return false ;}} catch (MalformedURLException e) {e. printStackTrace ();} catch (IOException e) {e. printStackTrace ();} catch (PackageManager. nameNotFoundException e) {e. printStackTrace ();} finally {httpConn. disconnect ();} return false ;}
First, create HTTPURLConnection to access the server update. xml file, and then parse the update. xml file, and save the version information, APK, and update log. After parsing, compare the current client version with the server version. If the server version is larger, the server has an updated version, the checkVersion () method returns true; otherwise, false.
Check the updated code below. Note that network requests in the main thread (UI thread) are not allowed in Android.checkVersion()
Must be placed in a non-main thread. There are multiple methods to implement asynchronous requests. Here I use AsyncTask.
public void checkUpdate() { new AsyncTask<Void, Void, Boolean>() { @Override protected Boolean doInBackground(Void... params) { boolean hasNewVersion = checkVersion(); return hasNewVersion; } @Override protected void onPostExecute(Boolean hasNewVersion) { super.onPostExecute(hasNewVersion); if (mCheckUpdateListener == null || !mCheckUpdateListener.onCompleted(hasNewVersion, mRemoteVersionCode, mRemoteVersionName, mUpdateLog, mApkDownloadUrl)) { if (hasNewVersion) { showUpdateDialog(); } } } }.execute(); }
Download the new APK installation package
showUpdateDialog()
After the call, the update prompt dialog box is displayed. Click the event button in the dialog box to create DownloadManager. request object, set various properties of the object, such as the download save path and notification bar title, and put the download Request in the download queue of the System Service DownloadManager, and hand it to the system for processing the download logic. To listen for download completion events, the broadcast is registered in the code.DownloadManager.ACTION_DOWNLOAD_COMPLETE
. The download progress is monitored by registering the ContentObserver.
/*** Display the update dialog box */private void showUpdateDialog () {AlertDialog. builder builder = new AlertDialog. builder (mContext); builder. setTitle (mTitle); builder. setMessage (mUpdateLog); builder. setPositiveButton (mDialogOkBtnTxt, new DialogInterface. onClickListener () {@ Override public void onClick (DialogInterface dialog, int which) {dialog. dismiss (); // download mDownloadMgr = (DownloadManager) mContext in the background. getSystem Service (Context. DOWNLOAD_SERVICE); DownloadManager. request request = new DownloadManager. request (Uri. parse (mApkDownloadUrl); if (Environment. getExternalStorageState (). equals (Environment. MEDIA_MOUNTED) {// if the Save path contains sub-directories, you need to recursively create the directory if (! CreateDirIfAbsent (mSavePath) {Log. e ("TAG", "apk save path can not be created:" + mSavePath); return;} request. setDestinationUri (Uri. fromFile (new File (mSavePath); request. setTitle (mNotificationTitle); request. setTitle (mNotificationMessage); // register the broadcast and listen to the download completion event mContext. registerReceiver (mCompleteReceiver, new IntentFilter (DownloadManager. ACTION_DOWNLOAD_COMPLETE); // register the listener to download the progress of mContext. getContentRe Solver (). registerContentObserver (Uri. parse ("content: // downloads/my_downloads"), true, mContentObserver); mDownloadId = mDownloadMgr. enqueue (request);} else {Log. e ("TAG", "can not access external storage! "); Return;} Toast. makeText (mContext, "downloading in the background... ", Toast. LENGTH_SHORT ). show () ;}}); builder. setNegativeButton (mDialogCancelBtnTxt, new DialogInterface. onClickListener () {@ Override public void onClick (DialogInterface dialog, int which) {dialog. cancel () ;}}); builder. create (). show ();}/*** if the directory specified by the path parameter does not exist, create the specified directory ** @ param path absolute path (including the file name, for example, '/sdcard/storage/download/test.apk') * @ retur N returns true if the directory is successfully created; otherwise, false */private boolean createDirIfAbsent (String path) {String [] array = path. trim (). split (File. separator); List <String> dirNames = Arrays. asList (array ). subList (1, array. length-1); StringBuilder pathBuilder = new StringBuilder (File. separator); for (String d: dirNames) {pathBuilder. append (d); File f = new File (pathBuilder. toString (); if (! F. exists ()&&! F. mkdir () {return false;} pathBuilder. append (File. separator) ;}return true ;}
Install APK
Once the Apk download is complete, a broadcast message will be received. you can install the APK. However, you must first use the download Id to determine whether the broadcast event was sent because of the completion of the APK download, because the system may have multiple download tasks at the same time, they are differentiated by the download id.
mCompleteReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); if (downloadId == mDownloadId) { installApk(); release(); } } };
The following is the installApk () method. First, retrieve the downloaded APK storage path from DownloadManager by the download Id, and then install the downloaded APK through Intent. The code is very simple. Note: Intent sets the identifierIntent.FLAG_ACTIVITY_NEW_TASK
Otherwise, the installation program cannot be started normally.
/*** Replace and install the current App. Note: The signature is consistent */private void installApk () {// obtain the downloaded APK address Uri apkUri = mDownloadMgr. getUriForDownloadedFile (mDownloadId); Intent intent = new Intent (Intent. ACTION_VIEW); intent. setFlags (Intent. FLAG_ACTIVITY_NEW_TASK); intent. setDataAndType (apkUri, "application/vnd. android. package-archive "); mContext. startActivity (intent );}
Github source code
Whinc/Android-UpdateManager
Good references:
DownloadManager | Android Developers
DownloadManager for Android download management
Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.