APP升级的流程是
1 访问服务器获取APP更新消息
2 下载APP到本地
3 从本地更新到本地
一般是用HTTP来获取 ,主要目的是为了获取是否有更新包, 更新包下载路径
private boolean check_server_version()
{
AsyncHttpClient client = new AsyncHttpClient();
RequestParams params = new RequestParams();
path =mserverIP + path ;
Log.e("data_____",path);
params.put("serial_num","hello");
client.post(path, params, new AsyncHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, cz.msebera.android.httpclient.Header[] headers, byte[] responseBody) {
String s = new String(responseBody);
JSONObject jsonObject1 = null;
try {
jsonObject1 = new JSONObject(s );
Log.e("data_",jsonObject1.toString());
if(jsonObject1.getInt("apk_state")==1){
is_update = true;
update_msg = jsonObject1.getString("apk_msg");
version = jsonObject1.getDouble("apk_version");
String apk_name = jsonObject1.getString("apk_name");
String apk_dir=jsonObject1.getString("apk_dir");
mdownload_path = mserverIP+ "/tractor_client/download_apk/" + apk_name;
Log.e("data_",mdownload_path);
showUpdataDialog("新版本:"+version+"\r\n"+update_msg);
}else{
is_update = false;
}
}catch (Exception e){
// Toast.makeText(context,"注册失败!",Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(int statusCode, cz.msebera.android.httpclient.Header[] headers, byte[] responseBody, Throwable error) {
}
});
return true;
}
mdownload_path是服务器APP路径
downLoadPath是安卓本地路径,这里记得加SD卡路径
private void downloadApk() {
try {
final long startTime = System.currentTimeMillis();
Log.i("DOWNLOAD", "startTime=" + startTime);
//获取文件名
URL myURL = new URL(mdownload_path);
URLConnection conn = myURL.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
int fileSize = conn.getContentLength();//根据响应获取文件大小
Log.i("DOWNLOAD", "总大小="+fileSize);
if (fileSize <= 0) throw new RuntimeException("无法获知文件大小 ");
if (is == null) throw new RuntimeException("stream is null");
File file1 = new File(downLoadPath);
if (!file1.exists()) {
file1.mkdirs();
}
//把数据存入路径+文件名
FileOutputStream fos = new FileOutputStream(downLoadPath + "/" + newApkName);
byte buf[] = new byte[1024];
int downLoadFileSize = 0;
do {
//循环读取
int numread = is.read(buf);
if (numread == -1) {
break;
}
fos.write(buf, 0, numread);
downLoadFileSize += numread;
Log.i("DOWNLOAD", "downLoadFileSize="+downLoadFileSize);
Log.i("DOWNLOAD", "fileSize="+fileSize);
Log.i("DOWNLOAD", "download downLoadFileSize="+(int)((float)downLoadFileSize*100/fileSize));
progressDialog.setProgress((int)((float)downLoadFileSize*100/fileSize));
//更新进度条
} while (true);
delOldApk();
progressDialog.dismiss();
showInstallDialog("下载完成,是否安装?");
Log.i("DOWNLOAD", "download success");
Log.i("DOWNLOAD", "totalTime=" + (System.currentTimeMillis() - startTime));
is.close();
} catch (Exception ex) {
Log.e("DOWNLOAD", "111111 error: " + ex.getMessage(), ex);
progressDialog.cancel();
try{
AlertDialog.Builder adBd=new AlertDialog.Builder(context);
adBd.setTitle("下载错误");
adBd.setMessage("检查网络或者服务器!");
adBd.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
adBd.show();
}
catch (Exception e){
Log.e("DOWNLOAD_EEE", "111111 error: " + ex.getMessage(), ex);
}
}
}
这里直接把安装包的路径传递过来,然后调用系统的安装器进行安装
private void installApk(Context context, File file) {
Intent intent = new Intent(Intent.ACTION_VIEW);
//判断是否是AndroidN以及更高的版本
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri contentUri = FileProvider.getUriForFile(context, "com.baozun.book.fileProvider", file);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
} else {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
}
context.startActivity(intent);
}
完整代码
package com.example.administrator.test;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.FragmentManager;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Looper;
import android.support.v4.content.FileProvider;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.kconponent.Ksql.KSQLConfigHelper;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.RequestParams;
import org.json.JSONObject;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
public class UpdateManager {
private String downLoadPath = Environment.getExternalStorageDirectory().getPath()+"/client/";
private String url = "";//apk下载地址
private boolean isforce = false;
private String oldApkName = "old_tractor.apk";
private String newApkName = "new_tractor.apk";
private Context context;
private AlertDialog.Builder updataDialog;
private AlertDialog.Builder installDialog;
private ProgressDialog progressDialog;
private FragmentManager fm;
public static UpdateManager updateManager;
private String mserverIP;
private String mdownload_path;
private boolean is_update = false;
private double version =0;
private String update_msg;
private String path = "/tractor_client/get_apk_update";
public static UpdateManager getInstance() {
if (updateManager == null) {
updateManager = new UpdateManager();
}
return updateManager;
}
public void start(){
// update
if(check_server_version()){
}
// if(checkIsHaveNewAPK()){
// showInstallDialog("发现新版本,是否安装?");
// }else{
// showUpdataDialog("最新");
// }
}
/**
* 版本更新提示框
*/
public void showUpdataDialog(String content) {
updataDialog = new AlertDialog.Builder(context);
updataDialog.setTitle("检查更新");
updataDialog.setMessage( content);
updataDialog.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
updataDialog.setPositiveButton("确定更新", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
createProgress(context);
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
downloadApk();
Looper.loop();//增加部分
}
}).start();
}
});
updataDialog.show( );
}
/**
* 弹出安装Dialog
*/
private void showInstallDialog(String content){
installDialog = new AlertDialog.Builder(context);
installDialog.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
installDialog.setPositiveButton("确认", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
File fileAPK = new File(downLoadPath, newApkName);
installApk(context, fileAPK);
}
});
installDialog.show();
}
private boolean check_server_version()
{
AsyncHttpClient client = new AsyncHttpClient();
RequestParams params = new RequestParams();
path =mserverIP + path ;
Log.e("data_____",path);
params.put("serial_num","hello");
client.post(path, params, new AsyncHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, cz.msebera.android.httpclient.Header[] headers, byte[] responseBody) {
String s = new String(responseBody);
JSONObject jsonObject1 = null;
try {
jsonObject1 = new JSONObject(s );
Log.e("data_",jsonObject1.toString());
if(jsonObject1.getInt("apk_state")==1){
is_update = true;
update_msg = jsonObject1.getString("apk_msg");
version = jsonObject1.getDouble("apk_version");
String apk_name = jsonObject1.getString("apk_name");
String apk_dir=jsonObject1.getString("apk_dir");
mdownload_path = mserverIP+ "/tractor_client/download_apk/" + apk_name;
Log.e("data_",mdownload_path);
showUpdataDialog("新版本:"+version+"\r\n"+update_msg);
}else{
is_update = false;
}
}catch (Exception e){
// Toast.makeText(context,"注册失败!",Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(int statusCode, cz.msebera.android.httpclient.Header[] headers, byte[] responseBody, Throwable error) {
}
});
return true;
}
/**
* 检查有没有最新的APK
*/
private boolean checkIsHaveNewAPK(){
File file = new File(downLoadPath);
if (!file.exists()) {
file.mkdirs();
}
File fileAPK = new File(downLoadPath, newApkName);
if(fileAPK.exists()){
return true;
}
return false;
}
/**
* 删除旧的apk
*/
private void delOldApk(){
File fileAPK = new File(downLoadPath, oldApkName);
if(fileAPK.exists()){
fileAPK.delete();
}
}
/**
* 下载APK
*/
private void downloadApk() {
try {
final long startTime = System.currentTimeMillis();
Log.i("DOWNLOAD", "startTime=" + startTime);
//获取文件名
URL myURL = new URL(mdownload_path);
URLConnection conn = myURL.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
int fileSize = conn.getContentLength();//根据响应获取文件大小
Log.i("DOWNLOAD", "总大小="+fileSize);
if (fileSize <= 0) throw new RuntimeException("无法获知文件大小 ");
if (is == null) throw new RuntimeException("stream is null");
File file1 = new File(downLoadPath);
if (!file1.exists()) {
file1.mkdirs();
}
//把数据存入路径+文件名
FileOutputStream fos = new FileOutputStream(downLoadPath + "/" + newApkName);
byte buf[] = new byte[1024];
int downLoadFileSize = 0;
do {
//循环读取
int numread = is.read(buf);
if (numread == -1) {
break;
}
fos.write(buf, 0, numread);
downLoadFileSize += numread;
Log.i("DOWNLOAD", "downLoadFileSize="+downLoadFileSize);
Log.i("DOWNLOAD", "fileSize="+fileSize);
Log.i("DOWNLOAD", "download downLoadFileSize="+(int)((float)downLoadFileSize*100/fileSize));
progressDialog.setProgress((int)((float)downLoadFileSize*100/fileSize));
//更新进度条
} while (true);
delOldApk();
progressDialog.dismiss();
showInstallDialog("下载完成,是否安装?");
Log.i("DOWNLOAD", "download success");
Log.i("DOWNLOAD", "totalTime=" + (System.currentTimeMillis() - startTime));
is.close();
} catch (Exception ex) {
Log.e("DOWNLOAD", "111111 error: " + ex.getMessage(), ex);
progressDialog.cancel();
try{
AlertDialog.Builder adBd=new AlertDialog.Builder(context);
adBd.setTitle("下载错误");
adBd.setMessage("检查网络或者服务器!");
adBd.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
adBd.show();
}
catch (Exception e){
Log.e("DOWNLOAD_EEE", "111111 error: " + ex.getMessage(), ex);
}
}
}
/**
* 强制更新时显示在屏幕的进度条
*/
private void createProgress(Context context) {
progressDialog = new ProgressDialog(context);
progressDialog.setMax(100);
progressDialog.setCancelable(false);
progressDialog.setMessage("正在下载...");
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.show();
}
/**
* 安装apk
*/
private void installApk(Context context, File file) {
Intent intent = new Intent(Intent.ACTION_VIEW);
//判断是否是AndroidN以及更高的版本
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri contentUri = FileProvider.getUriForFile(context, "com.baozun.book.fileProvider", file);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
} else {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
}
context.startActivity(intent);
}
/**
* apk网络地址
*/
public UpdateManager setContext(Context context) {
this.context = context;
return this;
}
/**
* apk网络地址
*/
public UpdateManager setUrl(String url) {
this.url = url;
return this;
}
/**
* 新版本文件名
*/
public UpdateManager setNewFileName(String fileName) {
this.newApkName = fileName;
return this;
}
/**
* 旧版本文件名
*/
public UpdateManager setOldFileName(String fileName) {
this.oldApkName = fileName;
return this;
}
/**
* Fragment管理器
*/
public UpdateManager setFragmentManager(FragmentManager fm) {
this.fm = fm;
return this;
}
/**
* 下载路径
*/
public UpdateManager setDownloadPath(String downLoadPath) {
this.downLoadPath = downLoadPath;
return this;
}
/**
* 是否强制更新
*/
public UpdateManager setIsforce(boolean isforce) {
this.isforce = isforce;
return this;
}
public UpdateManager setServerIP(String mserverIP)
{
this.mserverIP = mserverIP;
return this;
}
}
调用:
UpdateManager.getInstance()
.setContext(context)
.setDownloadPath(downLoadPath)
.setNewFileName(newFileName)
.setOldFileName(oldFileName)
.setIsforce(false)
.setServerIP("http://127.0.0.1:60001")
.start();