Android應用自動更新功能代碼實現

因爲Android項目開源所致,市面上出現了N多安卓軟件市場。爲了讓咱們開發的軟件有更多的用戶使用,咱們須要向N多市場發佈,軟件升級後,咱們也必須到安卓市場上進行更新,給咱們增長了工做量。所以咱們有必要給咱們的Android應用增長自動更新的功能。html

既然實現自動更新,咱們首先必須讓咱們的應用知道是否存在新版本的軟件,所以咱們能夠在本身的網站上放置配置文件,存放軟件的版本信息:java

[html] view plaincopyandroid

  1. <update>  緩存

  2.     <version>2</version>  服務器

  3.     <name>baidu_xinwen_1.1.0</name>  網絡

  4.     <url>http://gdown.baidu.com/data/wisegame/f98d235e39e29031/baiduxinwen.apk</url>  app

  5. </update>  ide

在這裏我使用的是XML文件,方便讀取。因爲XML文件內容比較少,所以可經過DOM方式進行文件的解析:網站

[java] view plaincopyui

  1. public class ParseXmlService  

  2. {  

  3.     public HashMap<String, String> parseXml(InputStream inStream) throws Exception  

  4.     {  

  5.         HashMap<String, String> hashMap = new HashMap<String, String>();  

  6.           

  7.         // 實例化一個文檔構建器工廠  

  8.         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();  

  9.         // 經過文檔構建器工廠獲取一個文檔構建器  

  10.         DocumentBuilder builder = factory.newDocumentBuilder();  

  11.         // 經過文檔經過文檔構建器構建一個文檔實例  

  12.         Document document = builder.parse(inStream);  

  13.         //獲取XML文件根節點  

  14.         Element root = document.getDocumentElement();  

  15.         //得到全部子節點  

  16.         NodeList childNodes = root.getChildNodes();  

  17.         for (int j = 0; j < childNodes.getLength(); j++)  

  18.         {  

  19.             //遍歷子節點  

  20.             Node childNode = (Node) childNodes.item(j);  

  21.             if (childNode.getNodeType() == Node.ELEMENT_NODE)  

  22.             {  

  23.                 Element childElement = (Element) childNode;  

  24.                 //版本號  

  25.                 if ("version".equals(childElement.getNodeName()))  

  26.                 {  

  27.                     hashMap.put("version",childElement.getFirstChild().getNodeValue());  

  28.                 }  

  29.                 //軟件名稱  

  30.                 else if (("name".equals(childElement.getNodeName())))  

  31.                 {  

  32.                     hashMap.put("name",childElement.getFirstChild().getNodeValue());  

  33.                 }  

  34.                 //下載地址  

  35.                 else if (("url".equals(childElement.getNodeName())))  

  36.                 {  

  37.                     hashMap.put("url",childElement.getFirstChild().getNodeValue());  

  38.                 }  

  39.             }  

  40.         }  

  41.         return hashMap;  

  42.     }  

  43. }  

經過parseXml()方法,咱們能夠獲取服務器上應用的版本、文件名以及下載地址。緊接着咱們就須要獲取到咱們手機上應用的版本信息:

[java] view plaincopy

  1. /** 

  2.  * 獲取軟件版本號 

  3.  *  

  4.  * @param context 

  5.  * @return  

  6.  */  

  7. private int getVersionCode(Context context)  

  8. {  

  9.     int versionCode = 0;  

  10.     try  

  11.     {  

  12.         // 獲取軟件版本號,  

  13.         versionCode = context.getPackageManager().getPackageInfo("com.szy.update"0).versionCode;  

  14.     } catch (NameNotFoundException e)  

  15.     {  

  16.         e.printStackTrace();  

  17.     }  

  18.     return versionCode;  

  19. }  

經過該方法咱們獲取到的versionCode對應AndroidManifest.xml下android:versionCode。android:versionCode和android:versionName兩個屬性分別表示版本號,版本名稱。versionCode是整數型,而versionName是字符串。因爲versionName是給用戶看的,不太容易比較大小,升級檢查時,就能夠檢查versionCode。把獲取到的手機上應用版本與服務器端的版本進行比較,應用就能夠判斷處是否須要更新軟件。

處理流程


處理代碼

[java] view plaincopy

  1. package com.szy.update;  

  2.   

  3. import java.io.File;  

  4. import java.io.FileOutputStream;  

  5. import java.io.IOException;  

  6. import java.io.InputStream;  

  7. import java.net.HttpURLConnection;  

  8. import java.net.MalformedURLException;  

  9. import java.net.URL;  

  10. import java.util.HashMap;  

  11.   

  12. import android.app.AlertDialog;  

  13. import android.app.Dialog;  

  14. import android.app.AlertDialog.Builder;  

  15. import android.content.Context;  

  16. import android.content.DialogInterface;  

  17. import android.content.Intent;  

  18. import android.content.DialogInterface.OnClickListener;  

  19. import android.content.pm.PackageManager.NameNotFoundException;  

  20. import android.net.Uri;  

  21. import android.os.Environment;  

  22. import android.os.Handler;  

  23. import android.os.Message;  

  24. import android.view.LayoutInflater;  

  25. import android.view.View;  

  26. import android.widget.ProgressBar;  

  27. import android.widget.Toast;  

  28.   

  29. /** 

  30.  *@author coolszy 

  31.  *@date 2012-4-26 

  32.  *@blog http://blog.92coding.com 

  33.  */  

  34.   

  35. public class UpdateManager  

  36. {  

  37.     /* 下載中 */  

  38.     private static final int DOWNLOAD = 1;  

  39.     /* 下載結束 */  

  40.     private static final int DOWNLOAD_FINISH = 2;  

  41.     /* 保存解析的XML信息 */  

  42.     HashMap<String, String> mHashMap;  

  43.     /* 下載保存路徑 */  

  44.     private String mSavePath;  

  45.     /* 記錄進度條數量 */  

  46.     private int progress;  

  47.     /* 是否取消更新 */  

  48.     private boolean cancelUpdate = false;  

  49.   

  50.     private Context mContext;  

  51.     /* 更新進度條 */  

  52.     private ProgressBar mProgress;  

  53.     private Dialog mDownloadDialog;  

  54.   

  55.     private Handler mHandler = new Handler()  

  56.     {  

  57.         public void handleMessage(Message msg)  

  58.         {  

  59.             switch (msg.what)  

  60.             {  

  61.             // 正在下載  

  62.             case DOWNLOAD:  

  63.                 // 設置進度條位置  

  64.                 mProgress.setProgress(progress);  

  65.                 break;  

  66.             case DOWNLOAD_FINISH:  

  67.                 // 安裝文件  

  68.                 installApk();  

  69.                 break;  

  70.             default:  

  71.                 break;  

  72.             }  

  73.         };  

  74.     };  

  75.   

  76.     public UpdateManager(Context context)  

  77.     {  

  78.         this.mContext = context;  

  79.     }  

  80.   

  81.     /** 

  82.      * 檢測軟件更新 

  83.      */  

  84.     public void checkUpdate()  

  85.     {  

  86.         if (isUpdate())  

  87.         {  

  88.             // 顯示提示對話框  

  89.             showNoticeDialog();  

  90.         } else  

  91.         {  

  92.             Toast.makeText(mContext, R.string.soft_update_no, Toast.LENGTH_LONG).show();  

  93.         }  

  94.     }  

  95.   

  96.     /** 

  97.      * 檢查軟件是否有更新版本 

  98.      *  

  99.      * @return  

  100.      */  

  101.     private boolean isUpdate()  

  102.     {  

  103.         // 獲取當前軟件版本  

  104.         int versionCode = getVersionCode(mContext);  

  105.         // 把version.xml放到網絡上,而後獲取文件信息  

  106.         InputStream inStream = ParseXmlService.class.getClassLoader().getResourceAsStream("version.xml");  

  107.         // 解析XML文件。 因爲XML文件比較小,所以使用DOM方式進行解析  

  108.         ParseXmlService service = new ParseXmlService();  

  109.         try  

  110.         {  

  111.             mHashMap = service.parseXml(inStream);  

  112.         } catch (Exception e)  

  113.         {  

  114.             e.printStackTrace();  

  115.         }  

  116.         if (null != mHashMap)  

  117.         {  

  118.             int serviceCode = Integer.valueOf(mHashMap.get("version"));  

  119.             // 版本判斷  

  120.             if (serviceCode > versionCode)  

  121.             {  

  122.                 return true;  

  123.             }  

  124.         }  

  125.         return false;  

  126.     }  

  127.   

  128. /** 

  129.  * 獲取軟件版本號 

  130.  *  

  131.  * @param context 

  132.  * @return  

  133.  */  

  134. private int getVersionCode(Context context)  

  135. {  

  136.     int versionCode = 0;  

  137.     try  

  138.     {  

  139.         // 獲取軟件版本號,對應AndroidManifest.xml下android:versionCode  

  140.         versionCode = context.getPackageManager().getPackageInfo("com.szy.update"0).versionCode;  

  141.     } catch (NameNotFoundException e)  

  142.     {  

  143.         e.printStackTrace();  

  144.     }  

  145.     return versionCode;  

  146. }  

  147.   

  148.     /** 

  149.      * 顯示軟件更新對話框 

  150.      */  

  151.     private void showNoticeDialog()  

  152.     {  

  153.         // 構造對話框  

  154.         AlertDialog.Builder builder = new Builder(mContext);  

  155.         builder.setTitle(R.string.soft_update_title);  

  156.         builder.setMessage(R.string.soft_update_info);  

  157.         // 更新  

  158.         builder.setPositiveButton(R.string.soft_update_updatebtn, new OnClickListener()  

  159.         {  

  160.             @Override  

  161.             public void onClick(DialogInterface dialog, int which)  

  162.             {  

  163.                 dialog.dismiss();  

  164.                 // 顯示下載對話框  

  165.                 showDownloadDialog();  

  166.             }  

  167.         });  

  168.         // 稍後更新  

  169.         builder.setNegativeButton(R.string.soft_update_later, new OnClickListener()  

  170.         {  

  171.             @Override  

  172.             public void onClick(DialogInterface dialog, int which)  

  173.             {  

  174.                 dialog.dismiss();  

  175.             }  

  176.         });  

  177.         Dialog noticeDialog = builder.create();  

  178.         noticeDialog.show();  

  179.     }  

  180.   

  181.     /** 

  182.      * 顯示軟件下載對話框 

  183.      */  

  184.     private void showDownloadDialog()  

  185.     {  

  186.         // 構造軟件下載對話框  

  187.         AlertDialog.Builder builder = new Builder(mContext);  

  188.         builder.setTitle(R.string.soft_updating);  

  189.         // 給下載對話框增長進度條  

  190.         final LayoutInflater inflater = LayoutInflater.from(mContext);  

  191.         View v = inflater.inflate(R.layout.softupdate_progress, null);  

  192.         mProgress = (ProgressBar) v.findViewById(R.id.update_progress);  

  193.         builder.setView(v);  

  194.         // 取消更新  

  195.         builder.setNegativeButton(R.string.soft_update_cancel, new OnClickListener()  

  196.         {  

  197.             @Override  

  198.             public void onClick(DialogInterface dialog, int which)  

  199.             {  

  200.                 dialog.dismiss();  

  201.                 // 設置取消狀態  

  202.                 cancelUpdate = true;  

  203.             }  

  204.         });  

  205.         mDownloadDialog = builder.create();  

  206.         mDownloadDialog.show();  

  207.         // 如今文件  

  208.         downloadApk();  

  209.     }  

  210.   

  211.     /** 

  212.      * 下載apk文件 

  213.      */  

  214.     private void downloadApk()  

  215.     {  

  216.         // 啓動新線程下載軟件  

  217.         new downloadApkThread().start();  

  218.     }  

  219.   

  220.     /** 

  221.      * 下載文件線程 

  222.      *  

  223.      * @author coolszy 

  224.      *@date 2012-4-26 

  225.      *@blog http://blog.92coding.com 

  226.      */  

  227.     private class downloadApkThread extends Thread  

  228.     {  

  229.         @Override  

  230.         public void run()  

  231.         {  

  232.             try  

  233.             {  

  234.                 // 判斷SD卡是否存在,而且是否具備讀寫權限  

  235.                 if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))  

  236.                 {  

  237.                     // 得到存儲卡的路徑  

  238.                     String sdpath = Environment.getExternalStorageDirectory() + "/";  

  239.                     mSavePath = sdpath + "download";  

  240.                     URL url = new URL(mHashMap.get("url"));  

  241.                     // 建立鏈接  

  242.                     HttpURLConnection conn = (HttpURLConnection) url.openConnection();  

  243.                     conn.connect();  

  244.                     // 獲取文件大小  

  245.                     int length = conn.getContentLength();  

  246.                     // 建立輸入流  

  247.                     InputStream is = conn.getInputStream();  

  248.   

  249.                     File file = new File(mSavePath);  

  250.                     // 判斷文件目錄是否存在  

  251.                     if (!file.exists())  

  252.                     {  

  253.                         file.mkdir();  

  254.                     }  

  255.                     File apkFile = new File(mSavePath, mHashMap.get("name"));  

  256.                     FileOutputStream fos = new FileOutputStream(apkFile);  

  257.                     int count = 0;  

  258.                     // 緩存  

  259.                     byte buf[] = new byte[1024];  

  260.                     // 寫入到文件中  

  261.                     do  

  262.                     {  

  263.                         int numread = is.read(buf);  

  264.                         count += numread;  

  265.                         // 計算進度條位置  

  266.                         progress = (int) (((float) count / length) * 100);  

  267.                         // 更新進度  

  268.                         mHandler.sendEmptyMessage(DOWNLOAD);  

  269.                         if (numread <= 0)  

  270.                         {  

  271.                             // 下載完成  

  272.                             mHandler.sendEmptyMessage(DOWNLOAD_FINISH);  

  273.                             break;  

  274.                         }  

  275.                         // 寫入文件  

  276.                         fos.write(buf, 0, numread);  

  277.                     } while (!cancelUpdate);// 點擊取消就中止下載.  

  278.                     fos.close();  

  279.                     is.close();  

  280.                 }  

  281.             } catch (MalformedURLException e)  

  282.             {  

  283.                 e.printStackTrace();  

  284.             } catch (IOException e)  

  285.             {  

  286.                 e.printStackTrace();  

  287.             }  

  288.             // 取消下載對話框顯示  

  289.             mDownloadDialog.dismiss();  

  290.         }  

  291.     };  

  292.   

  293.     /** 

  294.      * 安裝APK文件 

  295.      */  

  296.     private void installApk()  

  297.     {  

  298.         File apkfile = new File(mSavePath, mHashMap.get("name"));  

  299.         if (!apkfile.exists())  

  300.         {  

  301.             return;  

  302.         }  

  303.         // 經過Intent安裝APK文件  

  304.         Intent i = new Intent(Intent.ACTION_VIEW);  

  305.         i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive");  

  306.         mContext.startActivity(i);  

  307.     }  

  308. }  

效果圖

檢查模擬器SDCARD是否存在下載文件:

相關文章
相關標籤/搜索