市场上的Android应用都能够自动提示升级更新,这里就完整的来实现一下AndroidAPP,实现自动升级的功能。
Demo地址:http://download.csdn.net/detail/ericfantastic/9250609
效果图:
具体如何实现,其实不难,先看看流程:
本地AndroidApp必须要先有一个版本号用于标识当前版本,再从服务器获取服务器最新版本,进行相比较。
实现流程:
1、Manifest.xml添加联网权限,读写SD卡权限,版本号versionCode和版本名versionName,其中versionCode用来比较版本使用的变量,versionName为用于显示在界面上的版本字符串。
package com.eric.androidupdatedemo;
import java.io.File;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
public class MainActivity extends Activity {
private TextView textView;
public static int version,serverVersion;
public static String versionName,serverVersionName,downloadResult;
private Button btn;
private ProgressBar proBar;
public static receiveVersionHandler handler;
private UpdateManager manager = UpdateManager.getInstance();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textview_id);
btn = (Button) findViewById(R.id.button_id);
proBar=(ProgressBar)findViewById(R.id.progressBar_id);
Context c = this;
version = manager.getVersion(c);
versionName = manager.getVersionName(c);
textView.setText("当前版本号:"+version+"\n"+"当前版本名:"+versionName);
handler = new receiveVersionHandler();
//检查更新按钮点击事件
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
manager.compareVersion(MainActivity.this);
}
});
}
public class receiveVersionHandler extends Handler{
@Override
public void handleMessage(Message msg) {
proBar.setProgress(msg.arg1);
proBar.setVisibility(R.id.button_id);
textView.setText("下载进度:"+msg.arg1);
if(msg.arg1 == 100){
Intent intent = new Intent(Intent.ACTION_VIEW);
String path = Environment.getExternalStorageDirectory()+"/AndroidUpdateDemo.apk";
intent.setDataAndType(Uri.fromFile(new File(path)),
"application/vnd.android.package-archive");
startActivity(intent);
}
proBar.setVisibility(R.id.button_id);
}
}
}
package com.eric.androidupdatedemo;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.R.integer;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
/*
*@author Eric
*@2015-11-7上午8:03:31
*/
public class UpdateManager {
private static UpdateManager manager = null;
private UpdateManager(){}
public static UpdateManager getInstance(){
manager = new UpdateManager();
return manager;
}
//获取版本号
public int getVersion(Context context){
int version = 0;
try {
version = context.getPackageManager().getPackageInfo(
"com.eric.androidupdatedemo", 0).versionCode;
} catch (Exception e) {
System.out.println("获取版本号异常!");
}
return version;
}
//获取版本名
public String getVersionName(Context context){
String versionName = null;
try {
versionName = context.getPackageManager().getPackageInfo(
"com.eric.androidupdatedemo", 0).versionName;
} catch (Exception e) {
System.out.println("获取版本名异常!");
}
return versionName;
}
//获取服务器版本号
public String getServerVersion(){
String serverJson = null;
byte[] buffer = new byte[128];
try {
URL serverURL = new URL("http://192.168.226.106/ver.aspx");
HttpURLConnection connect = (HttpURLConnection) serverURL.openConnection();
BufferedInputStream bis = new BufferedInputStream(connect.getInputStream());
int n = 0;
while((n = bis.read(buffer))!= -1){
serverJson = new String(buffer);
}
} catch (Exception e) {
System.out.println("获取服务器版本号异常!"+e);
}
return serverJson;
}
//比较服务器版本与本地版本弹出对话框
public boolean compareVersion(Context context){
final Context contextTemp = context;
new Thread(){
public void run() {
Looper.prepare();
String serverJson = manager.getServerVersion();
//解析Json数据
try {
JSONArray array = new JSONArray(serverJson);
JSONObject object = array.getJSONObject(0);
String getServerVersion = object.getString("version");
String getServerVersionName = object.getString("versionName");
MainActivity.serverVersion = Integer.parseInt(getServerVersion);
MainActivity.serverVersionName = getServerVersionName;
if(MainActivity.version < MainActivity.serverVersion){
//弹出一个对话框
AlertDialog.Builder builder = new Builder(contextTemp);
builder.setTitle("版本更新" ) ;
builder.setMessage("当前版本:"+MainActivity.versionName
+"\n"+"服务器版本:"+MainActivity.serverVersionName ) ;
builder.setPositiveButton("立即更新",new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int arg1) {
//开启线程下载apk
new Thread(){
public void run() {
Looper.prepare();
downloadApkFile(contextTemp);
Looper.loop();
};
}.start();
}
});
builder.setNegativeButton("下次再说", null);
builder.show();
}else{
AlertDialog.Builder builder = new Builder(contextTemp);
builder.setTitle("版本信息" ) ;
builder.setMessage("当前已经是最新版本" ) ;
builder.setPositiveButton("确定",null);
builder.show();
}
} catch (JSONException e) {
e.printStackTrace();
System.out.println("获取服务器版本线程异常!"+e);
}
Looper.loop();
};
}.start();
return false;
}
//下载apk文件
public void downloadApkFile(Context context){
String savePath = Environment.getExternalStorageDirectory()+"/AndroidUpdateDemo.apk";
String serverFilePath = "http://192.168.226.106/AndroidUpdateDemo.png";
try {
if(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())){
URL serverURL = new URL(serverFilePath);
HttpURLConnection connect = (HttpURLConnection) serverURL.openConnection();
BufferedInputStream bis = new BufferedInputStream(connect.getInputStream());
File apkfile = new File(savePath);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(apkfile));
int fileLength = connect.getContentLength();
int downLength = 0;
int progress = 0;
int n;
byte[] buffer = new byte[1024];
while((n=bis.read(buffer, 0, buffer.length))!=-1){
bos.write(buffer, 0, n);
downLength +=n;
progress = (int) (((float) downLength / fileLength) * 100);
Message msg = new Message();
msg.arg1 = progress;
MainActivity.handler.sendMessage(msg);
//System.out.println("发送"+progress);
}
bis.close();
bos.close();
connect.disconnect();
}
} catch (Exception e) {
System.out.println("下载出错!"+e);
}
/*AlertDialog.Builder builder = new Builder(context);
builder.setTitle("下载apk" ) ;
builder.setMessage("正在下载" ) ;
builder.setPositiveButton("确定",null);
builder.show();*/
}
}
具体实现都在UpdateManager类中,详细说明一下,其中,
getVersion(Context context)、getVersionName(Context context)本地版本的获取很简单一看就懂;
getServerVersion()服务器版本的获取:读取服务器目录下的ver.aspx文件,返回json字符串;
compareVersion(Context context)比较版本:启动线程,读取json字符串,并解析服务器版本赋值到serverVersion中,并且比较本地版本和服务器版本,如果低于服务器版本,就启动新线程下载apk文件;
downloadApkFile(Context context)下载apk文件:设置文件保存路径,服务器访问路径,通过HTTP协议下载文件,这里测试的时候,apk文件无法下载,故将服务器的apk修改扩展名为png格式,下载完成后保存为apk文件。
搭建本地Web服务器:
1、开启功能:控制面板-> 程序-> 程序和功能 -> 打开或关闭Windows功能,将“Internet信息服务”下的所有功能都打开。
2、设置防火墙:控制面板-> 系统安全 -> Windows防火墙 -> 允许程序通过Windows防火墙,勾选“万维网服务(HTTP)”。
3、以上步骤完成后,web服务器就搭好了,可以win+R,运行cmd,键入ipconfig /all ,查看本机IP地址,打开浏览器输入地址ip地址测试一下,如果打开的是IIS7网页,说明成功了。
然后就是将新版本的apk放到服务器目录下,一般是系统盘目录下C:\inetpub\wwwroot文件夹中。
放置两个文件,一个是2.0版本的apk文件,一个是ver.aspx文件用于获取服务器版本的json字符串,里面的内容为:[{"appname":"AndroidUpdateDemo","apkname":"AndroidUpdateDemo.apk","versionName":"02.00.01","version":"2"}] 。
由于测试时候apk文件无法直接下载,想了个办法将apk文件扩展名改为png,在Android端下载完成后把它在保存为apk文件。
上述操作结束后,服务器端就完全搭好了,可以开始测试升级流程。