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;
}
}
Android实现版本更新的更多相关文章
- android应用版本更新功能---完整版
源码下载地址:csdn下载地址:http://download.csdn.net/download/csdn576038874/9526085 博客园下载地址:http://files.cnblogs ...
- Android程序版本更新--通知栏更新下载安装(转)
Android应用检查版本更新后,在通知栏下载,更新下载进度,下载完成自动安装,效果图如下: 检查当前版本号 AndroidManifest文件中的versionCode用来标识版本,在服务器放一个新 ...
- Android软件版本更新
转的:适合新手学习,但在实际项目中不可这么做. 以下是我转的内容: ================================================================= ...
- android检测版本更新
原理就是从服务器获取版本号和本得apk的版本号对比更新: //检查更新 Activity activity = this; while(activity.getParent ...
- Android提示版本更新的实现
一.首先,参考了以下文章<Android自动检测版本及自动升级> http://www.linuxidc.com/Linux/2011-10/45718p2.htm: 步骤: .检测当前版 ...
- Android关于版本更新下载安装之踩坑记录(针对7.0以上)
最近刚刚把古老的项目targetSdk版本升级到26,升级之前是19(非常非常古老了).那么升级后一些问题开始出现. Android 8.0 (Android O)为了针对一些流氓软件引导用户安装其他 ...
- Android 全局弹出版本更新 Dialog 思考和解决办法
Android 针对版本更新,需要做全局的弹出(需求:版本更新只需要在 App 内全局弹出就可以),思路是使用 AlertDialog ,然后设置 setType 为 TYPE_ALERT_WINDO ...
- Android其它新控件 (转)
原文出处:http://blog.csdn.net/lavor_zl/article/details/51312715 Android其它新控件是指非Android大版本更新时提出的新控件,也非谷歌I ...
- 从 Eclipse 迁移至 Android Studio
从 Eclipse 迁移至 Android Studio 本文内容 Android Studio 基础知识 迁移先决条件 将项目导入 Android Studio 后续步骤 将项目迁移至 Androi ...
随机推荐
- 写入cookie后只显示一次的DIV提示框代码
<script type="text/javascript"> function cookiesave(n, v, mins, dn, path){ if(n) { i ...
- apk文件分析原则
如果在dex生成的jar文件里没有发现关键内容的话,就要注意jar里面的native函数以及loadlibrary操作,从而可以判断出加载了哪些so,调用了什么函数.就不会出现判断不出是不是加载了某s ...
- (转)Java 之 FileReader FileInputStream InputStreamReader BufferedReader 作用与区别
Java 之 FileReader FileInputStream InputStreamReader BufferedReader 作用与区别 ava.io下面有两个抽象类:InputStream和 ...
- HDU 5523 Game
坑题 #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> us ...
- DataGridView如何实现列标头带数据筛选功能,就象Excel高级筛选功能一样
'近日有本论坛网友问:DataGridView如何实现列标头带数据筛选功能,就象Excel高级筛选功能一样 '今晚正好闲着没事,加之以前也没用到过这个需求,所以就写了个模拟功能,供各位坛友酌情参考. ...
- CultureInfo中重要的InvariantCulture
CultureInfo简述 CultureInfo类位于System.Globalization命名空间内,这个类和这个命名空间许多人都不了解也认为不需要太多了解,实际上,你写的程序中会经常间接得使用 ...
- Xcode之Alcatraz
Alcatraz的安装和使用 转发:http://www.cnblogs.com/wendingding/p/4964661.html 一.简单说明 Alcatraz 是一款 Xcode的插件管理工具 ...
- c循环程序
6.用双循环打印n行如下图形. * *** ***** ******* 6 7 8 #include<stdio.h> 9 int main() 10 { 11 int i=0,j=0,n ...
- Laravel 数据插入
Laravel 的数据库操作基于 Eloquent ORM,在插入数据时有以下几种方式,返回结果也不会不同: 1.insert 插入后会返回 true or false: 2.create 插入成功后 ...
- mysql优化----第一篇:综述
一 系统层面 查看CPU和IO状态,确定瓶颈.增 更换设备 二 数据库层面 1 参数优化. 参考文章<mysql性能优化----调整参数>增大数据库内存缓存等设置. 参考 http: ...