网络断开后重连downloadProvider继续下载问题

最近在安卓4.4上遇到一个断开wifi后重新连接wifi, downloadProvider继续下载文件失败的问题。于是开始了解下载管理模块的断点续载功能:

1、首先,分析android log, 当将网络断开之后,下载会中止,出现如下信息:

W/DownloadManager(29473): Aborting request for download 5: Failed reading response: java.net.SocketException: recvfrom failed: ETIMEDOUT (Connection timed out)
I/DownloadManager(29473): Download 5 finished with status WAITING_FOR_NETWORK

在代码中搜索Failed reading response, 发现是在下载数据中不断读取网络数据流时抛出的异常:
/**
* Transfer as much data as possible from the HTTP response to the
* destination file.
*/
private void transferData(State state, InputStream in, OutputStream out)
throws StopRequestException {
final byte data[] = new byte[Constants.BUFFER_SIZE];
for (;;) {
int bytesRead = readFromResponse(state, data, in);

if (bytesRead == -1) { // success, end of stream already reached
handleEndOfStream(state);
return;
}

state.mGotData = true;
writeDataToDestination(state, data, bytesRead, out);
state.mCurrentBytes += bytesRead;
reportProgress(state);
checkPausedOrCanceled(state);
}

在循环中不停读取网络那边的响应,当网络断开后,InputStream的读接口应该就会抛出异常,代码中进行捕捉,并且判断之后是否能够断点续载,然后抛出相应信息:

/**
* Read some data from the HTTP response stream, handling I/O errors.
* @param data buffer to use to read data
* @param entityStream stream for reading the HTTP response entity
* @return the number of bytes actually read or -1 if the end of the stream has been reached
*/
private int readFromResponse(State state, byte[] data, InputStream entityStream)
throws StopRequestException {
try {
return entityStream.read(data);
} catch (IOException ex) {
ContentValues values = new ContentValues();
values.put(Downloads.Impl.COLUMN_CURRENT_BYTES, state.mCurrentBytes);
mContext.getContentResolver().update(mInfo.getAllDownloadsUri(), values, null, null);

if (cannotResume(state)) {
throw new StopRequestException(STATUS_CANNOT_RESUME,
"Failed reading response: " + ex + "; unable to resume", ex);
} else {
throw new StopRequestException(STATUS_HTTP_DATA_ERROR,
"Failed reading response: " + ex, ex);
}
}
}

这里的判断是否能够续载,有很多条件, 主要是两个方面,下载字节数是否大于0 或者 是否DRM 下载需要转换:
D/DownloadManager( 9658): state.mCurrentBytes=5257536 state.mHeaderETag=69b8155f8ae29636cec71afb21637c92 mInfo.mNoIntegrity=false state.mMimeType=application/vnd.android.package-archive

导出数据库,查看此时下载管理该文件状态:

这个状态 status = 195 是怎么来的呢?

我们可以继续跟踪代码,前面说了,当网络断开后,代码开始抛出异常StopRequestException, 并且带有错误码,仔细阅读代码,这个异常是各个方法,
一层一层网上抛出,最后达到下载管理线程 DownloadThread 类中的 run中, 它在catch这个异常后,也会打印出log信息,并且增加了处理:
catch (StopRequestException error) {
// remove the cause before printing, in case it contains PII
errorMsg = error.getMessage();
String msg = "Aborting request for download " + mInfo.mId + ": " + errorMsg;
Log.w(Constants.TAG, msg);
if (Constants.LOGV) {
Log.w(Constants.TAG, msg, error);
}
finalStatus = error.getFinalStatus();

从代码中可以看出其增加了下载文件在数据库中存放的Id信息,然后在加上出错新消息,也就我们最终看到的log:
W/DownloadManager(29473): Aborting request for download 5: Failed reading response: java.net.SocketException: recvfrom failed: ETIMEDOUT (Connection timed out)

在输出完信息之后,其会对错误码判断进行处理,想断网这种问题,会有个继续尝试,然后确定最终的错误码。最初抛出异常的错误码是STATUS_HTTP_DATA_ERROR , 即495.

W/DownloadManager(11584): Aborting request for download 5: Failed reading response: java.net.SocketException: recvfrom failed: ETIMEDOUT (Connection timed out)
D/DownloadManager(11584): -----finalStatus=495

最后经过代码转换:
// Some errors should be retryable, unless we fail too many times.
if (isStatusRetryable(finalStatus)) {
if (state.mGotData) {
numFailed = 1;
} else {
numFailed += 1;
}

if (numFailed it = mActiveNotifs.keySet().iterator();
while (it.hasNext()) {
final String tag = it.next();
if (!clustered.containsKey(tag)) {//没有包含在tag列表中的,需要清除
mNotifManager.cancel(tag, 0);
it.remove();
}
}

log信息, 构建好的tag形式就是type: id, 当然这是已经下载完成的:
D/DownloadManager(32155): =====tag=3:15
D/DownloadManager(32155): =====tag=3:14
D/DownloadManager(32155): =====tag=3:13
D/DownloadManager(32155): =====tag=3:12
D/DownloadManager(32155): =====tag=3:6
D/DownloadManager(32155): =====tag=3:19
D/DownloadManager(32155): =====tag=3:18
D/DownloadManager(32155): =====tag=3:17
D/DownloadManager(32155): =====tag=3:16
D/DownloadManager(32155): =====tag=3:20
D/DownloadManager(32155): =====tag=3:11
D/DownloadManager(32155): =====tag=3:10
D/DownloadManager(32155): =====tag=3:21
D/DownloadManager(32155): =====tag=1:com.android.browser
D/DownloadManager(32155): =====remove tag=1:com.android.browser

还有就是那种执行过一键清理后,那种更新信息也不会再显示在通知栏中了,因为其tag为null, 也已经不包含在tag列表中了。

时间: 2024-08-04 04:41:49

网络断开后重连downloadProvider继续下载问题的相关文章

用代码控制网络断开与重连

看到这个标题,如果你想说谁会这么蛋疼,有网不好好上,那么说明你还是一个纯洁的少年.自动重拨的需求所在多有,主要是为了绕过各大网站对相同IP地址的重复请求次数限制等等.具体的我不说了,说多了说我教坏小孩子.我最近研究这个只是因为我想写个软件自动播放和下载某个网站的视频,but这个网站一天只让同个IP免费看五个视频,我又抠不愿意花钱,但是又特别想多看多载几部.什么,你要我把网站地址告诉你?还是算了吧,传播XX(se)OO(qing)是违法的知道不. 按惯例,先声明:技术知识浩瀚无垠,笔者但求浅尝辄止

netty用户退出,网络断开,重连删除用户信息

netty断开连接之后,需要清除用户信息 在添加的myhandler中 重写channelInactive方法 原文地址:https://www.cnblogs.com/mfser/p/9958929.html

Mysql网络断开重连问题

最近做一个项目的后台守护程序,需要多线程对mysql数据库服务进行操作,为了加强守护撑的健壮性,特地连接成功后拔掉网线,然后测试守护程序断开重新连接的健壮性,可是发现网络断开后,重新插上网线,用mysql_real_conncet进行重新连接返回的永远是假,也就是重新连接失败,之后我想断开网络后重新将mysql连接释放(mysql_close(MYSQL )),并重新初始化mysql_init((MYSQL )),然后再用mysql_real_conncet()函数进行连接,但是这样做的后果是m

【bug-004】【tcp】网络断开重连后,客户端recv函数一直阻塞,不会返回

[前提]客户端采用tcp阻塞模式[现象]与相机设备建立连接后,偶尔出现几次突然就收不到相机发过来的数据:几经排查,怀疑跟网络波动有关,于是通过插拔网线来模拟网络波动,果然bug复现. [原因](个人理解)每一个节点(包括服务器.客户端.中间节点)都应该会用一个五元组(源IP.源端口.目的IP.目的端口和协议)来纪录一个tcp会话,哪一个节点出现网络波动,那么该节点的纪录就会被清空.所以网络恢复后,服务器端(相机)发来的数据就不会到达客户端,客户端则一直阻塞在recv函数. [解决方案]1.换成非

关于LWIP断开网线后重连问题(热插拔问题)

最近在弄STM32+LWIP协议,在网络拔掉网线情况下,无法重新连接.网上找了好多方法都没有实现,着实郁闷!后来无意间看到了暂时解决这一问题的方法,虽然不是那么完美,但最算能解决问题.分享给大家. 问题:LWIP建立一个TCP服务器,收发数据也正常.但是客户端非正常断线-如客户端掉电,突然拔掉客户端的网线,然后重新连接服务器,就连接不上了. 原因:LWIP_CLOSE(),在非正常断线情况下使用不知道有什么还占着内存释放不了,没法正常释放资源.有高手知道怎么释放,可以指点一下. 我的方法是:使用

[转载]win7休眠后网络断开怎么办?如何设置?

http://jingyan.baidu.com/article/8065f87fc87d0423312498af.html 有时会遇到在Windows7系统休眠模式下会自动断开网络连接,唤醒系统也是无法连接,网络断开,怎么办呢?首先win7系统是没有问题的,其次在Windows7系统中也介绍过休眠模式在待机的状态下是不会断开网络的,下面教大家如何解决休眠后网络断开的问题. 方法/步骤 具体步骤如下:1,右键单击桌面上的“计算机”属性, 2,单击左侧的“设备管理器”: 3,点击网络适配器: 4,

让命令提交后不受本地关闭终端窗口/网络断开连接的干扰

项目中操作场景:本地机器上通过ssh连接服务器进行相关操作.这里就出现一个问题,在我们本地程序中,向服务器发送一个命令是没有任何问题的,可是当本次程序意外关闭或者由于网络断开连接,这是我们通过本地程序在服务器上创建的进程也就会被杀死.所以问题就来了:如何让对应进程能无间断的执行,即通过本机程序在服务器上创建一个进程,当本地关闭ssh连接或者与服务器的网络断开之后,这个创建的进程要继续存在而不会被杀死.在IBM 上看到一遍文章,对这个问题的解决方法讲解的很详细,现在简要介绍下: 我们知道,当用户注

VPN断开自动重连

使用windows server 2008 R2自带服务建的PPTP,两台服务器通过VPN进行数据同步.连接一段时间后,VPN会自动断开,数据同步也会停止.这给工作带来了很大的麻烦. 检测网络中断,服务端需要开通ping,windows server 2008 R2默认没有开启icmp,需要在防火墙配置icmp响应,启用”文件和打印机共享(回显请求 - ICMPv4-In)“选项即可. VPN自动重连VPN: 1 @echo on 2 :a 3 rem 廷时60秒 4 ping -n 60 12

[android] 网络断开的监听

标签: android 网络监听 杂谈 分类: Android [转自]  http://blog.sina.com.cn/s/blog_5d5996d001012o07.html 其实手机在网络方面的的监听也比较重要,有时候我们必须实时监控这个程序的实时网络状态,android在网络断开与连接的时候都会发出广播,我们通过接收系统的广播就可以实现网络的监听,下面是代码--- onCreate的时候实例化 //监听器     private NetState receiver=new NetSta