Android MediaProvider--文件管理:必现,文件管理器中新建几个文件夹,批量删除后,连接电脑查看仍有部分文件夹未删除

问题描述:

【测试步骤】:1、进入文件管理器中,新建几个文件夹,然后批量全选这些文件夹--删除;
2、手机连接电脑,在电脑端查看文件显示。
【测试结果】:电脑端查看仍有部分文件夹未删除。插拔USB线几次,在电脑端重新查看,仍显示。
【预期结果】:电脑端不应显示已删除的文件夹。
【复现概率】:100%(若第一次未复现,步骤1、2重新操作即可复现)
【备注】:在文件管理中点击“搜索”,也能搜索出这些文件夹。
按以下步骤更容易复现
1.添加一个本地文件夹,删除新添加的文件夹
2.再新建另一文件夹。(文件系统中文件夹已创建,且媒体库中已新增此记录,但操作1中被删除的文件夹,在媒体库中又出现了)

此问题是由于MediaProvider添加了线程池扫描引起的,Android原生的不会有这个问题,


解决办法:修改packages/providers/MediaProvider/src/com/android/providers/media/MediaScannerThreadPool.java文件的内部类: 

private class InsertFolderTask extends Task {
        private ContentResolver mContentResolver;
	// <2015.05.06> modify for  start
	private boolean isExistInFileSystem(String folderPath) {
	    return new File(folderPath).exists();
	} 
	//<2015.05.06> modify for end

        public InsertFolderTask() {
            super(PRIORITY_MAX + LESS_PRIOR, 0);
            mContentResolver = mContext.getContentResolver();
        }

        @Override
        public void run() {
            long start = System.currentTimeMillis();
            int size = mFolderMap.size();
            List<ContentValues> folderList = new ArrayList<ContentValues>(size);
            Iterator<Entry<String, FolderStructure>> iterator = mFolderMap.entrySet().iterator();
            while (iterator.hasNext()) {
                Entry<String, FolderStructure> entry = iterator.next();
                String folderPath = entry.getKey();
                FolderStructure folderStructure = entry.getValue();
		// <2015.05.06> modify for start
		/// If folder have been deleted right now, remove from map and do next check.
		if (!isExistInFileSystem(folderPath)) {
		     iterator.remove();
		     continue;
	 	}
		// <2015.05.06> modify for end

                /// Root folder path(store in each directory) have been insert while begin scanning
                if (!isExistInDatabase(folderPath)) {
                    ContentValues values = new ContentValues();
                    values.put(MediaStore.Files.FileColumns.TITLE, MediaFile.getFileTitle(folderPath));
                    values.put(MediaStore.Files.FileColumns.FORMAT, MtpConstants.FORMAT_ASSOCIATION);
                    values.put(MediaStore.Files.FileColumns.DATA, folderPath);
                    values.put(MediaStore.Files.FileColumns.DATE_MODIFIED, folderStructure.mLastModified);
                    values.put(MediaStore.Files.FileColumns.SIZE, 0);
                    values.put(MediaStore.Files.FileColumns.IS_DRM, 0);
                    folderList.add(values);

                    if (folderList.size() >= 500) {
                        sortByPath(folderList);
                        flush(MediaScannerInserter.FILE_URI, folderList);
                        folderList.clear();
                    }
                }
            }
            if (!folderList.isEmpty()) {
                sortByPath(folderList);
                flush(MediaScannerInserter.FILE_URI, folderList);
            }
            /// Insert task finish, execute single type scan task.
            executeSingleTypeScanTask();
            long end = System.currentTimeMillis();
            MtkLog.v(TAG, "Insert all folder entries finsih in " + Thread.currentThread().getName() + ": folder size = "
                    + mFolderMap.size() + ", insert num = " + folderList.size() + ", cost = " + (end - start) + "ms");
        }

        private void sortByPath(List<ContentValues> list) {
            Collections.sort(list, new Comparator<ContentValues>() {
                public int compare(ContentValues old, ContentValues latest) {
                    String oldPath = old.getAsString(MediaStore.Files.FileColumns.DATA);
                    String latestPath = latest.getAsString(MediaStore.Files.FileColumns.DATA);
                    if (latestPath != null && oldPath != null) {
                        return oldPath.compareTo(latestPath);
                    }
                    return 0;
                };
            });
        }

        private boolean isExistInDatabase(String folderPath) {
            Cursor cursor = null;
            try {
                cursor = mContentResolver.query(MediaScannerInserter.FILE_URI, null,
                                MediaStore.Files.FileColumns.DATA + "=?", new String[] {folderPath}, null, null);
                return cursor != null && cursor.moveToFirst();
            } catch (Exception e) {
                MtkLog.e(TAG, "Check isExistInDatabase with Exception for " + folderPath, e);
                return true;
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }
        }

        private void flush(Uri tableUri, List<ContentValues> list) {
            long start = System.currentTimeMillis();
            int size = list.size();
            ContentValues[] valuesArray = new ContentValues[size];
            valuesArray = list.toArray(valuesArray);
            try {
                mContentResolver.bulkInsert(tableUri, valuesArray);
            } catch (Exception e) {
                MtkLog.e(TAG, "bulkInsert with Exception for " + tableUri, e);
            }
            long end = System.currentTimeMillis();
            MtkLog.d(TAG, "flush " + tableUri + " with size " + size + " which cost " + (end - start) + "ms");
        }
    }
添加// <2015.05.06> modify for start
// <2015.05.06> modify for end

的修改

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。