android APK更新
菜鸟的博客请多多指教
最近做了一个新功能,更新APK的功能
1、更新APK是一个耗时的任务,我采用了一个服务来做,上次在网上看到服务是在主线程里面,自己也测试了下,数据是真的
所以下载动作还必须在服务里面开一个线程来处理下载任务,在写下载任务的时候,由于经验不够,中间出了很多错,下载要分下载开始,下载中,下载异常,下载结束,
2、在后台下载,对用户来说,是看不见的,无法与用户交流,所以在开启服务的时候我就初始化了一个通知,通知在服务开启是初始化,所以其实通知也是在UI线程中,所以想在下载线程中更新通知进度栏,必须通过机制,来更新通知栏的进度条,但是后来组长又给你我一个需求,在点击通知栏时,在更新界面弹出一个对话框,显示是否要停止更新,这里就涉及到一个新的问题,怎样在Service里面获取Activity呢,找了很多资料,最后找到了一个ActivityManager系统服务,他可以得到指定包的任务栈,得到栈顶的Activity,这样就可以在Service中获取Activity里面了
String MY_PKG_NAME = "com.example.sunny.text333";
int i=0;
ActivityManager manager = (ActivityManager) MyApplication.getInstance().getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> list = manager.getRunningTasks(100);
for (ActivityManager.RunningTaskInfo info: list){
if(info.topActivity.getPackageName().equals(MY_PKG_NAME) || info.baseActivity.getPackageName().equals(MY_PKG_NAME)){
break;
}
i++;
}
ActivityManager.RunningTaskInfo info=list.get(i);
String className = info.topActivity.getClassName();//得到栈顶的Activity
Intent intent = null;
try {
intent = new Intent(this,Class.forName(className));
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK| Intent.FLAG_ACTIVITY_SINGLE_TOP);
Bundle bundle = new Bundle();
bundle.putString("flag","取消");
intent.putExtras(bundle);
} catch (ClassNotFoundException e) {
e.printStackTrace();
Log.e("没有找到Activity",""+className);
}
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
|Intent.FLAG_ACTIVITY_NEW_TASK);
pendingIntent = PendingIntent.getActivity(this, 0,intent,PendingIntent.FLAG_UPDATE_CURRENT);
notification.contentIntent =pendingIntent;
Log.e("通知的Activity名称",""+className);
下载线程:
class DownloadThread extends Thread {
String url;
MyHandler handler; public DownloadThread(String url, MyHandler handler) {
this.url = url;
this.handler = handler;
} @Override
public void run() { FileOutputStream fos = null;
InputStream io = null;
try {
handler.sendEmptyMessage(0);
URL u = new URL(url);
Log.e("URL","____________"+u);
HttpURLConnection connection = (HttpURLConnection) u.openConnection();
connection.setConnectTimeout(30000);
connection.setReadTimeout(30000);
io = connection.getInputStream(); if (io != null) {
File file = new File(Environment.getExternalStorageDirectory() + "/" + "mapp.apk");
byte[] buff = new byte[1024];
if (file.exists()) {
file.delete();
} else {
file.createNewFile();
}
fos = new FileOutputStream(file);
int readNum = 0;
int lastPress = 0;//上一次的进度值
int press = 0;//
int fileLength = 0;
int count = 0;//记录文件的读取个数
while (isrunning) {
readNum = io.read(buff);
fileLength = connection.getContentLength();
count += readNum;
press = (int) ((float) count / (float) (fileLength - 1) * 100.0);//下载总大小除以总的大小*100
BigDecimal bd = new BigDecimal(count);
BigDecimal bd1 = new BigDecimal(fileLength - 1);
if (readNum == -1 && bd.toPlainString().equals(bd1.toPlainString())) {// 下载完成
Log.e("sdas", "下载完成");
Message message = new Message();
message.obj = file;
message.what = 2;
handler.sendMessage(message);
break;
} else if (readNum == -1 && !bd.toPlainString().equals(bd1.toPlainString())) {
Log.e("sdas", "下载失败");
handler.sendEmptyMessage(4);
break;
} else if (readNum > 0) {
fos.write(buff, 0, readNum);
// Log.e("sdas", "readNum:" + readNum);
if (press - lastPress >= 1) {
lastPress = press;
// Log.e("sdas", "press:" + press);
Message message = new Message();
message.what = 1;
message.obj = press + "";
handler.sendMessage(message);
}
}
}
fos.flush();
fos.close();
io.close();
}
} catch (MalformedURLException e) {
handler.sendEmptyMessage(4);
e.printStackTrace();
} catch (IOException e) {
handler.sendEmptyMessage(4);
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.flush();
fos.close();
}
if (io != null) {
io.close();
}
} catch (IOException e) { } }
}
}
MyHandler的代码:
class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) { super.handleMessage(msg);
if (msg != null) {
switch (msg.what) {
case 0:// 初始化通知栏和进度条
views.setTextViewText(R.id.tvProcess, "开始下载……");
views.setTextColor(R.id.tvProcess, Color.BLACK);
views.setProgressBar(R.id.app_down_progressBar, 100, 0, false);
notification.defaults = Notification.DEFAULT_LIGHTS;
notification.contentView = views;
nm.notify(NOTIFICATIO_UPDATE_SOFT, notification);
MyApplication.getInstance().setIsupdateing(true);
break;
case 1:
int download_precent = Integer.parseInt(msg.obj.toString());// 获取下载进度
// 更新状态栏上的下载进度信息
views.setTextViewText(R.id.tvProcess, "已下载" + download_precent + "%");
views.setTextColor(R.id.tvProcess, Color.BLACK);
views.setProgressBar(R.id.app_down_progressBar, 100, download_precent, false);
notification.defaults = Notification.DEFAULT_LIGHTS;
notification.contentView = views;
nm.notify(NOTIFICATIO_UPDATE_SOFT, notification);
MyApplication.getInstance().setIsupdateing(true); break;
case 2:
MyApplication.getInstance().setIsupdateing(false);
/* if( unIntallapk()){
Log.e("文件卸载",""+unIntallapk()); }*/
Instanll((File) msg.obj); nm.cancel(NOTIFICATIO_UPDATE_SOFT);
// 停止掉当前的服务
stopSelf();
break;
case 3:// 停止下载
MyApplication.getInstance().setIsupdateing(false);
// 停止掉当前的服务
nm.cancel(NOTIFICATIO_UPDATE_SOFT);
stopSelf();
break;
case 4:// 下载异常
MyApplication.getInstance().setIsupdateing(false);
views.setTextViewText(R.id.tvProcess, "" + "已停止下载");
views.setTextColor(R.id.tvProcess, Color.BLUE);
// 在任务栏不被用户手动删除
notification.flags = Notification.FLAG_AUTO_CANCEL;
// 调用系统默认的声音提示以及震动
notification.defaults = Notification.DEFAULT_ALL;
notification.contentView = views;
nm.cancel(NOTIFICATIO_UPDATE_SOFT);
nm.notify(NOTIFICATIO_UPDATE_SOFT, notification);
break;
default:
break;
}
}
}
}
android APK更新的更多相关文章
- Android Apk增量更新
前言 有关APK更新的技术比较多,例如:增量更新.插件式开发.热修复.RN.静默安装. 下面简单介绍一下: 什么是增量更新? 增量更新就是原有app的基础上只更新发生变化的地方,其余保持原样. 与 ...
- 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新
[原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...
- 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新
上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...
- Android 数据库管理— — —更新数据
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android=" ...
- Android 增量更新(BSDiff / bspatch)
Android 增量更新 BSDiff / bspatchhttp://www.daemonology.net/bsdiff/android的代码目录下 \external\bsdiff bsdiff ...
- android apk 自我保护技术-加密apk
经过了忙碌的一周终于有时间静下来写点东西了,我们继续介绍android apk防止反编译技术的另一种方法.前两篇我们讲了加壳技术(http://my.oschina.net/u/2323218/blo ...
- 如何加密android apk
经过了忙碌的一周终于有时间静下来写点东西了,我们继续介绍android apk防止反编译技术的另一种方法.前两篇我们讲了加壳技术(http://my.oschina.net/u/2323218/blo ...
- android开发 更新升级安装到一半自动闪退
如题:android开发 更新升级安装到一半自动闪退,,,解决办法,如下(红色为我新增的代码) /** * 安装APK文件 */ private void installApk( ...
- Android热更新开源项目Tinker集成实践总结
前言 最近项目集成了Tinker,开始认为集成会比较简单,但是在实际操作的过程中还是遇到了一些问题,本文就会介绍在集成过程大家基本会遇到的主要问题. 考虑一:后台的选取 目前后台功能可以通过三种方式实 ...
随机推荐
- openGL漫游功能简单实现
最近弄openGL漫游功能的时候,在网上找了好多源码都没有达到预期效果,然后就自己写了一个算法分享一下. 上下键实现位移,左右键实现转动. 算法思想:由于改变观察点函数原型为: void gluLoo ...
- git push :推送本地更改到远程仓库的三种模式
摘要:由于在git push过程中,no-fast-forward 的push会被拒绝,如何解决git push失败的问题?这里面有三种方法,分别会形成merge形式的提交历史,线性形式的提交历史,覆 ...
- 使用C#反射中的MakeGenericType函数,来为泛型方法和泛型类指定(泛型的)类型
C#反射中的MakeGenericType函数可以用来指定泛型方法和泛型类的具体类型,方法如下面代码所示这里就不多讲了,详情看下面代码一切就清楚了: using System; using Syste ...
- PL/SQL Developer连接Oracle 11g在Win8 64位系统下乱码
PL/SQL Developer在64位系统上连接Oracle,需要安装32位Oracle client客户端,使用后,发现操作数据库出现乱码的情况.经过查找资料,解决此问题,方法如下: 需要在系统的 ...
- 《机器学习实战》学习笔记一K邻近算法
一. K邻近算法思想:存在一个样本数据集合,称为训练样本集,并且每个数据都存在标签,即我们知道样本集中每一数据(这里的数据是一组数据,可以是n维向量)与所属分类的对应关系.输入没有标签的新数据后,将 ...
- 总结一下今天做的unity面试题(一):刚体的点击事件
按照需求,由于要模拟丧尸被击中的效果,不能使用CharactorControll组件,只能使用rigidbody组件. 首先在场景上摆好僵尸和相机的位置,这里就不给相机加脚本了,直接固定住. 然后给丧 ...
- File相关的读取和写入以及复制
import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.File;import java.io.FileI ...
- JavaScript的apply()方法和call()方法
1 <script type="text/javascript"> 2 /*定义一个人类*/ 3 function Person(name,age) 4 { 5 thi ...
- [Spark] Spark的RDD编程
本篇博客中的操作都在 ./bin/pyspark 中执行. RDD,即弹性分布式数据集(Resilient Distributed Dataset),是Spark对数据的核心抽象.RDD是分布式元素的 ...
- [poj2182] Lost Cows (线段树)
线段树 Description N (2 <= N <= 8,000) cows have unique brands in the range 1..N. In a spectacula ...