android如何在wifi环境下 后台静默下载 新版apk?

前段时间,公司有个需求,要求每次用户打开app的时候,请求后台的接口,查看是否有最新版本的包,如果有更新,则去后台偷偷的下载最新版本的apk,考虑到用户流量,要求下载apk必须是在wifi环境下下载,基于此需求,主要有如下几个方面的考虑:


一、app首页请求接口,根据后台返回的最新版本号,以及数据库存的版本号,判断是否需要开始下载,还是接着上次下载

二、下载管理器:如果需要下载,则开启service,service中开启一个线程,让线程去下载apk,注意:如果wifi断了,一定要关闭线程,关闭service

三、对wifi写个广播接收者,如果wifi断了,这时候应该停止下载,如果wifi又连上了,则继续上次的下载

四、数据库:如果此时wifi断了,然后新版本又下载了一部分了,此时需要暂停下载,将已经下载的部分,包括下载的进度,新版的版本号等信息存入数据库中,基于此考虑,第一条,还需要根据数据库存入的版本号做比对,因为如果本地是1,数据库存的是2,这时候请求接口,发现接口返回是3,则需要更新数据库,并将已经下载的本地文件删除,重新下载

贴部分代码:

一、

//请求是否需要更新,请求后台的接口

requestVersionUpdate();

//后台接口返回

@Override

public voidonDataChanged(UpdateVersion data, NetworkHelper helper) {

if(null!= data) {

intro= data.intro;//更新文案

download_link= data.download_link;//新版本的下载链接

newVersion= data.version_code;//新版本的code

mDao=newThreadDaoImpl(SplashActivity.this);//得到数据库操作对象

threadInfo=mDao.select();//查询数据库里保存的纪录,如果没有,则为空

if(null!=threadInfo) {

dbVersion=threadInfo.getVersioncode();//得到数据库里保存的,上次下载的apk的版本号

}

fileName="/ceshi.apk";

forceInstall= data.force_update;//是否强制用户安装

//当前程序的版本号

intcurrentVersionCode = CommonHelper.getVersionCode(getApplicationContext());

if(newVersion== currentVersionCode) {

//如果有文件,则删除apk所在的文件

File file =newFile(DownloadService.DOWNLOAD_PATH);

if(file.exists()) {

FileUtil.deleteFile(file);

}

}else{

DownloadHelper downloadHelper =newDownloadHelper(SplashActivity.this);

if(dbVersion== -1) {

//通知下载器去下载,并且把纪录插入数据库中

ThreadInfo info =newThreadInfo(0,download_link,0,0,0,newVersion, MySqliteHelper.UNDOWNLOAD,intro, DownloadService.DOWNLOAD_PATH,fileName);

if(!mDao.isExists(newVersion)) {

mDao.insertThread(info);

}

//如果文件已经存在,则删除文件,防止用户已经部分下载了,然后把程序卸载了,后来又重新安装,此时需要将文件删除

File file =newFile(info.getDownloadFile());

if(file.exists()) {

FileUtil.deleteFile(file);

}

downloadHelper.downloadApk(info);

}else if(newVersion>dbVersion) {

//从数据库里查询是否下载过apk,如果有则删除下载的apk文件,并且将dbversion更新为最新的版本号

File file =newFile(threadInfo.getDownloadFile() +threadInfo.getFileName());

Log.i("anru","newVersion > dbVersion:::file:"+ file.toString());

// 路径为文件且不为空则进行删除

if(file.isFile() && file.exists()) {

file.delete();

mDao.deleteThread(dbVersion);

}

//删除之后,去启动下载

//通知下载器去下载

ThreadInfo info =newThreadInfo(0,download_link,0,0,0,newVersion, MySqliteHelper.UNDOWNLOAD,intro, DownloadService.DOWNLOAD_PATH,fileName);

if(!mDao.isExists(newVersion)) {

mDao.insertThread(info);

}

downloadHelper.downloadApk(info);

}else if(newVersion==dbVersion&&dbVersion> currentVersionCode) {

//从数据库里查询是否下载过apk,如果有则删除下载的apk文件,并且将dbversion更新为最新的版本号

File file =newFile(threadInfo.getDownloadFile() +threadInfo.getFileName());

if(threadInfo.getApkstatus() != MySqliteHelper.DOWNLOAD_COM) {

//继续去下载

downloadHelper.downloadApk(threadInfo);

}else if(!MD5Helper.getMD5(file).equals(data.apk_md5)) {//如果md5值不一致,则删除原文件,重新下载

// 路径为文件且不为空则进行删除

if(file.isFile() && file.exists()) {

file.delete();

mDao.deleteThread(dbVersion);

}

//删除之后,去启动下载

//通知下载器去下载

ThreadInfo info =newThreadInfo(0,download_link,0,0,0,newVersion, MySqliteHelper.UNDOWNLOAD,intro, DownloadService.DOWNLOAD_PATH,fileName);

if(!mDao.isExists(newVersion)) {

mDao.insertThread(info);

}

}else{

//提示用户安装

isShowInstall=1;

}

}

}

}

二、下载管理器:

//开启服务

Intent intent =newIntent(context, DownloadService.class);

intent.putExtra("info",info);

DownloadTask.mIsPause=false;

context.startService(intent);

//在服务页面,开启线程

@Override

public intonStartCommand(Intent intent,intflags,intstartId) {

try{

ThreadInfo info = (ThreadInfo) intent.getSerializableExtra("info");

if(info.getApkstatus() != MySqliteHelper.DOWNLOAD_COM) {//如果暂时未下载,去下载

//判断网络状态

if(isWifiAvailable()) {

thread=newInitThread(info);

thread.start();

}

}

}catch(Exception e) {

e.printStackTrace();

Log.i("anru","download kill");

DownloadTask.mIsPause=true;

stopSelf();

}

return super.onStartCommand(intent, flags, startId);

}

//下载的线程

classDownLoadThread extends Thread {

privateThreadInfo info;

public DownLoadThread(ThreadInfo info) {

this.info= info;

}

@Override

public voidrun() {

Log.i("anru","download开始下载");

Log.i("anru","apkstatus:"+info.getApkstatus());

HttpURLConnection conn =null;

RandomAccessFile raf =null;

InputStream in =null;

try{

URL url =newURL(info.getUrl());

conn = (HttpURLConnection) url.openConnection();

conn.setConnectTimeout(3000);

conn.setDoInput(true);

conn.setRequestMethod("GET");

// 设置下载位置

int start =info.getStart() +info.getFinished();

conn.setRequestProperty("Range",

"bytes="+ start +"-"+info.getEnd());

// 设置文件写入位置

File file =new File(info.getDownloadFile(),info.getFileName());

raf =new RandomAccessFile(file,"rwd");

raf.seek(start);

//Intent intent = new Intent(DownloadService.ACTION_UPDATE);

finished+=info.getFinished();

// 开始下载

if(conn.getResponseCode() ==206|| conn.getResponseCode() ==200) {//206 Partial Content

// 读取数据

in = conn.getInputStream();

intlen = -1;

byte[] b =new byte[1024*4];

longtime = System.currentTimeMillis();

while((len = in.read(b)) != -1) {

// 写入文件

raf.write(b,0, len);

finished+= len;

Log.i("anru","finished:"+finished);

info.setFinished(finished);

if(finished==info.getEnd()) {

info.setApkstatus(MySqliteHelper.DOWNLOAD_COM);

}else if(finished>0&&finished

info.setApkstatus(MySqliteHelper.DOWNLOAD_UNCOM);

}

mDao.updateThread(info);

// 在下载暂停时,保存下载进度

if(mIsPause) {

Log.i("anru","mIsPause");

return;

}

}

}

}catch(Exception e) {

Log.e("anru","跳出来了");

}finally{

try{

raf.close();

if(null!= in) {

in.close();

}

conn.disconnect();

}catch(Exception e) {

e.printStackTrace();

}

}

}

三、wifi监听器广播

@Override

public void onReceive(Context context, Intent intent) {

//TODO Auto-generated method stub

if(intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {//wifi连接上与否

NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);

if(info.getState().equals(NetworkInfo.State.DISCONNECTED)) {

//暂停apk的下载

Intent intent1 =newIntent(context, DownloadService.class);

context.stopService(intent1);

}else if(info.getState().equals(NetworkInfo.State.CONNECTED)) {

//继续去下载

DownloadHelper downloadHelper =newDownloadHelper(context);

ThreadDaoImpl mDao =newThreadDaoImpl(context);

ThreadInfo threadInfo = mDao.select();

downloadHelper.downloadApk(threadInfo);

}

}

}

四、数据库:

public interface ThreadDao {

public void insertThread(ThreadInfo info);

public void updateThread(ThreadInfo info);

public List getThreads(String url);

public boolean isExists(intversionCode);

public ThreadInfo select();

public void deleteThread(intversionCode);


上边代码只挑了一些比较重点的贴了,如果想下载demo,链接:

点击下载demo

http://download.csdn.net/detail/forever521_/9510974

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容