Android实现版本更新

时间:2023-03-10 02:27:05
Android实现版本更新

Android 实现从后台下载apk文件,保存到本地sd卡,使用系统安装apk,完成版本更新功能

LoadAppUtil.java

 import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List; /**
* Depiction:
* Author: kuzan
* Date: 2017/01/14 9:42
*/
public class LoadAppUtil { private static List<String> list = new ArrayList<>();
private static final int TIMEOUT = 10 * 60 * 1000; // 超时 public static final int LOAD_PROCESS = 1;
public static final int LOAD_SUCCEED = 2;
public static final int LOAD_ERROR = 3; /**
* 下载apk
* @param context
* @param packageName 保存apk的名称
* @param url apk后台下载的地址
*/
public static void loadApp(Context context, final String packageName, final String url) { final String path = getLoadAppPath(context, packageName); if (StringUtils.isEmptyString(path) || StringUtils.isEmptyString(url)) {
loadError(packageName);
return;
} // 判断是否在下载
if (list.contains(packageName)) {
return;
} list.add(packageName); new Thread(new Runnable() {
@Override
public void run() {
downloadUpdateFile(packageName, url, path);
}
}).start();
} /**
* 文件下载
* @param packageName 保存apk的名称
* @param down_url apk后台下载的地址
* @param file 保存apk的文件路径
* */
public static void downloadUpdateFile(String packageName, String down_url, String file) { int totalSize = 0; // 文件总大小
InputStream in = null;
FileOutputStream fos = null; FileUtils.deleteFile(file);
FileUtils.createFile(file); URL url;
try {
url = new URL(down_url); HttpURLConnection httpURLConnection = (HttpURLConnection) url
.openConnection(); httpURLConnection.setConnectTimeout(TIMEOUT); httpURLConnection.setReadTimeout(TIMEOUT); // 获取下载文件的size
totalSize = httpURLConnection.getContentLength();
Log.e("LoadAppUtil", "totalSize = " + totalSize); if (httpURLConnection.getResponseCode() == 404) {
loadError(packageName);
return;
} in = httpURLConnection.getInputStream();
fos = new FileOutputStream(file, false);
} catch (IOException e) {
e.printStackTrace();
loadError(packageName);
return;
} int downloadCount = 0; // 已下载大小
int updateProgress = 0; // 更新进度 byte buffer[] = new byte[64];
int readsize = 0; try {
LoadBean bean = new LoadBean(packageName,file,0);
post(LOAD_PROCESS,bean);
while ((readsize = in.read(buffer)) != -1) { fos.write(buffer, 0, readsize); // 计算已下载到的大小
downloadCount += readsize; // 先计算已下载的百分比,然后跟上次比较是否有增加,有则更新通知进度
int now = downloadCount * 100 / totalSize;
// Log.e(TAG, "now = " + now) ;
if (updateProgress < now) {
updateProgress = now;
// 发送下载进度
bean.setProcess(now);
post(LOAD_PROCESS,bean);
}
}
} catch (Exception e) {
e.printStackTrace();
loadError(packageName);
return;
} finally {
try {
fos.close();
in.close();
} catch (IOException e) {
e.printStackTrace();
}
} // 发送下载完成消息
if(list.contains(packageName)){
list.remove(packageName);
LoadBean bean = new LoadBean(packageName,file,100);
post(LOAD_SUCCEED,bean);
} } private static void loadError(String packageName) {
if (list.contains(packageName)) {
list.remove(packageName);
}
// 发送下载错误消息
LoadBean bean = new LoadBean(packageName,"",0);
post(LOAD_ERROR,bean);
} /**
* 获取保存apk的文件路径
*
* @param context
* @return
*/
public static String getLoadAppPath(Context context, String packageName) {
if (FileUtils.isSdCardExist()) {
return context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + File.separator + packageName + ".apk";
}
return "";
} /**
* 判断文件是否存在
* @param path 文件路径
* @return
*/
public static boolean isFileExists(String path) {
if (TextUtils.isEmpty(path)) {
return false;
}
try {
File f=new File(path);
if(!f.exists()) {
return false;
}
}
catch (Exception e) {
return false;
} return true;
} /**
* 通知UI
* */
public static void post(int clickId,LoadBean bean){
RxBus.getDefault().post(RxBusEvent.newBuilder(R.id.load_apk).clickId(clickId).setObj(bean).build());
}
}

调用方法:

LoadAppUtil.loadApp(UpdateActivity.this, newVersionName, UrlConstants.UPLOAD_URL);

信息读取:(使用的消息通知是android RxBus)

 mySubscriptions.add(RxBus.getDefault().toObserverable(RxBusEvent.class).subscribe(new Action1<RxBusEvent>() {
@Override
public void call(final RxBusEvent rxBusEvent) {
if (rxBusEvent.getType() == R.id.load_apk) {
switch (rxBusEvent.getClickId()) {
case LoadAppUtil.LOAD_SUCCEED:
runOnUiThread(new Runnable() {
@Override
public void run() {
// 下载完成
Log.e("LOAD", "LOAD_SUCCEED");
AppUtils.installApp(UpdateActivity.this, (LoadBean) rxBusEvent.getObj().getPath());
isLoadFinish = true;
}
});
break; case LoadAppUtil.LOAD_PROCESS:
runOnUiThread(new Runnable() {
@Override
public void run() {
// 下载进度
isLoadFinish = false;
updateProgress((LoadBean) rxBusEvent.getObj());
}
});
break; case LoadAppUtil.LOAD_ERROR:
runOnUiThread(new Runnable() {
@Override
public void run() {
// 下载出错
Log.e("upload", "err");
isLoadFinish = false;
ToastUtils.ToastMessage(UpdateActivity.this, "下载失败");
}
});
break;
}
}
}
}));

LoadBean.java

 public class LoadBean {

     private String packageName;
private String path;
private int process; public LoadBean(String packageName, String path, int process) {
this.packageName = packageName;
this.path = path;
this.process = process;
} public String getPackageName() {
return packageName;
} public void setPackageName(String packageName) {
this.packageName = packageName;
} public String getPath() {
return path;
} public void setPath(String path) {
this.path = path;
} public int getProcess() {
return process;
} public void setProcess(int process) {
this.process = process;
}
}