修改 MultiPointOutputStream 类的 close 和 flushProcess 方法。该解决方法只保证在下载出错时会回调taskEnd,因此只解决了下载卡死的问题,下载出错问题暂未解决,待后续研究。
具体修改如下:
// close 方法要保证 outputStreamMap 和 noSyncLengthMap 的元素个数相等,只修改这里没有作用
synchronized void close(int blockIndex) throws IOException {
final DownloadOutputStream outputStream = outputStreamMap.get(blockIndex);
if (outputStream != null) {
outputStream.close();
// outputStreamMap.remove(blockIndex);
synchronized (noSyncLengthMap) {
// make sure the length of noSyncLengthMap is equal to outputStreamMap
outputStreamMap.remove(blockIndex);
noSyncLengthMap.remove(blockIndex);
}
Util.d(TAG, "OutputStream close task[" + task.getId() + "] block[" + blockIndex + "]");
}
}
// flushProcess 增加 catch 块
void flushProcess() throws IOException {
boolean success;
final int size;
synchronized (noSyncLengthMap) {
// make sure the length of noSyncLengthMap is equal to outputStreamMap
size = noSyncLengthMap.size();
}
final SparseArray<Long> increaseLengthMap = new SparseArray<>(size);
try {
for (int i = 0; i < size; i++) {
final int blockIndex = outputStreamMap.keyAt(i);
// because we get no sync length value before flush and sync,
// so the length only possible less than or equal to the real persist
// length.
final long noSyncLength = noSyncLengthMap.get(blockIndex).get();
if (noSyncLength > 0) {
increaseLengthMap.put(blockIndex, noSyncLength);
final DownloadOutputStream outputStream = outputStreamMap
.get(blockIndex);
outputStream.flushAndSync();
}
}
success = true;
} catch (IOException ex) {
Util.w(TAG, "OutputStream flush and sync data to filesystem failed " + ex);
success = false;
} catch (Exception ex) { // 增加这部分,catch住其他类型exception
Util.w(TAG, "OutputStream flush and sync data to filesystem failed " + ex);
success = false;
}
if (success) {
final int increaseLengthSize = increaseLengthMap.size();
long allIncreaseLength = 0;
for (int i = 0; i < increaseLengthSize; i++) {
final int blockIndex = increaseLengthMap.keyAt(i);
final long noSyncLength = increaseLengthMap.valueAt(i);
store.onSyncToFilesystemSuccess(info, blockIndex, noSyncLength);
allIncreaseLength += noSyncLength;
noSyncLengthMap.get(blockIndex).addAndGet(-noSyncLength);
Util.d(TAG, "OutputStream sync success (" + task.getId() + ") "
+ "block(" + blockIndex + ") " + " syncLength(" + noSyncLength + ")"
+ " currentOffset(" + info.getBlock(blockIndex).getCurrentOffset()
+ ")");
}
allNoSyncLength.addAndGet(-allIncreaseLength);
lastSyncTimestamp.set(SystemClock.uptimeMillis());
}
}
OkDownload Version
v1.0.7
Problem Describe
下载稍大文件就会发生下载进度卡死的问题,导致不会回调taskEnd;将targetSdkVersion改为29,在Android 10上复现概率不低。
Log
日志如下,只摘了这一条: The current offset on block-info isn't update correct, 2920 != 10006923 on 1.
Reason
MultiPointOutputStream 的 flushProcess 方法没有catch住其他exception,导致刷新下载进度时 syncFuture 线程异常退出 ,使其他下载线程无法同步下载状态而陷入等待状态,导致下载进度卡死。
Solution
修改 MultiPointOutputStream 类的 close 和 flushProcess 方法。该解决方法只保证在下载出错时会回调taskEnd,因此只解决了下载卡死的问题,下载出错问题暂未解决,待后续研究。 具体修改如下: