一.首先我們思考一下步驟
1,擷取當前APK的版本
2,去伺服器上擷取最新的版本
3,對比後,決定是否更新。
4,更新,去伺服器上下載apk.
5.下載後,儲存到sd卡,然後安裝apk
二,用戶端代碼如下
package com.zhenshi.updataapk;import java.io.File;import com.zhenshi.util.HttpConnect;import com.zhenshi.util.ToastUtil;import android.app.Activity;import android.app.AlertDialog;import android.app.Dialog;import android.app.ProgressDialog;import android.content.Context;import android.content.DialogInterface;import android.content.Intent;import android.content.pm.PackageManager.NameNotFoundException;import android.net.Uri;import android.os.Bundle;import android.os.Handler;/** * class name:TestUpdataActivity<BR> * class description:<BR> * PS: <BR> * * @version 1.00 2012-4-5 * @author ZHENSHI)peijiangping */public class TestUpdataActivity extends Activity {private String packageName;private ProgressDialog pBar;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);yesOrNoUpdataApk();}/** * Role:是否更新版本<BR> * Date:2012-4-5<BR> * * @author ZHENSHI)peijiangping */private int yesOrNoUpdataApk() {packageName = this.getPackageName();String nowVersion = getVerCode(TestUpdataActivity.this);String newVersion = goToCheckNewVersion();if (newVersion.equals("Error")) {return 0;}if (Double.valueOf(newVersion) > Double.valueOf(nowVersion)) {doNewVersionUpdate(nowVersion, newVersion);}return 1;}/** * Role:是否進行更新提示框<BR> * Date:2012-4-5<BR> * * @author ZHENSHI)peijiangping */private void doNewVersionUpdate(String nowVersion, String newVersion) {StringBuffer sb = new StringBuffer();sb.append("目前的版本:");sb.append(nowVersion);sb.append(", 發現新版本:");sb.append(newVersion);sb.append(", 是否更新?");Dialog dialog = new AlertDialog.Builder(TestUpdataActivity.this).setTitle("軟體更新").setMessage(sb.toString())// 設定內容.setPositiveButton("更新",// 設定確定按鈕new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog,int which) {pBar = new ProgressDialog(TestUpdataActivity.this);pBar.setTitle("正在下載");pBar.setMessage("請稍候...");// pBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);pBar.show();goToDownloadApk();}}).setNegativeButton("暫不更新",new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog,int whichButton) {// 點擊"取消"按鈕之後退出程式finish();}}).create();// 建立// 顯示對話方塊dialog.show();}/** * Role:開啟下載apk的線程<BR> * Date:2012-4-6<BR> * * @author ZHENSHI)peijiangping */private void goToDownloadApk() {new Thread(new DownloadApkThread(handler)).start();}public Handler handler = new Handler() {public void handleMessage(android.os.Message msg) {super.handleMessage(msg);if (msg.what == 1) {ToastUtil toastUtil = new ToastUtil(TestUpdataActivity.this);toastUtil.showDefultToast("下載成功!!").show();Intent intent = new Intent(Intent.ACTION_VIEW);intent.setDataAndType(Uri.fromFile(new File("/sdcard/update/", "updata.apk")),"application/vnd.android.package-archive");startActivity(intent);} else {ToastUtil toastUtil = new ToastUtil(TestUpdataActivity.this);toastUtil.showDefultToast("下載失敗!!").show();}pBar.cancel();}};/** * Role:去擷取當前的應用最新版本<BR> * Date:2012-4-5<BR> * * @author ZHENSHI)peijiangping */private String goToCheckNewVersion() {System.out.println("goToCheckNewVersion");String newVersion = null;final String url = "http://192.168.1.41:8080/TestHttpServlet/GetVersionServlet";HttpConnect hc = new HttpConnect(url, this);newVersion = hc.getDataAsString(null);if (newVersion.equals("Error")) {return "Error";}return newVersion;}/** * Role:取得程式的目前的版本<BR> * Date:2012-4-5<BR> * * @author ZHENSHI)peijiangping */private String getVerCode(Context context) {int verCode = 0;String verName = null;try {verCode = context.getPackageManager().getPackageInfo(packageName, 0).versionCode;verName = context.getPackageManager().getPackageInfo(packageName, 0).versionName;} catch (NameNotFoundException e) {System.out.println("no");}System.out.println("verCode" + verCode + "===" + "verName" + verName);return verName;}}
package com.zhenshi.updataapk;import com.zhenshi.util.HttpDownload;import android.os.Handler;import android.os.Message;/** * class name:DownloadApkThread<BR> * class description:下載apk的線程<BR> * PS: <BR> * * @version 1.00 2012-4-5 * @author ZHENSHI)peijiangping */public class DownloadApkThread implements Runnable {private Handler handler;private static final String url = "http://192.168.1.41:8080/TestHttpServlet/apk/TestUpdata.apk";private static final String fileName = "updata.apk";private static final String path = "/sdcard/update";public DownloadApkThread(Handler handler) {this.handler = handler;}@Overridepublic void run() {System.out.println("下載線程開啟");Message message = new Message();message.what = HttpDownload.downLoadFile(url, fileName, path);handler.sendMessage(message);}}
package com.zhenshi.util;import java.io.IOException;import java.io.InputStream;import java.util.List;import org.apache.http.HttpResponse;import org.apache.http.NameValuePair;import org.apache.http.client.HttpClient;import org.apache.http.client.entity.UrlEncodedFormEntity;import org.apache.http.client.methods.HttpPost;import org.apache.http.impl.client.DefaultHttpClient;import org.apache.http.params.BasicHttpParams;import org.apache.http.params.HttpConnectionParams;import org.apache.http.params.HttpParams;import org.apache.http.protocol.HTTP;import org.apache.http.util.EntityUtils;import android.content.Context;import android.util.Log;/** * class name:HttpConnect<BR> * class description:http請求工具類<BR> * PS: <BR> * * @version 1.00 2011/09/21 * @author CODYY)peijiangping */public class HttpConnect {/** * 訪問的Web伺服器位址 */private String url;private HttpPost httpRequest;private HttpResponse httpResponse;private HttpParams httpParams;private HttpClient httpClient;public HttpConnect(String url, Context context) {this.url = url;httpParams = new BasicHttpParams();HttpConnectionParams.setConnectionTimeout(httpParams, 15000);HttpConnectionParams.setSoTimeout(httpParams, 15000);httpClient = new DefaultHttpClient(httpParams);}/** * Role:通過Http請求來擷取傳回值(InputStream) <BR> * Date:2012-2-10 <BR> * * @author CODYY)peijiangping */public InputStream getDataAsInputStream(List<NameValuePair> params) {InputStream result = null;try {httpRequest = new HttpPost(url);if (params != null) {httpRequest.setEntity(new UrlEncodedFormEntity(params,HTTP.UTF_8));}httpResponse = httpClient.execute(httpRequest);if (200 == httpResponse.getStatusLine().getStatusCode()) {result = httpResponse.getEntity().getContent();}} catch (IOException e) {Log.e("nimeimei", e.getMessage(), e);return result;}return result;}/** * Role:通過Http請求來擷取傳回值(String),異常返回Error<BR> * Date:2012-2-10 <BR> * * @author CODYY)peijiangping */public String getDataAsString(List<NameValuePair> params) {String result = null;try {httpRequest = new HttpPost(url);if (params != null) {httpRequest.setEntity(new UrlEncodedFormEntity(params,HTTP.UTF_8));}httpResponse = httpClient.execute(httpRequest);if (200 == httpResponse.getStatusLine().getStatusCode()) {result = EntityUtils.toString(httpResponse.getEntity());System.out.println("取得傳回值" + result);}} catch (IOException e) {e.printStackTrace();return "Error";}return result;}/** * Role:通過Http請求來擷取傳回值(int),失敗返回-1,成功返回資料 <BR> * Date:2012-2-10 <BR> * * @author CODYY)peijiangping */public int getDataAsInt(List<NameValuePair> params) {int result = -1;try {httpRequest = new HttpPost(url);if (params != null) {httpRequest.setEntity(new UrlEncodedFormEntity(params,HTTP.UTF_8));}httpResponse = httpClient.execute(httpRequest);if (200 == httpResponse.getStatusLine().getStatusCode()) {result = Integer.parseInt(EntityUtils.toString(httpResponse.getEntity()));}} catch (IOException e) {return result;}return result;}/** * Role:http請求伺服器,不取得返回資料,成功返回1<BR> * Date:2012-2-10 <BR> * * @author CODYY)peijiangping */public int sendToService(List<NameValuePair> params) {try {httpRequest = new HttpPost(url);if (params != null) {httpRequest.setEntity(new UrlEncodedFormEntity(params,HTTP.UTF_8));}httpResponse = httpClient.execute(httpRequest);} catch (Exception e) {e.printStackTrace();return 0;}return 1;}}
package com.zhenshi.util;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL;/** * 類名:HttpDownload<BR> * 作用:下載檔案的類<BR> * 日期:2012-4-5<BR> * * @version V1.0 * @author peijiangping */public class HttpDownload {/** * 功能:下載檔案到指定目錄下,成功返回1<BR> * 日期:2012-4-5<BR> * 作者:裴江平 */public static int downLoadFile(String httpUrl, String fileName, String path) {FileOutputStream fos = null;InputStream is = null;HttpURLConnection conn = null;// 當存放檔案的檔案目錄不存在的時候建立檔案目錄File tmpFile = new File(path);if (!tmpFile.exists()) {tmpFile.mkdir();}// 擷取檔案對象File file = new File(path + "/"+fileName);try {URL url = new URL(httpUrl);try {conn = (HttpURLConnection) url.openConnection();is = conn.getInputStream();// 獲得http請求返回的InputStream對象。fos = new FileOutputStream(file);// 獲得檔案輸出資料流對象來寫檔案用的byte[] buf = new byte[256];conn.connect();// http請求伺服器double count = 0;// http請求取得響應的時候if (conn.getResponseCode() >= 400) {System.out.println("nono");return 0;} else {while (count <= 100) {if (is != null) {int numRead = is.read(buf);if (numRead <= 0) {break;} else {fos.write(buf, 0, numRead);}} else {break;}}}conn.disconnect();fos.close();is.close();} catch (IOException e) {e.printStackTrace();return 0;} finally {if (conn != null) {conn.disconnect();conn = null;}if (fos != null) {try {fos.close();} catch (IOException e) {e.printStackTrace();}fos = null;}if (is != null) {try {is.close();} catch (IOException e) {e.printStackTrace();}is = null;}}} catch (MalformedURLException e) {e.printStackTrace();return 0;}return 1;}}
package com.zhenshi.util;import android.content.Context;import android.graphics.drawable.Drawable;import android.view.Gravity;import android.view.LayoutInflater;import android.view.View;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.Toast;/** * class name:ToastUtil<BR> * class description:顯示toast的一個工具類<BR> * PS: <BR> * * @version 1.00 2011/09/30 * @author CODYY)peijiangping */public class ToastUtil {private Context context;public ToastUtil(Context context) {this.context = context;}/** * @param title * @param icon * @return返回一個帶圖片的toast */public Toast showPicToast(String title, Drawable icon) {Toast toast = Toast.makeText(context, title, Toast.LENGTH_LONG);toast.setGravity(Gravity.CENTER, 0, 0);LinearLayout toastView = (LinearLayout) toast.getView();ImageView imageCodeProject = new ImageView(context);imageCodeProject.setBackgroundDrawable(icon);toastView.addView(imageCodeProject, 0);return toast;}/** * @param title * @return返回一個預設的toast */public Toast showDefultToast(String title) {Toast toast = Toast.makeText(context, title, Toast.LENGTH_SHORT);return toast;}/** * @param layoutid * @return返回一個自訂的toast */public Toast showDiyToast(int layoutid) {LayoutInflater inflater = LayoutInflater.from(context);View myView = inflater.inflate(layoutid,null);Toast toast = new Toast(context);toast.setGravity(Gravity.RIGHT | Gravity.TOP, 12, 40);toast.setDuration(Toast.LENGTH_LONG);toast.setView(myView);return toast;}}
三,伺服器代碼如下:
package com.zhenshi.servlet;import java.io.IOException;import java.util.Map;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.zhenshi.util.SerialPortListener;/** * class name:GetVersionServlet<BR> * class description:擷取最新的軟體版本<BR> * PS: <BR> * * @version 1.00 2012-4-6 * @author ZHENSHI)peijiangping */public class GetVersionServlet extends HttpServlet {private static final long serialVersionUID = 1L;public Map<String, String> configMap;/** * @see HttpServlet#HttpServlet() */public GetVersionServlet() {super();// TODO Auto-generated constructor stub}/** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse * response) */protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("utf-8");configMap = SerialPortListener.configMap;String version = configMap.get("version");System.out.println(version);response.getWriter().write(version);}/** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse * response) */protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {/* 接收post請求 */doGet(request, response);}}
package com.zhenshi.util;import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;import java.util.HashMap;import java.util.Map;import javax.servlet.ServletContext;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;/** * class name:SerialPortListener<BR> * class description:WEb伺服器啟動監聽類<BR> * PS: <BR> * Date:2012-2-16<BR> * * @version 1.00 * @author CODYY)peijiangping */public class SerialPortListener implements ServletContextListener {public static Map<String, String> configMap;public void contextInitialized(ServletContextEvent event) {ServletContext context = event.getServletContext();String path = context.getRealPath("/");path = path.replace("\\", "/");path = path.replace("/WebContent", "");configMap = findConfig(path);//context.setAttribute("configMap", configMap);}public void contextDestroyed(ServletContextEvent arg0) {}public Map<String, String> findConfig(String path) {Map<String, String> configMap = new HashMap<String, String>();FileReader fr = null;BufferedReader br = null;try {fr = new FileReader(path + "conf/config.properties");// 建立FileReader對象,用來讀取字元流br = new BufferedReader(fr); // 緩衝指定檔案的輸入String myreadline; // 定義一個String類型的變數,用來每次讀取一行while (br.ready()) {myreadline = br.readLine();String[] keyAndValue = myreadline.split("=");if (keyAndValue.length == 2) {configMap.put(keyAndValue[0].trim(), keyAndValue[1].trim());} else if (keyAndValue.length > 2) {String keyName = myreadline.substring(0,myreadline.indexOf("="));String keyValue = myreadline.substring(myreadline.indexOf("=") + 1);configMap.put(keyName.trim(), keyValue.trim());}}} catch (IOException e) {e.printStackTrace();} finally {if (br != null) {try {br.close();} catch (IOException e) {e.printStackTrace();}}if (fr != null) {try {fr.close();} catch (IOException e) {e.printStackTrace();}}}return configMap;}}
config.properties內容為:
#configversion=1.0
web.xml內容為:
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>TestHttpServlet</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <listener> <listener-class>com.zhenshi.util.SerialPortListener</listener-class> </listener> <servlet> <description></description> <display-name>GetVersionServlet</display-name> <servlet-name>GetVersionServlet</servlet-name> <servlet-class>com.zhenshi.servlet.GetVersionServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>GetVersionServlet</servlet-name> <url-pattern>/GetVersionServlet</url-pattern> </servlet-mapping></web-app>
伺服器為Tomcat.
Androidmainfest.xml記得加上一些應用相關許可權。