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

的修改

时间: 2024-08-08 05:14:21

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

如何在PDF阅读器中新建文档

对于PDF,阅读.查看或许很熟悉,新建一个PDF文档,不少小伙伴还很陌生.所以今天,小编就给大家介绍几种创建PDF文档的办法. 一.将其他文件变为PDF 这个办法其实就是我们通常说的文档转换,利用福昕PDF阅读器可以将office 文档转换为PDF. 步骤:点击"主页"-"创建-将文件转换为PDF",或者直接点击快捷键"Ctrl+N"即可.这时候,在弹出的窗口选择相关文档,你会发现,常见office文档都可以通过这种办法变成PDF,还包括图像文件

去掉ubuntu的文件管理器中“位置”栏里的无用标签

每次看到那些无用的文件夹放在那总是感觉很不爽... 首先更改 /home/slyfc/.config/user-dirs.dirs  里的东西,把你不想要的删掉,注意不要删桌面,其余的随意 重启后发现文件复原,原因是xdg-user-dirs-update开机重写了这个文件. 那么关掉这个东西就行了,在/etc/xdg/user-dirs.conf中修改为enabled=False 更改好配置文件后,重启,会发现那些文件变成了书签,就可以右键删除了

文件管理器中不支持的wma歌曲也显示可以播放的音乐图标

关闭MTK_WMV_PLAYBACK_SUPPORT=no文件管理器中不支持的wma歌曲也显示可以播放的音乐图标

linux文件管理必会知识

linux文件管理必会知识 一.文件查看类命令         ① less 选项  参数(文件名)                分屏显示文件内容(查看至文件的结尾不会退出,按q退出)            快捷键                ctrl+d 向下翻半屏                ctrl+u 向上翻半屏                回车键 向下翻一行                K键 向上翻一行                 空格键 向下翻一整屏          

android求助:关于播放器中的“播放/暂停”键: 用ImageButton来设置点击效果时的问题

============问题描述============ 大家好,我最近遇到个问题: 大家都知道,播放器中的播放/暂停键是这样的逻辑:当用户点击了这个键,如果当前显示的是"播放"图案,会变为"暂停"图案:反之,如果当前是"暂停"图案,会变为"播放"图案 , 如此反复... 现在我正在实现这个效果,我是这样做的: 在以上的基本效果的基础上,我还添加了点击过程中的效果,就是当点下还木有松开时,会有一个点击效果(比如给当前图片加个光

Android 手动按power键上锁,没有锁屏提示音,无法恢复【单机必现】

测试步骤 [测试版本]T0606 [模块版本] NAVI锁屏:5.0.0.ck [测试步骤] 1.手动按power键上锁, [测试结果] 没有锁屏提示音,无法恢复[单机必现] [预期结果] 有提示音 [发生次数] 单机必现 从log可以找到 4321 05-25 16:58:23.779 886 32501 W SoundPool: sample 1 not READY 7641 05-25 16:58:33.879 886 32563 W SoundPool: sample 1 not REA

windowsf进程管理器中进程解释

(1)[system Idle Process] 进程文件: [system process] or [system process] 进程名称: Windows内存处理系统进程 描 述: Windows页面内存管理进程,拥有0级优先. 介 绍:该进程作为单线程运行在每个处理器上,并在系统不处理其他线程的时候分派处理器的时间.它的cpu占用率越大表示可供分配的CPU资源越多,数字越小则表示CPU资源紧张. (2)[alg.exe] 进程文件: alg or alg.exe 进程名称: 应用层网关

Android多媒体框架对音乐播放器的支持

下面介绍一下Andriod多媒体框架对开发者提供的支持有哪些. 1. MediaScannerReceiver 这个广播接收者在接收到ACTION_BOOT_COMPLETED.ACTION_MEDIA_MOUNTED或 ACTION_MEDIA_SCANNER_SCAN_FILE 广播时对SD卡中的图片.音乐和视频文件进行了扫描,因为扫描不能影响用户使用,这里启动了一个服务MediaScannerService,扫描的文件类型如下: /* Audio */ addFileType("MP3&q

Android MediaProvider数据库模式

摘要: Android MediaProvider 使用 SQLite 数据库存储图片.视频.音频等多媒体文件的信息,供视频播放器.音乐播放器.图库使用.本文详细分析了 Android MediaProvider 多媒体数据库(以 SDK 2.3.3 为例)的模式(schema),并简要叙述与系统媒体扫描服务 MediaScanner 的交互. 1. 如何提取数据库 以 root 权限进入 adb shell,使用 sqlite3 打开位于手机上/data/data/com.android.pr