Android应用程序实现自动更新功能2_客户端实现

来源:互联网 发布:淘宝新手卖家提取软件 编辑:程序博客网 时间:2024/05/18 04:15

上一篇配置好服务器后,就可以进行客户端的实现了。

客户端的实现包括三个过程,版本号的检测和比较,安装包文件的下载,安装包文件的安装。

版本号的检测,需要下载version.xml文件,然后解析判断是否安装。

文件下载代码:

try {URL url = new URL("http://192.168.21.243/version.xml");HttpURLConnection conn = (HttpURLConnection)url.openConnection();conn.setReadTimeout(5*1000);conn.setRequestMethod("GET"); conn.connect();InputStream verstream = conn.getInputStream();ParseXmlService service = new ParseXmlService();hashMap = service.parseXml(verstream);Log.v(TAG, "version:"+hashMap.get("version"));Log.v(TAG, "name:"+hashMap.get("name"));Log.v(TAG, "url:"+hashMap.get("url"));} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}
使用ParseXmlService类进行解析,解析代码如下:

public class ParseXmlService {String TAG = "ParseXmlService";public HashMap<String, String> parseXml(InputStream inStream) throws Exception{HashMap<String, String> hashMap = new HashMap<String, String>();XmlPullParser parser = Xml.newPullParser();parser.setInput(inStream, "UTF-8");int eventType = parser.getEventType();while(eventType != XmlPullParser.END_DOCUMENT){switch (eventType) {case XmlPullParser.START_DOCUMENT:break;case XmlPullParser.START_TAG:if (parser.getName().equals("version")) {eventType = parser.next();hashMap.put("version", parser.getText());}else if (parser.getName().equals("name")) {eventType = parser.next();hashMap.put("name", parser.getText());}else if (parser.getName().equals("url")) {eventType = parser.next();hashMap.put("url", parser.getText());}break;case XmlPullParser.END_TAG: break;}eventType = parser.next();}return hashMap;}}
解析完以后,如果版本号比当前的版本号要高,就触发下载与更新。

下载apk的程序:

void dowloadApk(){//String savepath = getApplicationContext().getFilesDir().getPath()+"/data/user/";//String savepath = "/data/user/";Log.v(TAG,"into the dowloadApk");String upgradefile = "http://192.168.21.243/upgrade.apk";URL url = null;try {url = new URL(upgradefile);} catch (MalformedURLException e1) {e1.printStackTrace();}try {HttpURLConnection conn = (HttpURLConnection)url.openConnection();conn.connect();int length = conn.getContentLength(); InputStream is = conn.getInputStream();// File file = new File(savepath);// if (!file.exists())//             {//                 file.mkdir();//             }  //File apkFile = new File("/mnt/nand/", "upgrade.apk");             //FileOutputStream fos = new FileOutputStream(apkFile);            //FileOutputStream fos = getApplicationContext().openFileOutput("upgrade.apk",Context.MODE_PRIVATE);            FileOutputStream fos = getApplicationContext().openFileOutput("upgrade.apk",Context.MODE_WORLD_READABLE);             int count = 0;             byte buf[] = new byte[256];             int numread = 0;                          do{             numread = is.read(buf,0,256);             count += numread;                          try {Thread.sleep(50);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}                          Log.v(TAG,"dowloading the data numread:"+numread);             progress = (int) (((float) count / length) * 100);mHandler.sendEmptyMessage(DOWNLOAD);            if(numread >= 0){         fos.write(buf, 0, numread);         }            if (numread <= 0){break;}                           }while(!cancelUpdate);                          fos.close();             is.close();} catch (IOException e) {e.printStackTrace();}mDownloadDialog.dismiss();if(!cancelUpdate){mHandler.sendEmptyMessage(FINISH_DIALOG);}if(cancelUpdate)cancelUpdate = false;Log.v(TAG,"out the dowloadApk");}
其中注意的是下载apk需要另开一个线程实现,同时记得加上网络和存储介质的访问权限

private class downloadApkThread extends Thread{ @Override        public void run()        { dowloadApk(); //showDownloadDialog();         } }
new downloadApkThread().start();
在AndroidManifest.xml中加入相应的权限

    <uses-permission android:name="android.permission.INTERNET" />    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
下载完之后,会在/data/data/yingyong/files/下生成相应的文件,宏
Context.MODE_WORLD_READABLE
很关键,否则安装的时候没有权限会报错。

安装实现的相应的代码:

public void ApkInstall(){//Intent intent = new Intent(this,InstallActivity.class);    //startActivity(intent);         String apkpath = getApplicationContext().getFilesDir().getPath() + "/upgrade.apk";Uri uri = Uri.fromFile(new File(apkpath));Intent intent = new Intent(Intent.ACTION_VIEW);intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);intent.setDataAndType(uri, "application/vnd.android.package-archive");startActivity(intent);}
在代码中,
Intent.FLAG_ACTIVITY_NEW_TASK
这个参数很重要,否则在程序安装到一半时就会出现闪退的现象,其实这种安装不属于静默安装,而是通过使用每个客户端设备使用的默认安装程序来安装。Google这种架构的设计主要是出于安全的方面考虑,试想一下,如果使用静默安装,用户根本不知道程序都获取了哪些权限,这就给用户带来了不可控的风险。

总结,在这个过程中并没有设计到UI的设计,这个设计可以放到下一节去讲,主要是涉及到进度条的操作,

安卓自带的进度条实在是太丑了。

在代码设计时,任何的UI操作都不要在下载线程中实现,最好使用消息机制发送消息,在主线程中实现。




0 0