CTS DownloadManagerTest testMinimumDownload failed
2016-04-27 17:56
411 查看
DownloadManagerTest testMinimumDownload代码如下:
当下载完成之后会关闭这个ParcelFileDescriptor会调用这个OnCloseListener。然后后者会将ParcelFileDescriptor对应的文件大小信息更新到数据库中。
testMinimumDownload接着回去调用DownloadManager的enqueue,最终会导致DownloadProvider启动一个DownloadThread去下载对应的文件。
这里下载完成后会通知DownloadProvider下载完成,进而导致前面的ParcelFileDescriptor对象被close导致OnCloseListener执行。
同时DownloadThread继续执行finalizeDestination方法:
这里会重命名下载的文件。如果这个操作比OnCloseListener先被执行就导致,onCloseListener将数据库的下载文件大小信息跟新为0.
从而导致testMinimumDownload后续查询下载文件大小做assert操作失败。
public void testMinimumDownload() throws Exception { final DownloadCompleteReceiver receiver = new DownloadCompleteReceiver(); try { IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE); mContext.registerReceiver(receiver, intentFilter); long id = mDownloadManager.enqueue(new Request(getMinimumDownloadUrl())); receiver.waitForDownloadComplete(LONG_TIMEOUT, id); ParcelFileDescriptor fileDescriptor = mDownloadManager.openDownloadedFile(id); assertEquals(MINIMUM_DOWNLOAD_BYTES, fileDescriptor.getStatSize()); Cursor cursor = null; try { cursor = mDownloadManager.query(new Query().setFilterById(id)); assertTrue(cursor.moveToNext()); assertEquals(DownloadManager.STATUS_SUCCESSFUL, cursor.getInt( cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))); assertEquals(MINIMUM_DOWNLOAD_BYTES, cursor.getInt( cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES))); assertFalse(cursor.moveToNext()); } finally { if (cursor != null) { cursor.close(); } } assertRemoveDownload(id, 0); } finally { mContext.unregisterReceiver(receiver); } }函数一开始调用DownloadManager的openDownloadFile:
public ParcelFileDescriptor openDownloadedFile(long id) throws FileNotFoundException { return mResolver.openFileDescriptor(getDownloadUri(id), "r"); }最终调用的是DownloadProvider的openFile:
@Override public ParcelFileDescriptor openFile(final Uri uri, String mode) throws FileNotFoundException { ......
} else { try { // When finished writing, update size and timestamp return ParcelFileDescriptor.open(file, pfdMode, mHandler, new OnCloseListener() { @Override public void onClose(IOException e) { final ContentValues values = new ContentValues(); values.put(Downloads.Impl.COLUMN_TOTAL_BYTES, file.length()); values.put(Downloads.Impl.COLUMN_LAST_MODIFICATION, System.currentTimeMillis()); update(uri, values, null, null); if (shouldScan) { final Intent intent = new Intent( Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); intent.setData(Uri.fromFile(file)); getContext().sendBroadcast(intent); } } }); } catch (IOException e) { throw new FileNotFoundException("Failed to open for writing: " + e); } } ...... }这个方法返回ParcelFileDescriptor对象同时为其设置了一个OnCloseListener。
当下载完成之后会关闭这个ParcelFileDescriptor会调用这个OnCloseListener。然后后者会将ParcelFileDescriptor对应的文件大小信息更新到数据库中。
testMinimumDownload接着回去调用DownloadManager的enqueue,最终会导致DownloadProvider启动一个DownloadThread去下载对应的文件。
public class DownloadThread implements Runnable { ...... @Override public void run() { ...... try { ...... executeDownload(); ...... } catch(...) { ...... } finally { logDebug("Finished with status " + Downloads.Impl.statusToString(mInfoDelta.mStatus)); mNotifier.notifyDownloadSpeed(mId, 0); finalizeDestination(); mInfoDelta.writeToDatabase(); if (Downloads.Impl.isStatusCompleted(mInfoDelta.mStatus)) { mInfo.sendIntentIfRequested(); } TrafficStats.clearThreadStatsTag(); TrafficStats.clearThreadStatsUid(); netPolicy.unregisterListener(mPolicyListener); if (wakeLock != null) { wakeLock.release(); wakeLock = null; } } ..... } ...... }
这里下载完成后会通知DownloadProvider下载完成,进而导致前面的ParcelFileDescriptor对象被close导致OnCloseListener执行。
同时DownloadThread继续执行finalizeDestination方法:
private void finalizeDestination() { ...... if (Downloads.Impl.isStatusError(mInfoDelta.mStatus)) { ...... } else if (Downloads.Impl.isStatusSuccess(mInfoDelta.mStatus)) { // When success, open access if local file if (mInfoDelta.mFileName != null) { try { // TODO: remove this once PackageInstaller works with content:// Os.chmod(mInfoDelta.mFileName, 0644); } catch (ErrnoException ignored) { } if (mInfo.mDestination != Downloads.Impl.DESTINATION_FILE_URI) { try { // Move into final resting place, if needed final File before = new File(mInfoDelta.mFileName); final File beforeDir = Helpers.getRunningDestinationDirectory( mContext, mInfo.mDestination); final File afterDir = Helpers.getSuccessDestinationDirectory( mContext, mInfo.mDestination); if (!beforeDir.equals(afterDir) && before.getParentFile().equals(beforeDir)) { final File after = new File(afterDir, before.getName()); if (before.renameTo(after)) { mInfoDelta.mFileName = after.getAbsolutePath(); } } } catch (IOException ignored) { } } } } ...... }
这里会重命名下载的文件。如果这个操作比OnCloseListener先被执行就导致,onCloseListener将数据库的下载文件大小信息跟新为0.
从而导致testMinimumDownload后续查询下载文件大小做assert操作失败。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories