一.首先我们思考一下步骤
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; @Override public 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() { @Override public 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; } @Override public 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 version=1.0
<?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>
Androidmainfest.xml记得加上一些应用相关权限。