调用MediaScannerConnection扫描6000+文件触发RemoteServiceException如何解决
批量媒体扫描RemoteServiceException异常原因及解决方案
异常触发原因
- 核心诱因是单次传入
MediaScannerConnection的文件路径数量过大:安卓系统的Binder跨进程通信缓冲区默认仅为1MB左右,你一次性传入6000+路径,扫描完成后系统返回的大量回调数据会直接撑爆缓冲区,最终触发广播投递失败的异常。 - 次要诱因:如果扫描回调内存在耗时操作,会导致主线程消息队列堵塞,同样可能引发该类异常。
解决方案
- 分片批量扫描
不要一次性传入全量扫描路径,将扫描列表拆分为单个大小100~200的小分片,等当前分片全部扫描完成后再提交下一个分片,参考实现代码如下:
// 单次扫描的分片大小,可根据设备表现调整 private static final int SCAN_BATCH_SIZE = 150; private List<String> mTotalScanList = new ArrayList<>(); private int mCurrentBatchPos = 0; // 入口:启动全量扫描 private void startMediaScan(List<String> scanList) { mTotalScanList = scanList; mCurrentBatchPos = 0; scanNextBatch(); } // 扫描下一个分片 private void scanNextBatch() { int startIndex = mCurrentBatchPos * SCAN_BATCH_SIZE; // 所有分片扫描完成 if (startIndex >= mTotalScanList.size()) { Log.d("MediaScanUtils", "All media files scan completed"); return; } int endIndex = Math.min(startIndex + SCAN_BATCH_SIZE, mTotalScanList.size()); List<String> currentBatch = mTotalScanList.subList(startIndex, endIndex); String[] scanPaths = new String[currentBatch.size()]; String[] mimeTypes = new String[currentBatch.size()]; AtomicInteger callbackCounter = new AtomicInteger(0); for (int i = 0; i < currentBatch.size(); i++) { String path = currentBatch.get(i); scanPaths[i] = path; File file = new File(path); mimeTypes[i] = file.isDirectory() ? "*/*" : FileSystem.getMimeType(path); } MediaScannerConnection.scanFile(MyApplication.getContext(), scanPaths, mimeTypes, (path, uri) -> { Log.d("MediaScanUtils", "Scanned Path: " + path + " Uri: " + uri); // 当前分片全部回调完成,启动下一个分片扫描 if (callbackCounter.incrementAndGet() == currentBatch.size()) { mCurrentBatchPos++; scanNextBatch(); } }); }
- 简化回调逻辑
扫描回调内仅保留日志、计数这类轻量操作,不要执行IO读写、数据库写入、复杂计算等耗时逻辑,避免主线程消息队列堵塞。
内容的提问来源于stack exchange,提问作者MuseYkh
相关产品推荐
相关产品推荐

