网上看了好多自动升级安装的例子.可能是我没配置好.做起来各种的不爽 虽然代码都大同小异 还是自己做的比较满意
先说下主要的实现逻辑:在测试服务器上放一个xml,用来说明服务器的版本,和新apk的下载地址,运行本地apk的时间.去检测服务器xml里的服务器的版本信息,本地apk的版本信息可以在AndroidManifest.xml中的versionCode拿到.代码是context.getPackageManager().getPackageInfo("com.example.updateversion", 0).0;如果他的版本号比本地的版本号高的话就下载更新服务器上的apk,完了后安装新的apk,这样就实现了自动更新apk的目的,记得发布新的apk的时候一定要修改AndroidManifest.xml中的versionCode,只能搞不能低,然的话就这次可以更新.下次再比对的时候就没法更新了
本例共有3个类文件.一个activity 一个下载的主工具类 一个解析xml的工具类 还有2个布局文件.主布局文件和一个progressbar
1.主要的业务类:注释都在代理里了
- <span style="font-size:18px;">package com.example.updateversion;
-
- 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;
- import java.util.HashMap;
-
- import android.app.AlertDialog;
- import android.app.AlertDialog.Builder;
- import android.app.Dialog;
- import android.content.Context;
- import android.content.DialogInterface;
- import android.content.DialogInterface.OnClickListener;
- import android.content.Intent;
- import android.content.pm.PackageManager.NameNotFoundException;
- import android.net.Uri;
- import android.os.Environment;
- import android.os.Handler;
- import android.os.Message;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.widget.ProgressBar;
- import android.widget.Toast;
-
-
-
-
-
-
-
- public class UpdateVersionService {
- private static final int DOWN = 1;
- private static final int DOWN_FINISH = 0;
- private HashMap<String, String> hashMap;
- private String fileSavePath;
- private String updateVersionXMLPath;
- private int progress;
- private boolean cancelUpdate = false;
- private Context context;
- private ProgressBar progressBar;
- private Dialog downLoadDialog;
- private Handler handler = new Handler() {
-
- @Override
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- switch ((Integer) msg.obj) {
- case DOWN:
- progressBar.setProgress(progress);
- break;
- case DOWN_FINISH:
- Toast.makeText(context, "文件下载完成,正在安装更新", Toast.LENGTH_SHORT).show();
- installAPK();
- break;
-
- default:
- break;
- }
- }
-
- };
-
-
-
-
-
-
-
-
-
- public UpdateVersionService(String updateVersionXMLPath, Context context) {
- super();
- this.updateVersionXMLPath = updateVersionXMLPath;
- this.context = context;
- }
-
-
-
-
-
-
- public void checkUpdate() {
- if (isUpdate()) {
- showUpdateVersionDialog();
- } else {
- Toast.makeText(context, "已经是新版本", Toast.LENGTH_SHORT).show();
- }
- }
-
-
-
-
- private void showUpdateVersionDialog() {
-
- AlertDialog.Builder builder = new Builder(context);
- builder.setTitle("软件更新");
- builder.setMessage("检测到新版本,是否下载更新");
-
- builder.setPositiveButton("更新", new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
-
- showDownloadDialog();
- }
- });
-
- builder.setNegativeButton("稍后更新", new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- }
- });
- Dialog noticeDialog = builder.create();
- noticeDialog.show();
- }
-
-
-
-
- protected void showDownloadDialog() {
- {
-
- AlertDialog.Builder builder = new Builder(context);
- builder.setTitle("正在更新");
-
- final LayoutInflater inflater = LayoutInflater.from(context);
- View v = inflater.inflate(R.layout.downloaddialog, null);
- progressBar = (ProgressBar) v.findViewById(R.id.updateProgress);
- builder.setView(v);
-
- builder.setNegativeButton("取消", new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
-
- cancelUpdate = true;
- }
- });
- downLoadDialog = builder.create();
- downLoadDialog.show();
-
- downloadApk();
- }
-
- }
-
-
-
-
- private void downloadApk() {
- new downloadApkThread().start();
-
- }
-
-
-
-
-
-
- private boolean isUpdate() {
- int versionCode = getVersionCode(context);
- try {
-
- URL url = new URL(updateVersionXMLPath);
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();
- conn.setReadTimeout(5 * 1000);
- conn.setRequestMethod("GET");
- InputStream inputStream = conn.getInputStream();
-
- ParseXmlService service = new ParseXmlService();
- hashMap = service.parseXml(inputStream);
- } catch (Exception e) {
- e.printStackTrace();
- }
- if (null != hashMap) {
- int serverCode = Integer.valueOf(hashMap.get("versionCode"));
-
- if (serverCode > versionCode) {
- Toast.makeText(context, "新版本是: " + serverCode, Toast.LENGTH_SHORT).show();
- return true;
- }
- }
- return false;
-
- }
-
-
-
-
-
-
-
- private int getVersionCode(Context context2) {
- int versionCode = 0;
- try {
-
- versionCode = context.getPackageManager().getPackageInfo("com.example.updateversion", 0).versionCode;
- Toast.makeText(context, "当前版本是: " + versionCode, Toast.LENGTH_SHORT).show();
- } catch (NameNotFoundException e) {
- e.printStackTrace();
- }
- return versionCode;
-
- }
-
-
-
-
- private void installAPK() {
- File apkfile = new File(fileSavePath, hashMap.get("fileName") + ".apk");
- if (!apkfile.exists()) {
- return;
- }
-
- Intent i = new Intent(Intent.ACTION_VIEW);
- System.out.println("filepath=" + apkfile.toString() + " " + apkfile.getPath());
- i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive");
- context.startActivity(i);
- android.os.Process.killProcess(android.os.Process.myPid());
-
- }
-
-
-
-
- public void uninstallAPK() {
- Uri packageURI = Uri.parse("package:com.example.updateversion");
- Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, packageURI);
- context.startActivity(uninstallIntent);
-
- }
-
-
-
-
-
-
-
- public class downloadApkThread extends Thread {
- @Override
- public void run() {
-
- super.run();
- try {
-
- if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
-
- String sdpath = Environment.getExternalStorageDirectory() + "/";
- fileSavePath = sdpath + "download";
- URL url = new URL(hashMap.get("loadUrl"));
-
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();
- conn.setReadTimeout(5 * 1000);
- conn.setRequestMethod("GET");
- conn.setRequestProperty("Charser", "GBK,utf-8;q=0.7,*;q=0.3");
-
- int length = conn.getContentLength();
-
- InputStream is = conn.getInputStream();
-
- File file = new File(fileSavePath);
-
- if (!file.exists()) {
- file.mkdir();
- }
- File apkFile = new File(fileSavePath, hashMap.get("fileName") + ".apk");
- FileOutputStream fos = new FileOutputStream(apkFile);
- int count = 0;
-
- byte buf[] = new byte[1024];
-
- do {
- int numread = is.read(buf);
- count += numread;
-
- progress = (int) (((float) count / length) * 100);
-
- Message message = new Message();
- message.obj = DOWN;
- handler.sendMessage(message);
- if (numread <= 0) {
-
-
- downLoadDialog.dismiss();
- Message message2 = new Message();
- message2.obj = DOWN_FINISH;
- handler.sendMessage(message2);
- break;
- }
-
- fos.write(buf, 0, numread);
- } while (!cancelUpdate);
- fos.close();
- is.close();
- }
- } catch (MalformedURLException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- }
-
- }
- }
- </span>
2:解析工具类,能做到自动升级的地步,xml解析就不用再注释了吧:
- <span style="font-size:18px;">package com.example.updateversion;
-
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.HashMap;
-
- import org.xmlpull.v1.XmlPullParser;
- import org.xmlpull.v1.XmlPullParserException;
-
- import android.util.Xml;
-
- public class ParseXmlService {
-
- public HashMap<String, String> parseXml(InputStream inputStream) {
- HashMap<String, String> hashMap = null;
- boolean flag = true;
- try {
- XmlPullParser pullParser = Xml.newPullParser();
- pullParser.setInput(inputStream, "UTF-8");
- int event = pullParser.getEventType();
- while (event != XmlPullParser.END_DOCUMENT) {
- switch (event) {
- case XmlPullParser.START_DOCUMENT:
- hashMap = new HashMap<String, String>();
- break;
- case XmlPullParser.START_TAG:
- flag = true;
- String name = pullParser.getName();
- if ("VERSIONCODE".equalsIgnoreCase(name) && flag == true) {
- hashMap.put("versionCode", pullParser.nextText().trim());
- } else if ("FILENAME".equalsIgnoreCase(name) && flag == true) {
- hashMap.put("fileName", pullParser.nextText().trim());
- } else if ("LOADURL".equalsIgnoreCase(name) && flag == true) {
- hashMap.put("loadUrl", pullParser.nextText().trim());
- }
- break;
- case XmlPullParser.END_TAG:
- flag = false;
- break;
- }
- event = pullParser.next();
- }
- } catch (XmlPullParserException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
-
-
-
-
-
- return hashMap;
- }
-
- }
- </span>
3:activity的代码主ui:
- <span style="font-size:18px;">package com.example.updateversion;
-
- import android.app.Activity;
- import android.os.Bundle;
- import android.os.Handler;
- import android.view.View;
-
- public class MainActivity extends Activity {
- private UpdateVersionService updateVersionService;
- private static final String UPDATEVERSIONXMLPATH = "http://192.168.1.30:8080/server/updateversion/version.xml";
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
-
- new Handler().postDelayed(new Runnable() {
-
- @Override
- public void run() {
-
- updateVersionService = new UpdateVersionService(UPDATEVERSIONXMLPATH, MainActivity.this);
- updateVersionService.checkUpdate();
- }
-
- }, 2000);
-
- }
-
-
-
-
-
-
- public void updateVersion(View view) {
- updateVersionService = new UpdateVersionService(UPDATEVERSIONXMLPATH, this);
- updateVersionService.checkUpdate();
- }
-
- }
- </span>
4:下面是主页面的xml和progress的xml
页面:
- <span style="font-size:18px;"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center_vertical|center_horizontal"
- android:orientation="vertical" >
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/version_msg"
- android:textSize="30sp"
- tools:context=".MainActivity" />
-
- <Button
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="30dp"
- android:onClick="updateVersion"
- android:text="@string/update" />
-
- </LinearLayout></span>
progress:
- <span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
-
- <ProgressBar
- android:id="@+id/updateProgress"
- style="@android:attr/progressBarStyleHorizontal"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" />
-
- </LinearLayout></span>
以上就是整个程序的代码了 发布新版本只需要修改AndroidManifest.xml文件中的versionCode的值,一定要比升级之前的版本高,那个versionName在本例中没有什么实际意义,主要是versioncode,如果想在ui上看的清楚一点的话 可以经string.xml中的version_msg 标明版本号.这样在ui上就能看到当前的版本了
以后能让自己清楚点再次使用这个例子 把服务器的xml格式也贴上来,新的apk和xml放一个文件夹就行
- <span style="font-size:18px;"><?xml version="1.0" encoding="UTF-8"?>
- <VERSION>
- <VERSIONCODE>2</VERSIONCODE>
- <FILENAME>updateversion</FILENAME>
- <LOADURL>http://192.168.1.30:8080/server/updateversion/updateversion.apk
- </LOADURL>
- </VERSION></span>
切记:如果测试的话,不管新的还是旧的apk 都得打包成apk文件.并且用同一个签名.如果是想在debug情况下使用 可以用(win7)C:\Users\rongsheng\.android目录下的debug.keystore这个签名(两个apk签名要一样),系统自带的签名的密码都是android