android应用自升级

1 篇文章 0 订阅
1 篇文章 0 订阅

在智能手机上,应用自升级是很常见的功能。研究了一天,基本案例已经出炉。

首先说一下自动升级的基本流程:

1.首先,这肯定是一个需要网络交互的过程,用户打开应用之后会自动给服务器发一个请求,然后服务器给予一个版本信息,

客户端得到后通过解析是否有新的版本。然后根据相关信息提示用户是否更新。

2.在服务器端,我们通过从客户端发来的请求生成一个xml文件传送给客户端,请求的信息包括客户端的版本和应用名称,把这些信息和服务器上的数据库对照,然后给出相关的回馈信息。

3.在客户端,更新检查同过线程进行,解析从服务器端得到的xml文件后半段是否有新版本,如果有提醒用户更新,如果没有,结束线程。

具体实现:

服务器端采用apache和php,mysql。

这里我先在mysql数据表中存一条数据:

然后写一个提供客户端访问的php脚本:

autoupdate.php:

<?php
$app_version = $_GET['version'];  //得到当前版本号
$App_name = $_GET['name'];			//得到应用名称
$Host = "localhost";  //链接数据库的主机名
$UName = "root";			//进入数据库的用户名
$Password = "123456";		//密码
$DBName = "app_update";		//数据库名
$TBName = "version";		//表名
$conn = mysql_connect($Host,$UName,$Password)or die("connect failed");  //链接
mysql_select_db($DBName,$conn);//选择数据库
$sql = "select * from version where version_id>$app_version and name='$App_name' order by id limit 0,1"; //查询数据库中是否有比当前版本更新的应用
$result = mysql_query($sql,$conn);
$success = 0;  
while($row=mysql_fetch_array($result))
{
$success = 1;  //查询不为空,说明有更新的版本
list($id,$name,$version,$url) = $row; //取得版本信息
}
//create xml file生成xml文件
header("Content-Type:text/plain");
$doc = new DOMDocument('1.0','utf-8');
$root = $doc->createElement("root");
$doc->appendChild( $root );
$update = $doc->createElement( "update" );
$root->appendChild($update);
$update->setAttribute("success",$success);

if($success){ //如果有更新版本,则把新版本信息发给客户端
	$item = $doc->createElement("item");
	$update->appendChild($item);
	$item->setAttribute("version",$version);
	$item->setAttribute("name",$name);
	$send_url = $doc->createTextNode($url);
	$item->appendChild($send_url);
}
echo $doc->saveXML();
?>


当然,我们需要把指定的应用放到上传到服务器目录下,设定数据库中的url。

从浏览器中访问这个php文件:

 

再来看看客户端:

还是从效果图说起吧:

 

MainActivity.java:
package com.xluo.test.autoupdate;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.util.Log;
import android.view.Menu;
import android.widget.Toast;

public class MainActivity extends Activity {
	
	private static final String UPDATE_FILE = "/data/data/update.apk";  //下载后存储的地方
	private static final String UPDATE_FILE_TMP = "/data/data/update.apk.tmp";//临时文件
	private Toast mToast;
	private static String UPDATE_URL = "http://10.16.6.163/test/autoupdate.php?version=20121122&name=AutoUpdate";
	/*
	 * 请求url,为了方便,这里的version设为20121122,在数据库中是20121123,说明有最新版本
	 * 
	 */
	private static UpdateInfo ui; 
	private static final String TAG = "MainActivity";
	private Handler mHandler = new Handler(){ //处理线程中解析xml文件后的数据
		public void handleMessage(Message msg){
			ui = (UpdateInfo)msg.obj;
			if(ui.URL != ""){
				new AlertDialog.Builder(MainActivity.this)
				.setTitle(R.string.dialog_title)
				.setMessage(R.string.dialo_text)
				.setPositiveButton(R.string.dialog_sure, new DialogInterface.OnClickListener() {
					
					@Override
					public void onClick(DialogInterface dialog, int which) {
						// TODO Auto-generated method stub
						UpdateDownloadTask udt = new UpdateDownloadTask();
						udt.execute(ui.URL);
					}
				})
				.setNegativeButton(R.string.dialog_cancel,null)
				.show();
			}
		}
	};
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG,"Start check update version");
        AppUpdate au = new AppUpdate(UPDATE_URL,mHandler);
        au.start();//应用打开后开启检测版本线程
        mToast = Toast.makeText(MainActivity.this, R.string.update_download_pending, Toast.LENGTH_SHORT);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
    
    private class UpdateDownloadTask extends AsyncTask<String, Integer, Boolean> { //下载类

        @Override
        protected Boolean doInBackground(String... params) {
            // TODO Auto-generated method stub
            HttpGet httpRequest = new HttpGet(params[0]);

            HttpClient httpClient = new DefaultHttpClient();
            long length = -1;
            try {

                HttpResponse httpResponse = httpClient.execute(httpRequest);

                HttpEntity entity = httpResponse.getEntity();

                length = entity.getContentLength();
                Log.i("UpdateDownloadTask", "begin length:" + length);
                InputStream inputStream = entity.getContent();

                byte[] b = new byte[4 * 1024];

                int readedLength = -1;
                File file = new File(UPDATE_FILE_TMP);
                if (file.exists()) {
                    file.delete();
                }
                OutputStream outputStream = MainActivity.this.openFileOutput(file.getName(),Context.MODE_WORLD_READABLE);
                long count = 0;
                long show_progress = 0;
                long progress_old = 0;
                while ((readedLength = inputStream.read(b)) != -1
                        && !this.isCancelled()) {

                    outputStream.write(b, 0, readedLength);

                    count += readedLength;

                    show_progress = (count*100/length);
                    if(progress_old != show_progress){
                    publishProgress((int)show_progress);
                    progress_old = show_progress;
                    }

                }
                inputStream.close();
                outputStream.close();
                if (!this.isCancelled()) {
                    File update_file = new File(UPDATE_FILE);
                    if (update_file.exists()) {
                        update_file.delete();
                    }
                    file.renameTo(update_file);
                } else {
                    if (file.exists()) {
                        file.delete();
                    }
                    return false;
                }
            } catch (ClientProtocolException e) {

                // TODO Auto-generated catch block
                Log.e("UpdateDownloadTask",
                        "ClientProtocolException Error:" + e.toString());
                return false;

            } catch (IOException e) {
                // TODO Auto-generated catch block
                Log.e("UpdateDownloadTask", "IOException Error:" + e.toString());
                return false;

            }
            return true;

        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            int progress = values[0];
            Log.d("UpdateDownloadTask","publishProgress"+progress);
            mToast.setText(getString(R.string.update_download_pending)+progress+"%");
            mToast.show();
        }

        @Override
        protected void onPostExecute(Boolean success) {
            if (true == success) {
                Intent launchIntent = new Intent(Intent.ACTION_VIEW);
                Uri path = Uri.fromFile(new File(UPDATE_FILE));
                String mimetype = "application/vnd.android.package-archive";
                launchIntent.setDataAndType(path, mimetype);
                launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                try{
                      startActivity(launchIntent);
                }catch (ActivityNotFoundException ex)
                {
                      Log.e("UpdateDownloadTask","ActivityNotFoundException Error:" + ex.toString());
                }
                MainActivity.this.finish();
            } else {
                Log.e("UpdateDownloadTask","Download failed");
            }
        }
    }  
}

 

AppUpdate.java:

package com.xluo.test.autoupdate;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

import android.os.Handler;
import android.os.Message;
import android.util.Log;

public class AppUpdate extends Thread{
	private String updateURL;
	private Handler mHandler;
	public AppUpdate(String url,Handler h){
		this.updateURL = url;  //访问地址
		this.mHandler = h;  //处理消息的handler
	}
	public void run(){
		try{
			URL url = new URL(updateURL);
			URLConnection con = url.openConnection();
	        if (((HttpURLConnection) con).getResponseCode() != HttpURLConnection.HTTP_OK) {
	            return ;
	        }
	        InputStream is = con.getInputStream();
	        UpdateInfo info = xmlAnalysis.getXML(is);  //得到解析后的xml中的信息
	        is.close();
	        if(info != null){
	            Message msg = new Message();
	            msg.obj = info;
	            mHandler.removeCallbacksAndMessages(msg);
	            mHandler.sendMessage(msg); //send给MainActivity中的handler
	        }
		}catch(InterruptedException e){
			e.printStackTrace();
		}
		catch(Exception e){
			e.printStackTrace();
		}
	}
}


 

解析xml文件的类:

xmlAnalysis.java:

package com.xluo.test.autoupdate;

import java.io.InputStream;

import org.xmlpull.v1.XmlPullParser;

import android.util.Log;
import android.util.Xml;

public class xmlAnalysis {
	private static final int UNKNOWN = 0;
	private static final int FORCE = 1;
	
	private static UpdateInfo ui;
	public static UpdateInfo getXML(InputStream is) throws Exception{
		ui = new UpdateInfo();
		XmlPullParser parser = Xml.newPullParser();
		parser.setInput(is, "utf-8");
		int event = parser.getEventType();
		while(event != XmlPullParser.END_DOCUMENT){
			switch(event){
			case XmlPullParser.START_DOCUMENT:
				break;
			case XmlPullParser.START_TAG:
				if("update".equals(parser.getName())){
					ui.SUCCESS = parser.getAttributeValue("", "success");
				}else if("item".equals(parser.getName())){
					ui.NAME = parser.getAttributeValue(null, "name");
					ui.VERSION = parser.getAttributeValue(null,"version");
				}
				break;
			
			case XmlPullParser.TEXT:
				ui.URL = parser.getText();
			default:
				break;
			}
		event = parser.next();
		}
		return ui;
	}

}


还有一个装载升级信息的类就不写了,很简单。

在AndroidManifest.xml中把相关权限打开,这里设计到上网,读写文件,下载权限。

这里应用没有存储版本信息的功能,只是做了一个测试。那样也很容易,我们可以在安装应用的时候把版本信息用sharedpreference存储,它便于存储一些简单的信息。然后每次在打开应用的时候都做存和取的操作就ok了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值