迁移本人cnblog文章:
一、问题起源
最近有同事反馈试用的机器出现问题,图库的照片全部消失,新下载的第三方应用图片,也无法显示。针对该问题,当时以为是媒体库scan过程和数据库存在异常,查了半天无任何结论。内部讨论后,初步怀疑是nomedia导致,查看外置存储根目录的隐藏文件,果然有.nomdia生成,但这个是谁生成的呢?无从知晓,随后让同事提供试用过程,一步步盘查,结果定位到国内某度应用导致。对比国内其他机器,无此问题,应该是规避了。那么如何规避该问题,删除此文件或者排除此路径的隐藏机制?
二、nomedia实现方式
既然规避,自然需要弄清楚系统如何实现nomedia隐藏的机制。那么nomedia到底如何定义的呢?
frameworks/base/core/java/android/provider/MediaStore.java
/**
* Name of the file signaling the media scanner to ignore media in the containing directory
* and its subdirectories. Developers should use this to avoid application graphics showing
* up in the Gallery and likewise prevent application sounds and music from showing up in
* the Music app.
*/
public static final String MEDIA_IGNORE_FILENAME = ".nomedia";
如上定义,顾名思义,是隐藏此文件当前目录以及子目录的媒体文件。那么系统是如何利用.nomedia实现该机制的呢?
根据代码搜索到的路径分析,目前有两个地方进行了隐藏处理,MediaProvider和MediaScanner,下面先看MediaProvider:
1、MediaProvider
packages/providers/MediaProvider/src/com/android/providers/media/MediaProvider.java
/*
* Sets the media type of all files below the newly added .nomedia file or
* hidden folder to 0, so the entries no longer appear in e.g. the audio and
* images views.
*
* @param path The path to the new .nomedia file or hidden directory
*/
private void processNewNoMediaPath(final DatabaseHelper helper, final SQLiteDatabase db,
final String path) {
final File nomedia = new File(path);
if (nomedia.exists()) {
hidePath(helper, db, path);
} else {
// File doesn't exist. Try again in a little while.
// XXX there's probably a better way of doing this
new Thread(new Runnable() {
@Override
public void run() {
SystemClock.sleep(2000);
if (nomedia.exists()) {
hidePath(helper, db, path);
} else {
Log.w(TAG, "does not exist: " + path, new Exception());
}
}}).start();
}
}