Android提示版本更新

http://blog.csdn.net/harvic880925/article/details/25191159

前言:在軟件開發的尾聲應該都會遇到這個問題,還好網上資料很多,所以基本不費什麼力氣就搞定了,現記錄於下。這裏用的PHP服務器。

 效果圖:(PHP服務器)

                   初始界面                      檢測後,如果已是最新版

                                        

如果不是最新版,提示更新                  正在下載                             安裝新程序    

     

 一、準備知識

 在AndroidManifest.xml裏定義了每個Android apk的版本標識:

[html] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     package="com.example.try_downloadfile_progress"  
  3.     android:versionCode="1"  
  4.     android:versionName="1.0" >  

其中,android:versionCode和android:versionName兩個字段分別表示版本代碼,版本名稱。versionCode是整型數字,versionName是字符串。由於version是給用戶看的,不太容易比較大小,升級檢查時,可以以檢查versionCode爲主,方便比較出版本的前後大小。
那麼,在應用中如何讀取AndroidManifest.xml中的versionCode和versionName呢?可以使用PackageManager的API,參考以下代碼:

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1.     /** 
  2.      * 獲取軟件版本號 
  3.      * @param context 
  4.      * @return 
  5.      */  
  6.     public static int getVerCode(Context context) {  
  7.         int verCode = -1;  
  8.         try {  
  9.             //注意:"com.example.try_downloadfile_progress"對應AndroidManifest.xml裏的package="……"部分  
  10.             verCode = context.getPackageManager().getPackageInfo(  
  11.                     "com.example.try_downloadfile_progress"0).versionCode;  
  12.         } catch (NameNotFoundException e) {  
  13.             Log.e("msg",e.getMessage());  
  14.         }  
  15.         return verCode;  
  16.     }  
  17.    /** 
  18.     * 獲取版本名稱 
  19.     * @param context 
  20.     * @return 
  21.     */  
  22.     public static String getVerName(Context context) {  
  23.         String verName = "";  
  24.         try {  
  25.             verName = context.getPackageManager().getPackageInfo(  
  26.                     "com.example.try_downloadfile_progress"0).versionName;  
  27.         } catch (NameNotFoundException e) {  
  28.             Log.e("msg",e.getMessage());  
  29.         }  
  30.         return verName;     
  31. }  

這裏要注意一個地方:代碼裏的“com.example.try_downloadfile_progress”對應AndroidManifest.xml裏的package="……"部分

二、XML代碼 

 XML代碼非常簡單,就是如初始化界面那樣,在裏面加一個BUTTON而已。代碼如下:

[html] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     tools:context=".MainActivity" >  
  6.   
  7.     <Button   
  8.         android:id="@+id/chek_newest_version"  
  9.         android:layout_width="fill_parent"  
  10.         android:layout_height="wrap_content"  
  11.         android:layout_margin="5dip"  
  12.         android:text="檢測最新版本"/>  
  13.   
  14. </RelativeLayout>  

三、輔助類構建(Common)

 這裏爲了開發方便,將一些公共的函數,單獨放在Common類中實現,代碼如下:

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. package com.example.try_downloadfile_progress;  
  2. /** 
  3.  * @author harvic 
  4.  * @date 2014-5-7 
  5.  * @address http://blog.csdn.net/harvic880925 
  6.  */  
  7. import java.io.BufferedReader;  
  8. import java.io.InputStreamReader;  
  9. import java.util.List;  
  10.   
  11. import org.apache.http.HttpResponse;  
  12. import org.apache.http.NameValuePair;  
  13. import org.apache.http.client.entity.UrlEncodedFormEntity;  
  14. import org.apache.http.client.methods.HttpPost;  
  15. import org.apache.http.impl.client.DefaultHttpClient;  
  16. import org.apache.http.protocol.HTTP;  
  17.   
  18. import android.content.Context;  
  19. import android.content.pm.PackageManager.NameNotFoundException;  
  20. import android.util.Log;  
  21.   
  22. public class Common {  
  23.     public static final String SERVER_IP="http://192.168.1.105/";  
  24.     public static final String SERVER_ADDRESS=SERVER_IP+"try_downloadFile_progress_server/index.php";//軟件更新包地址  
  25.     public static final String UPDATESOFTADDRESS=SERVER_IP+"try_downloadFile_progress_server/update_pakage/baidu.apk";//軟件更新包地址  
  26.   
  27.     /** 
  28.      * 向服務器發送查詢請求,返回查到的StringBuilder類型數據 
  29.      *  
  30.      * @param ArrayList 
  31.      *            <NameValuePair> vps POST進來的參值對 
  32.      * @return StringBuilder builder 返回查到的結果 
  33.      * @throws Exception 
  34.      */  
  35.     public static StringBuilder post_to_server(List<NameValuePair> vps) {  
  36.         DefaultHttpClient httpclient = new DefaultHttpClient();  
  37.         try {  
  38.             HttpResponse response = null;  
  39.             // 創建httpost.訪問本地服務器網址  
  40.             HttpPost httpost = new HttpPost(SERVER_ADDRESS);  
  41.             StringBuilder builder = new StringBuilder();  
  42.   
  43.             httpost.setEntity(new UrlEncodedFormEntity(vps, HTTP.UTF_8));  
  44.             response = httpclient.execute(httpost); // 執行  
  45.   
  46.             if (response.getEntity() != null) {  
  47.                 // 如果服務器端JSON沒寫對,這句是會出異常,是執行不過去的  
  48.                 BufferedReader reader = new BufferedReader(  
  49.                         new InputStreamReader(response.getEntity().getContent()));  
  50.                 String s = reader.readLine();  
  51.                 for (; s != null; s = reader.readLine()) {  
  52.                     builder.append(s);  
  53.                 }  
  54.             }  
  55.             return builder;  
  56.   
  57.         } catch (Exception e) {  
  58.             // TODO: handle exception  
  59.             Log.e("msg",e.getMessage());  
  60.             return null;  
  61.         } finally {  
  62.             try {  
  63.                 httpclient.getConnectionManager().shutdown();// 關閉連接  
  64.                 // 這兩種釋放連接的方法都可以  
  65.             } catch (Exception e) {  
  66.                 // TODO Auto-generated catch block  
  67.                 Log.e("msg",e.getMessage());  
  68.             }  
  69.         }  
  70.     }  
  71.       
  72.     /** 
  73.      * 獲取軟件版本號 
  74.      * @param context 
  75.      * @return 
  76.      */  
  77.     public static int getVerCode(Context context) {  
  78.         int verCode = -1;  
  79.         try {  
  80.             //注意:"com.example.try_downloadfile_progress"對應AndroidManifest.xml裏的package="……"部分  
  81.             verCode = context.getPackageManager().getPackageInfo(  
  82.                     "com.example.try_downloadfile_progress"0).versionCode;  
  83.         } catch (NameNotFoundException e) {  
  84.             Log.e("msg",e.getMessage());  
  85.         }  
  86.         return verCode;  
  87.     }  
  88.    /** 
  89.     * 獲取版本名稱 
  90.     * @param context 
  91.     * @return 
  92.     */  
  93.     public static String getVerName(Context context) {  
  94.         String verName = "";  
  95.         try {  
  96.             verName = context.getPackageManager().getPackageInfo(  
  97.                     "com.example.try_downloadfile_progress"0).versionName;  
  98.         } catch (NameNotFoundException e) {  
  99.             Log.e("msg",e.getMessage());  
  100.         }  
  101.         return verName;     
  102. }     
  103.       
  104. }  


這裏除了上面我們提到的兩個函數getVerCode和getVerName外,還有幾個常量和一個函數定義,含義分別如下:

SERVER_IP:服務器IP地址(大家在拿到試驗的時候,要改成自己服務器IP地址) 
SERVER_ADDRESS:android程序要將請求發送到的頁面地址,無須更改。
UPDATESOFTADDRESS:更新安裝包存放的位置,無須更改。

 函數StringBuilder post_to_server(List<NameValuePair> vps)是訪問服務器並返回結果的功能封裝。傳進去名值對,返回StringBuilder對象

 四、主頁面代碼構建

 1、首先設置AndroidManifest.xml,使其能訪問網絡和SD卡

在</manifest>標籤上面,加入:

[html] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. <uses-permission android:name="android.permission.INTERNET" >  
  2. </uses-permission>  
  3. <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" >  
  4. </uses-permission>  
  5. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" >  
  6. </uses-permission>  

2、主頁代碼:

先貼出全部代碼,然後逐步講解,全部代碼如下:

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. package com.example.try_downloadfile_progress;  
  2. /** 
  3.  * @author harvic 
  4.  * @date 2014-5-7 
  5.  * @address http://blog.csdn.net/harvic880925 
  6.  */  
  7. import java.io.File;  
  8. import java.io.FileOutputStream;  
  9. import java.io.IOException;  
  10. import java.io.InputStream;  
  11. import java.util.ArrayList;  
  12. import java.util.List;  
  13.   
  14. import org.apache.http.HttpEntity;  
  15. import org.apache.http.HttpResponse;  
  16. import org.apache.http.NameValuePair;  
  17. import org.apache.http.client.ClientProtocolException;  
  18. import org.apache.http.client.HttpClient;  
  19. import org.apache.http.client.methods.HttpGet;  
  20. import org.apache.http.impl.client.DefaultHttpClient;  
  21. import org.apache.http.message.BasicNameValuePair;  
  22. import org.json.JSONArray;  
  23.   
  24. import android.net.Uri;  
  25. import android.os.AsyncTask;  
  26. import android.os.Bundle;  
  27. import android.os.Environment;  
  28. import android.os.Handler;  
  29. import android.app.Activity;  
  30. import android.app.AlertDialog;  
  31. import android.app.Dialog;  
  32. import android.app.ProgressDialog;  
  33. import android.content.DialogInterface;  
  34. import android.content.Intent;  
  35. import android.util.Log;  
  36. import android.view.View;  
  37. import android.view.View.OnClickListener;  
  38. import android.widget.Button;  
  39.   
  40. public class MainActivity extends Activity {  
  41.   
  42.     Button m_btnCheckNewestVersion;  
  43.     long m_newVerCode; //最新版的版本號  
  44.     String m_newVerName; //最新版的版本名  
  45.     String m_appNameStr; //下載到本地要給這個APP命的名字  
  46.       
  47.     Handler m_mainHandler;  
  48.     ProgressDialog m_progressDlg;  
  49.     @Override  
  50.     protected void onCreate(Bundle savedInstanceState) {  
  51.         super.onCreate(savedInstanceState);  
  52.         setContentView(R.layout.activity_main);  
  53.           
  54.         //初始化相關變量  
  55.         initVariable();  
  56.           
  57.         m_btnCheckNewestVersion.setOnClickListener(btnClickListener);  
  58.     }  
  59.     private void initVariable()  
  60.     {  
  61.         m_btnCheckNewestVersion = (Button)findViewById(R.id.chek_newest_version);  
  62.         m_mainHandler = new Handler();  
  63.         m_progressDlg =  new ProgressDialog(this);  
  64.         m_progressDlg.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);  
  65.          // 設置ProgressDialog 的進度條是否不明確 false 就是不設置爲不明確       
  66.         m_progressDlg.setIndeterminate(false);      
  67.         m_appNameStr = "haha.apk";  
  68.     }  
  69.       
  70.     OnClickListener btnClickListener = new View.OnClickListener() {  
  71.           
  72.         @Override  
  73.         public void onClick(View v) {  
  74.             // TODO Auto-generated method stub  
  75.             new checkNewestVersionAsyncTask().execute();  
  76.         }  
  77.     };  
  78.       
  79.     class checkNewestVersionAsyncTask extends AsyncTask<Void, Void, Boolean>  
  80.     {  
  81.   
  82.         @Override  
  83.         protected Boolean doInBackground(Void... params) {  
  84.             // TODO Auto-generated method stub  
  85.             if(postCheckNewestVersionCommand2Server())  
  86.             {  
  87.                 int vercode = Common.getVerCode(getApplicationContext()); // 用到前面第一節寫的方法    
  88.                  if (m_newVerCode > vercode) {    
  89.                      return true;  
  90.                  } else {    
  91.                      return false;  
  92.                  }    
  93.             }  
  94.             return false;  
  95.         }  
  96.           
  97.         @Override  
  98.         protected void onPostExecute(Boolean result) {  
  99.             // TODO Auto-generated method stub  
  100.             if (result) {//如果有最新版本  
  101.                 doNewVersionUpdate(); // 更新新版本    
  102.             }else {  
  103.                 notNewVersionDlgShow(); // 提示當前爲最新版本    
  104.             }  
  105.             super.onPostExecute(result);  
  106.         }  
  107.           
  108.         @Override  
  109.         protected void onPreExecute() {  
  110.             // TODO Auto-generated method stub  
  111.             super.onPreExecute();  
  112.         }  
  113.     }  
  114.       
  115.     /** 
  116.      * 從服務器獲取當前最新版本號,如果成功返回TURE,如果失敗,返回FALSE 
  117.      * @return 
  118.      */  
  119.     private Boolean postCheckNewestVersionCommand2Server()  
  120.     {  
  121.         StringBuilder builder = new StringBuilder();  
  122.         JSONArray jsonArray = null;  
  123.         try {  
  124.             // 構造POST方法的{name:value} 參數對  
  125.             List<NameValuePair> vps = new ArrayList<NameValuePair>();  
  126.             // 將參數傳入post方法中  
  127.             vps.add(new BasicNameValuePair("action""checkNewestVersion"));  
  128.             builder = Common.post_to_server(vps);  
  129.             jsonArray = new JSONArray(builder.toString());  
  130.             if (jsonArray.length()>0) {  
  131.                 if (jsonArray.getJSONObject(0).getInt("id") == 1) {  
  132.                     m_newVerName = jsonArray.getJSONObject(0).getString("verName");  
  133.                     m_newVerCode = jsonArray.getJSONObject(0).getLong("verCode");  
  134.                       
  135.                     return true;  
  136.                 }  
  137.             }  
  138.       
  139.             return false;  
  140.         } catch (Exception e) {  
  141.             Log.e("msg",e.getMessage());  
  142.             m_newVerName="";  
  143.             m_newVerCode=-1;  
  144.             return false;  
  145.         }  
  146.     }  
  147.       
  148.     /** 
  149.      * 提示更新新版本 
  150.      */  
  151.         private void doNewVersionUpdate() {  
  152.             int verCode = Common.getVerCode(getApplicationContext());    
  153.             String verName = Common.getVerName(getApplicationContext());    
  154.               
  155.             String str= "當前版本:"+verName+" Code:"+verCode+" ,發現新版本:"+m_newVerName+  
  156.                     " Code:"+m_newVerCode+" ,是否更新?";    
  157.             Dialog dialog = new AlertDialog.Builder(this).setTitle("軟件更新").setMessage(str)    
  158.                     // 設置內容    
  159.                     .setPositiveButton("更新",// 設置確定按鈕    
  160.                             new DialogInterface.OnClickListener() {    
  161.                                 @Override    
  162.                                 public void onClick(DialogInterface dialog,    
  163.                                         int which) {   
  164.                                     m_progressDlg.setTitle("正在下載");    
  165.                                     m_progressDlg.setMessage("請稍候...");    
  166.                                     downFile(Common.UPDATESOFTADDRESS);  //開始下載  
  167.                                 }    
  168.                             })    
  169.                     .setNegativeButton("暫不更新",    
  170.                             new DialogInterface.OnClickListener() {    
  171.                                 public void onClick(DialogInterface dialog,    
  172.                                         int whichButton) {    
  173.                                     // 點擊"取消"按鈕之後退出程序    
  174.                                     finish();    
  175.                                 }    
  176.                             }).create();// 創建    
  177.             // 顯示對話框    
  178.             dialog.show();    
  179.         }  
  180.         /** 
  181.          *  提示當前爲最新版本   
  182.          */  
  183.         private void notNewVersionDlgShow()  
  184.         {  
  185.             int verCode = Common.getVerCode(this);    
  186.             String verName = Common.getVerName(this);   
  187.             String str="當前版本:"+verName+" Code:"+verCode+",/n已是最新版,無需更新!";  
  188.             Dialog dialog = new AlertDialog.Builder(this).setTitle("軟件更新")    
  189.                     .setMessage(str)// 設置內容    
  190.                     .setPositiveButton("確定",// 設置確定按鈕    
  191.                             new DialogInterface.OnClickListener() {    
  192.                                 @Override    
  193.                                 public void onClick(DialogInterface dialog,    
  194.                                         int which) {    
  195.                                     finish();    
  196.                                 }    
  197.                             }).create();// 創建    
  198.             // 顯示對話框    
  199.             dialog.show();    
  200.         }  
  201.         private void downFile(final String url)  
  202.         {  
  203.             m_progressDlg.show();    
  204.             new Thread() {    
  205.                 public void run() {    
  206.                     HttpClient client = new DefaultHttpClient();    
  207.                     HttpGet get = new HttpGet(url);    
  208.                     HttpResponse response;    
  209.                     try {    
  210.                         response = client.execute(get);    
  211.                         HttpEntity entity = response.getEntity();    
  212.                         long length = entity.getContentLength();    
  213.                           
  214.                         m_progressDlg.setMax((int)length);//設置進度條的最大值  
  215.                           
  216.                         InputStream is = entity.getContent();    
  217.                         FileOutputStream fileOutputStream = null;    
  218.                         if (is != null) {    
  219.                             File file = new File(    
  220.                                     Environment.getExternalStorageDirectory(),    
  221.                                     m_appNameStr);    
  222.                             fileOutputStream = new FileOutputStream(file);    
  223.                             byte[] buf = new byte[1024];    
  224.                             int ch = -1;    
  225.                             int count = 0;    
  226.                             while ((ch = is.read(buf)) != -1) {    
  227.                                 fileOutputStream.write(buf, 0, ch);    
  228.                                 count += ch;    
  229.                                 if (length > 0) {    
  230.                                      m_progressDlg.setProgress(count);  
  231.                                 }    
  232.                             }    
  233.                         }    
  234.                         fileOutputStream.flush();    
  235.                         if (fileOutputStream != null) {    
  236.                             fileOutputStream.close();    
  237.                         }    
  238.                         down();    
  239.                     } catch (ClientProtocolException e) {    
  240.                         e.printStackTrace();    
  241.                     } catch (IOException e) {    
  242.                         e.printStackTrace();    
  243.                     }    
  244.                 }    
  245.             }.start();    
  246.         }  
  247.         private void down() {  
  248.             m_mainHandler.post(new Runnable() {  
  249.                 public void run() {  
  250.                     m_progressDlg.cancel();  
  251.                     update();  
  252.                 }  
  253.             });  
  254.     }  
  255.           
  256.         void update() {  
  257.             Intent intent = new Intent(Intent.ACTION_VIEW);  
  258.             intent.setDataAndType(Uri.fromFile(new File(Environment  
  259.                     .getExternalStorageDirectory(), m_appNameStr)),  
  260.                     "application/vnd.android.package-archive");  
  261.             startActivity(intent);  
  262.         }  
  263.   
  264.   
  265. }  
逐步講解:

1、OnCreate函數:

先從主函數開始講,OnCreate函數中只有兩部分,一個是initVariable()初始化變量,這個不多說,難度不大;第二個是爲版本檢測按鈕設置監聽函數——btnClickListener,而在btnClickListener函數中可以明顯的看到,其中也只有一個類checkNewestVersionAsyncTask,這裏採用異步方式處理更新問題。下面看checkNewestVersionAsyncTask函數

2、checkNewestVersionAsyncTask函數

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. class checkNewestVersionAsyncTask extends AsyncTask<Void, Void, Boolean>  
  2. {  
  3.   
  4.     @Override  
  5.     protected Boolean doInBackground(Void... params) {  
  6.         // TODO Auto-generated method stub  
  7.         if(postCheckNewestVersionCommand2Server())  
  8.         {  
  9.             int vercode = Common.getVerCode(getApplicationContext()); // 用到前面第一節寫的方法    
  10.              if (m_newVerCode > vercode) {    
  11.                  return true;  
  12.              } else {    
  13.                  return false;  
  14.              }    
  15.         }  
  16.         return false;  
  17.     }  
  18.       
  19.     @Override  
  20.     protected void onPostExecute(Boolean result) {  
  21.         // TODO Auto-generated method stub  
  22.         if (result) {//如果有最新版本  
  23.             doNewVersionUpdate(); // 更新新版本    
  24.         }else {  
  25.             notNewVersionDlgShow(); // 提示當前爲最新版本    
  26.         }  
  27.         super.onPostExecute(result);  
  28.     }  
  29.       
  30.     @Override  
  31.     protected void onPreExecute() {  
  32.         // TODO Auto-generated method stub  
  33.         super.onPreExecute();  
  34.     }  
  35. }  

(1)首先看後臺操作doInBackground

首先利用postCheckNewestVersionCommand2Server()函數將請求發送到服務器,該函數根據是否請求成功返回TRUE或FALSE,然後將從服務器上獲取的版本代碼與本地的版本代碼進行比較,如果要更新返回TRUE,如果不要更新返回FASLE。

下面看看postCheckNewestVersionCommand2Server()的代碼:

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. private Boolean postCheckNewestVersionCommand2Server()  
  2. {  
  3.     StringBuilder builder = new StringBuilder();  
  4.     JSONArray jsonArray = null;  
  5.     try {  
  6.         // 構造POST方法的{name:value} 參數對  
  7.         List<NameValuePair> vps = new ArrayList<NameValuePair>();  
  8.         // 將參數傳入post方法中  
  9.         vps.add(new BasicNameValuePair("action""checkNewestVersion"));  
  10.         builder = Common.post_to_server(vps);  
  11.         jsonArray = new JSONArray(builder.toString());  
  12.         if (jsonArray.length()>0) {  
  13.             if (jsonArray.getJSONObject(0).getInt("id") == 1) {  
  14.                 m_newVerName = jsonArray.getJSONObject(0).getString("verName");  
  15.                 m_newVerCode = jsonArray.getJSONObject(0).getLong("verCode");  
  16.                   
  17.                 return true;  
  18.             }  
  19.         }  
  20.   
  21.         return false;  
  22.     } catch (Exception e) {  
  23.         Log.e("msg",e.getMessage());  
  24.         m_newVerName="";  
  25.         m_newVerCode=-1;  
  26.         return false;  
  27.     }  
  28. }  

這裏就是構建名值對,然後發向服務器,如果獲取到了值就返回TURE,如果沒獲取到值,就返回FALSE。服務器返回的JSON值爲:

[html] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. [{"id":"1","verName":"1.0.1","verCode":"2"}]  

對於服務器代碼,由於是用PHP寫的,這裏就不再列出了,在源碼裏有。

(2)onPostExecute()
繼續第一部分,在doInBackground操作完成後,如果需要更新doInBackground返回TRUE,否則返回FASLE,所以在onPostExecute
中根據result不同調用不同的函數,利用doNewVersionUpdate(); 提示用戶更新最新版本。利用notNewVersionDlgShow(); /提示用戶當前即爲最新版本,無需更新。

對於notNewVersionDlgShow()函數僅僅是創建了個對話框,沒什麼實體內容,就不再具體講解。下面具體講述doNewVersionUpdate()下載,更新與安裝程序的過程。

3、doNewVersionUpdate()提示版本更新
具體代碼如下:

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. private void doNewVersionUpdate() {  
  2.     int verCode = Common.getVerCode(getApplicationContext());    
  3.     String verName = Common.getVerName(getApplicationContext());    
  4.       
  5.     String str= "當前版本:"+verName+" Code:"+verCode+" ,發現新版本:"+m_newVerName+  
  6.             " Code:"+m_newVerCode+" ,是否更新?";    
  7.     Dialog dialog = new AlertDialog.Builder(this).setTitle("軟件更新").setMessage(str)    
  8.             // 設置內容    
  9.             .setPositiveButton("更新",// 設置確定按鈕    
  10.                     new DialogInterface.OnClickListener() {    
  11.                         @Override    
  12.                         public void onClick(DialogInterface dialog,    
  13.                                 int which) {   
  14.                             m_progressDlg.setTitle("正在下載");    
  15.                             m_progressDlg.setMessage("請稍候...");    
  16.                             downFile(Common.UPDATESOFTADDRESS);  //開始下載  
  17.                         }    
  18.                     })    
  19.             .setNegativeButton("暫不更新",    
  20.                     new DialogInterface.OnClickListener() {    
  21.                         public void onClick(DialogInterface dialog,    
  22.                                 int whichButton) {    
  23.                             // 點擊"取消"按鈕之後退出程序    
  24.                             finish();    
  25.                         }    
  26.                     }).create();// 創建    
  27.     // 顯示對話框    
  28.     dialog.show();    
  29. }  

這裏創建一個具有確定按鈕和取消按鈕功能的對話框,如果用戶點擊取消按鈕,會利用finish()結束掉程序運行;如果點擊確定按鈕,則利用 downFile(Common.UPDATESOFTADDRESS); 函數開始程序下載,其中downFile()函數傳進去的參數是APP所在的服務器地址。注意這裏的地址要具體到下載文件,比如這裏是http://192.168.1.105/server/XXX.apk

4、downFile(final String url)下載並顯示進度

具體代碼如下:

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. private void downFile(final String url)  
  2. {  
  3.     m_progressDlg.show();    
  4.     new Thread() {    
  5.         public void run() {    
  6.             HttpClient client = new DefaultHttpClient();    
  7.             HttpGet get = new HttpGet(url);    
  8.             HttpResponse response;    
  9.             try {    
  10.                 response = client.execute(get);    
  11.                 HttpEntity entity = response.getEntity();    
  12.                 long length = entity.getContentLength();    
  13.                   
  14.                 m_progressDlg.setMax((int)length);//設置進度條的最大值  
  15.                   
  16.                 InputStream is = entity.getContent();    
  17.                 FileOutputStream fileOutputStream = null;    
  18.                 if (is != null) {    
  19.                     File file = new File(    
  20.                             Environment.getExternalStorageDirectory(),    
  21.                             m_appNameStr);    
  22.                     fileOutputStream = new FileOutputStream(file);    
  23.                     byte[] buf = new byte[1024];    
  24.                     int ch = -1;    
  25.                     int count = 0;    
  26.                     while ((ch = is.read(buf)) != -1) {    
  27.                         fileOutputStream.write(buf, 0, ch);    
  28.                         count += ch;    
  29.                         if (length > 0) {    
  30.                              m_progressDlg.setProgress(count);//設置當前進度  
  31.                         }    
  32.                     }    
  33.                 }    
  34.                 fileOutputStream.flush();    
  35.                 if (fileOutputStream != null) {    
  36.                     fileOutputStream.close();    
  37.                 }    
  38.                 down();  //告訴HANDER已經下載完成了,可以安裝了  
  39.             } catch (ClientProtocolException e) {    
  40.                 e.printStackTrace();    
  41.             } catch (IOException e) {    
  42.                 e.printStackTrace();    
  43.             }    
  44.         }    
  45.     }.start();    
  46. }  

通過利用httpClient的get方法,獲取指定URL的內容,然後寫到本地SD卡中,對於進度條,首先利用m_progressDlg.setMax((int)length);設置進度條的最大值,然後在讀取返回結果並寫到本地時,利用 m_progressDlg.setProgress(count);設置當前進度。在全部寫完以後,調用down()函數,通知HANDER安裝程序。
5、安裝程序

安裝程序主要利用下面兩個函數:

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. /** 
  2.  * 告訴HANDER已經下載完成了,可以安裝了 
  3.  */  
  4. private void down() {  
  5.         m_mainHandler.post(new Runnable() {  
  6.             public void run() {  
  7.                 m_progressDlg.cancel();  
  8.                 update();  
  9.             }  
  10.         });  
  11. }  
  12. /** 
  13.  * 安裝程序 
  14.  */  
  15. void update() {  
  16.     Intent intent = new Intent(Intent.ACTION_VIEW);  
  17.     intent.setDataAndType(Uri.fromFile(new File(Environment  
  18.             .getExternalStorageDirectory(), m_appNameStr)),  
  19.             "application/vnd.android.package-archive");  
  20.     startActivity(intent);  
  21. }  

由於在android程序中必須依循單線程操作UI,所以在非主線程中不能操作UI,否則程序會崩掉,具體參見:《AsnyncTask與handler(一)——AsyncTask異步處理》與《AsnyncTask與handler(二)——handler消息機制》。所以這裏作用handler的方式更新UI。

好了,到這就全部講完了,下面給出客戶端與服務器端源碼,懂PHP的童鞋賺到了有木有……

 

源碼地址:http://download.csdn.net/detail/harvic880925/7309013 不要分,僅供分享。

 

 請大家尊重作者原創版權,轉載請標明出處:http://blog.csdn.net/harvic880925/article/details/25191159 不勝感激。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章