Android开发应用异步检查更新代码

开发环境:android studio    sdk 4.0及以上

场景:用户点击检查更新按钮进行检查服务器版本号,若有新版本则进行下载更新。异步检测版本号

  1 package com.example.qurenwu.qurenwu_2.util;
  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 import java.util.Map;
 12 
 13 import android.app.AlertDialog;
 14 import android.app.AlertDialog.Builder;
 15 import android.app.Dialog;
 16 import android.content.Context;
 17 import android.content.DialogInterface;
 18 import android.content.DialogInterface.OnClickListener;
 19 import android.content.Intent;
 20 import android.content.pm.PackageManager;
 21 import android.content.pm.PackageManager.NameNotFoundException;
 22 import android.net.Uri;
 23 import android.os.Environment;
 24 import android.os.Handler;
 25 import android.os.Message;
 26 import android.util.Log;
 27 import android.view.LayoutInflater;
 28 import android.view.View;
 29 import android.widget.ProgressBar;
 30 import android.widget.Toast;
 31 
 32 import com.example.qurenwu.qurenwu_2.R;
 33 import com.example.qurenwu.qurenwu_2.custom.GotaskGlobalVal;
 34 
 35 import org.w3c.dom.Document;
 36 import org.w3c.dom.Element;
 37 import org.w3c.dom.Node;
 38 import org.w3c.dom.NodeList;
 39 
 40 import javax.xml.parsers.DocumentBuilder;
 41 import javax.xml.parsers.DocumentBuilderFactory;
 42 
 43 /**
 44  * Created by Administrator on 2014/12/3.
 45  */
 46 public class UpdateManager {
 47     GotaskGlobalVal globalVal;  //全局
 48     /* 下载中 */
 49     private static final int DOWNLOAD = 1;
 50     /* 下载结束 */
 51     private static final int DOWNLOAD_FINISH = 2;
 52     /*检查是否有更新*/
 53     private static final int CHECK_APK_VERSION= 3;
 54     /* 保存解析的XML信息 */
 55     HashMap<String, String> mHashMap;
 56     /* 下载保存路径 */
 57     private String mSavePath;
 58     /* 记录进度条数量 */
 59     private int progress;
 60     /* 是否取消更新 */
 61     private boolean cancelUpdate = false;
 62 
 63     private Context mContext;
 64 
 65     private int mFlag; // 0:自启动检测  1:手动检测,区别在于前者若无更新则不提示,后者若无更新需要提示
 66     /* 更新进度条 */
 67     private ProgressBar mProgress;
 68     private Dialog mDownloadDialog;
 69 
 70     private Handler mHandler = new Handler()
 71     {
 72         public void handleMessage(Message msg)
 73         {
 74             switch (msg.what)
 75             {
 76                 // 正在下载
 77                 case DOWNLOAD:
 78                     // 设置进度条位置
 79                     mProgress.setProgress(progress);
 80                     break;
 81                 case DOWNLOAD_FINISH:
 82                     // 安装文件
 83                     installApk();
 84                     break;
 85                 case CHECK_APK_VERSION:  //检查版本更新
 86                     mHashMap = (HashMap<String,String>)msg.obj;
 87                     // 获取当前软件版本
 88                     int versionCode = getVersionCode(mContext);
 89                     if (null != mHashMap)
 90                     {
 91                         int serviceCode = Integer.valueOf(mHashMap.get("version"));
 92                         // 版本判断
 93                         Log.v("isUpdate","serviceCode:"+serviceCode+";versionCode:"+versionCode);
 94                         if (serviceCode > versionCode)
 95                         {
 96                             //需要更新
 97                             showNoticeDialog();
 98                         }
 99                         else
100                         {
101                             if(mFlag == 1)
102                             {Toast.makeText(mContext, R.string.soft_update_no, Toast.LENGTH_LONG).show();}
103                         }
104                     }
105                     break;
106                 default:
107                     break;
108             }
109         };
110     };
111 
112     public UpdateManager(Context context)
113     {
114         this.mContext = context;
115         globalVal = (GotaskGlobalVal)context.getApplicationContext();
116         mFlag = 0;
117     }
118 
119     /**
120      * 检测软件更新
121      * @param flag 0:启动时检测  1:手动检测,区别在于前者若无更新则不提示,后者若无更新需要提示
122      */
123     public void checkUpdate(int flag)
124     {
125         mFlag = flag;
126         CheckVersionHttpThread checkthread = new CheckVersionHttpThread(mHandler,CHECK_APK_VERSION);
127         new Thread(checkthread).start();
128     }
129     /**
130      * 检查软件是否有更新版本
131      *
132      * @return
133      */
134     private boolean isUpdate()
135     {
136         // 获取当前软件版本
137         int versionCode = getVersionCode(mContext);
138         // 把version.xml放到网络上,然后获取文件信息
139         //InputStream inStream = ParseXmlService.class.getClassLoader().getResourceAsStream("version.xml");
140         // 解析XML文件。 由于XML文件比较小,因此使用DOM方式进行解析
141         ParseXmlService service = new ParseXmlService();
142         try
143         {
144             //String path = "http://192.168.1.146:8080/picweb/xml/version.xml";
145             String path = globalVal.BASE_URL+"/xml/version.xml";
146             URL url = new URL(path);
147             HttpURLConnection conn = (HttpURLConnection)url.openConnection();
148             conn.setReadTimeout(5*1000);
149             conn.setRequestMethod("GET");
150             InputStream inStream = conn.getInputStream();
151             mHashMap = service.parseXml(inStream);
152         } catch (Exception e)
153         {
154             e.printStackTrace();
155         }
156         if (null != mHashMap)
157         {
158             int serviceCode = Integer.valueOf(mHashMap.get("version"));
159             // 版本判断
160             Log.v("isUpdate","serviceCode:"+serviceCode+";versionCode:"+versionCode);
161             if (serviceCode > versionCode)
162             {
163                 return true;
164             }
165         }
166         return false;
167     }
168 
169     /**
170      * 获取软件版本号
171      *
172      * @param context
173      * @return
174      */
175     private int getVersionCode(Context context)
176     {
177         int versionCode = 0;
178         try
179         {
180             // 获取软件版本号,对应AndroidManifest.xml下android:versionCode
181             versionCode = context.getPackageManager().getPackageInfo("com.example.qurenwu.qurenwu_2", 0).versionCode;
182         } catch (PackageManager.NameNotFoundException e)
183         {
184             e.printStackTrace();
185         }
186         return versionCode;
187     }
188 
189     /**
190      * 显示软件更新对话框
191      */
192     private void showNoticeDialog()
193     {
194         // 构造对话框
195         AlertDialog.Builder builder = new Builder(mContext);
196         builder.setTitle(R.string.soft_update_title);
197         builder.setMessage(R.string.soft_update_info);
198         // 更新
199         builder.setPositiveButton(R.string.soft_update_updatebtn, new OnClickListener()
200         {
201             @Override
202             public void onClick(DialogInterface dialog, int which)
203             {
204                 dialog.dismiss();
205                 // 显示下载对话框
206                 showDownloadDialog();
207             }
208         });
209         // 稍后更新
210         builder.setNegativeButton(R.string.soft_update_later, new OnClickListener()
211         {
212             @Override
213             public void onClick(DialogInterface dialog, int which)
214             {
215                 dialog.dismiss();
216             }
217         });
218         Dialog noticeDialog = builder.create();
219         noticeDialog.show();
220     }
221 
222     /**
223      * 显示软件下载对话框
224      */
225     private void showDownloadDialog()
226     {
227         // 构造软件下载对话框
228         AlertDialog.Builder builder = new Builder(mContext);
229         builder.setTitle(R.string.soft_updating);
230         // 给下载对话框增加进度条
231         final LayoutInflater inflater = LayoutInflater.from(mContext);
232         View v = inflater.inflate(R.layout.softupdate_progress, null);
233         mProgress = (ProgressBar) v.findViewById(R.id.update_progress);
234         builder.setView(v);
235         // 取消更新
236         builder.setNegativeButton(R.string.soft_update_cancel, new OnClickListener()
237         {
238             @Override
239             public void onClick(DialogInterface dialog, int which)
240             {
241                 dialog.dismiss();
242                 // 设置取消状态
243                 cancelUpdate = true;
244             }
245         });
246         mDownloadDialog = builder.create();
247         mDownloadDialog.show();
248         // 现在文件
249         downloadApk();
250     }
251 
252     /**
253      * 下载apk文件
254      */
255     private void downloadApk()
256     {
257         // 启动新线程下载软件
258         new downloadApkThread().start();
259     }
260 
261     /**
262      * 下载文件线程
263      */
264     private class downloadApkThread extends Thread
265     {
266         @Override
267         public void run()
268         {
269             try
270             {
271                 // 判断SD卡是否存在,并且是否具有读写权限
272                 if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
273                 {
274                     // 获得存储卡的路径
275                     String sdpath = Environment.getExternalStorageDirectory() + "/";
276                     mSavePath = sdpath + "download";
277                     URL url = new URL(mHashMap.get("url"));
278                     // 创建连接
279                     HttpURLConnection conn = (HttpURLConnection) url.openConnection();
280                     conn.connect();
281                     // 获取文件大小
282                     int length = conn.getContentLength();
283                     // 创建输入流
284                     InputStream is = conn.getInputStream();
285 
286                     File file = new File(mSavePath);
287                     // 判断文件目录是否存在
288                     if (!file.exists())
289                     {
290                         file.mkdir();
291                     }
292                     File apkFile = new File(mSavePath, mHashMap.get("name"));
293                     FileOutputStream fos = new FileOutputStream(apkFile);
294                     int count = 0;
295                     // 缓存
296                     byte buf[] = new byte[1024];
297                     // 写入到文件中
298                     do
299                     {
300                         int numread = is.read(buf);
301                         count += numread;
302                         // 计算进度条位置
303                         progress = (int) (((float) count / length) * 100);
304                         // 更新进度
305                         mHandler.sendEmptyMessage(DOWNLOAD);
306                         if (numread <= 0)
307                         {
308                             // 下载完成
309                             mHandler.sendEmptyMessage(DOWNLOAD_FINISH);
310                             break;
311                         }
312                         // 写入文件
313                         fos.write(buf, 0, numread);
314                     } while (!cancelUpdate);// 点击取消就停止下载.
315                     fos.close();
316                     is.close();
317                 }
318             } catch (MalformedURLException e)
319             {
320                 e.printStackTrace();
321             } catch (IOException e)
322             {
323                 e.printStackTrace();
324             }
325             // 取消下载对话框显示
326             mDownloadDialog.dismiss();
327         }
328     };
329 
330     /**
331      * 安装APK文件
332      */
333     private void installApk()
334     {
335         File apkfile = new File(mSavePath, mHashMap.get("name"));
336         if (!apkfile.exists())
337         {
338             return;
339         }
340         // 通过Intent安装APK文件
341         Intent i = new Intent(Intent.ACTION_VIEW);
342         i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive");
343         mContext.startActivity(i);
344     }
345     class ParseXmlService
346     {
347         public HashMap<String, String> parseXml(InputStream inStream) throws Exception
348         {
349             HashMap<String, String> hashMap = new HashMap<String, String>();
350 
351             // 实例化一个文档构建器工厂
352             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
353             // 通过文档构建器工厂获取一个文档构建器
354             DocumentBuilder builder = factory.newDocumentBuilder();
355             // 通过文档通过文档构建器构建一个文档实例
356             Document document = builder.parse(inStream);
357             //获取XML文件根节点
358             Element root = document.getDocumentElement();
359             //获得所有子节点
360             NodeList childNodes = root.getChildNodes();
361             for (int j = 0; j < childNodes.getLength(); j++)
362             {
363                 //遍历子节点
364                 Node childNode = (Node) childNodes.item(j);
365                 if (childNode.getNodeType() == Node.ELEMENT_NODE)
366                 {
367                     Element childElement = (Element) childNode;
368                     //版本号
369                     if ("version".equals(childElement.getNodeName()))
370                     {
371                         hashMap.put("version",childElement.getFirstChild().getNodeValue());
372                     }
373                     //软件名称
374                     else if (("name".equals(childElement.getNodeName())))
375                     {
376                         hashMap.put("name",childElement.getFirstChild().getNodeValue());
377                     }
378                     //下载地址
379                     else if (("url".equals(childElement.getNodeName())))
380                     {
381                         hashMap.put("url",childElement.getFirstChild().getNodeValue());
382                     }
383                 }
384             }
385             return hashMap;
386         }
387     }
388     /**
389      * 检测线程
390      */
391     class CheckVersionHttpThread implements Runnable{
392         private Handler handler;
393         int requestCode;
394         /**
395          * @param _handler
396          * @param _requestCode  若一个activity有多个此请求,那么activity中的handle的msg .what也不同,用该字段区分
397          */
398         public CheckVersionHttpThread(Handler _handler,int _requestCode)
399         {
400             this.handler = _handler;
401             this.requestCode = _requestCode;
402         }
403         @Override
404         public void run() {
405             HashMap<String, String> result= null;
406             // 把version.xml放到网络上,然后获取文件信息
407             //InputStream inStream = ParseXmlService.class.getClassLoader().getResourceAsStream("version.xml");
408             // 解析XML文件。 由于XML文件比较小,因此使用DOM方式进行解析
409             ParseXmlService service = new ParseXmlService();
410             try
411             {
412                 //String path = "http://192.168.1.146:8080/picweb/xml/version.xml";
413                 String path = globalVal.BASE_URL+"/xml/version.xml";
414                 URL url = new URL(path);
415                 HttpURLConnection conn = (HttpURLConnection)url.openConnection();
416                 conn.setReadTimeout(5*1000);
417                 conn.setRequestMethod("GET");
418                 InputStream inStream = conn.getInputStream();
419                 result = service.parseXml(inStream);
420             } catch (Exception e)
421             {
422                 e.printStackTrace();
423             }
424             Message msg = new Message();
425             msg.what = requestCode;
426             msg.obj = result;
427             handler.sendMessage(msg);
428         }
429     }
430 }


主界面中调用:

//检测新版本
        UpdateManager manager = new UpdateManager(MyActivity.this);// 检查软件更新
        manager.checkUpdate(0); // 0:表示启动时检测  1:手动检测,区别在于前者若无更新则不提示,后者若无更新需要提示


mainfest.xml 中需要配置版本号

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.qurenwu.qurenwu_2"
    android:versionCode="1"
    android:versionName="1.0" >

string.xml需要增加字符串

    <string name="soft_update_no">已经是最新版本</string>
    <string name="soft_update_title">软件更新</string>
    <string name="soft_update_info">检测到新版本,立即更新吗</string>
    <string name="soft_update_updatebtn">更新</string>
    <string name="soft_update_later">稍后更新</string>
    <string name="soft_updating">正在更新</string>
    <string name="soft_update_cancel">取消</string>

服务器端需要在目录如:http://192.168.11.1/xml/  目录下增加文件  version.xml  内容如下:

<?xml version="1.0" encoding="UTF-8"?>  
<update>  
    <version>1</version>  <!-- 必须是整数 -->
    <name>gotask.1.0</name>  
    <url>http://192.168.11.6/download/gotask.apk</url>  
</update> 

ok! 大功告成!

原文地址:https://www.cnblogs.com/feijian/p/4142795.html