Android提示版本更新

前言:在软件开发的尾声应该都会遇到这个问题,还好网上资料很多,所以基本不费什么力气就搞定了,现记录于下。这里用的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 不胜感激。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值