【发布时间】:2014-04-17 15:13:28
【问题描述】:
我是否应该使用 MediaScannerConnection.scanFile 方法以外的方法来刷新图库?
保存一个新的 jpg 后,我运行媒体扫描仪来刷新图库应用,就像这样
MediaScannerConnection.scanFile(this,
new String[] { fullname }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.d("ExternalStorage", "@@@@ Scanned " + path + ":");
Log.d("ExternalStorage", "@@@@ -> uri=" + uri);
}
});
日志的输出显示如下正确的输出
@@@@ 扫描/data/data/com.mypackage/files/skit_106_01.jpg:
@@@@ -> uri=content://media/external/images/media/95
图库应用显示没有可用的媒体
这段代码已经完美运行了一段时间。只有当我针对 4.4.2 版本创建了一个 Android avd 以进行进一步测试时,问题才浮出水面。
我的代码似乎是根据Androids文档刷新图库应用程序的推荐方式,所以这个问题可能与我保存文件的方式有关,代码如下。
更新
代码检查外部存储是否可用,并将写入外部存储,如果外部存储不可用,则将文件写入内部存储。
private void doSave(String fname, boolean doShare) {
fname = "skit_"+mCurrentSkitId +
"_"+mSkitManager.getCurrentFrameCount(
mCurrentSkitId)+1;
Log.d(TAG, "@@@@ doSave fName = " + fname + " Current skit id = " + mCurrentSkitId);
CharSequence text = getResources().getString(R.string.saved_as)
+ " " + fname;
try {
Bitmap b = mMainView.getSaveBitmap();
if (b == null) {
text = getResources().getString(R.string.save_fail_1);
;
Toast.makeText(this, text, Toast.LENGTH_LONG).show();
return;
}
fname = FileUtils.replaceInvalidFileNameChars(fname);
String value = fname;
File folder = FileUtils.getWritableFolder(this);
/*
* String folder =
* Environment.getExternalStorageDirectory().toString() +
* "/Pictures"; try { folder =
* Environment.getExternalStoragePublicDirectory
* (Environment.DIRECTORY_PICTURES).toString(); } catch
* (NoSuchFieldError e) {
*
* }
*/
String ext = ".jpg";
if (mPrefs.getString("format", "JPG").equals("PNG"))
ext = ".png";
String fullname = folder.getAbsolutePath() + File.separator + value
+ ext;
Map<String, String> hm = new HashMap<String, String>();
hm.put("filename", fullname);
FileOutputStream fos;
if (folder == getFilesDir())
fos = openFileOutput(value + ext, Context.MODE_WORLD_WRITEABLE);
else {
File f2 = new File(fullname);
fos = new FileOutputStream(f2);
}
b.compress(CompressFormat.JPEG, 95, fos);
fos.close();
String[] str = new String[1];
str[0] = fullname;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.FROYO) {
MediaScannerConnection.scanFile(this,
new String[] { fullname }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.d("ExternalStorage", "@@@@ Scanned " + path + ":");
Log.d("ExternalStorage", "@@@@ -> uri=" + uri);
}
});
}
text = text + value + ext + " "
+ getResources().getString(R.string.saved_end);
;
mLastSaveName = value;
setDetailTitle();
mSkitManager.createFrame(mCurrentSkitId, fullname);
} catch (Exception e) {
Map<String, String> hm = new HashMap<String, String>();
hm.put("text", e.toString());
e.printStackTrace();
text = getResources().getString(R.string.save_fail_2)
+ e.toString();
} catch (Error e) {
Map<String, String> hm = new HashMap<String, String>();
hm.put("text", e.toString());
e.printStackTrace();
text = getResources().getString(R.string.save_fail_2)
+ e.toString();
}
Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
}
检查外部存储可用性的代码如下所示
public static File getWritableFolder(Context context) {
File folder = context.getFilesDir();
if (externalStorageAvailable()) {
try {
folder = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
if (!folder.exists() || !folder.canWrite()) {
folder = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
}
if (!folder.exists() || !folder.canWrite()) {
folder = Environment.getExternalStorageDirectory();
}
} catch (Exception e) {
folder = Environment.getExternalStorageDirectory();
} catch (Error e) {
folder = Environment.getExternalStorageDirectory();
}
if (!folder.exists() || !folder.canWrite()) {
folder = context.getFilesDir();
}
}
return folder;
}
private static boolean externalStorageAvailable() {
boolean mExternalStorageAvailable;
boolean mExternalStorageWriteable;
String state = Environment.getExternalStorageState();
if (state.equals(Environment.MEDIA_MOUNTED)) {
// We can read and write the media
mExternalStorageAvailable = mExternalStorageWriteable = true;
} else if (state.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) {
// We can only read the media
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
} else {
// Something else is wrong. It may be one of many other states, but
// all we need
// to know is we can neither read nor write
mExternalStorageAvailable = mExternalStorageWriteable = false;
}
return mExternalStorageAvailable && mExternalStorageWriteable;
}
如果有人能够在上述任何一项中找出可能有助于解决此问题的漏洞,那就太好了。
【问题讨论】:
-
“我应该使用 MediaScannerConnection.scanFile 方法以外的方法来刷新图库吗?” -- 是的,但仅适用于外部存储上的文件。您正在尝试扫描内部存储上的文件。 “只有当我针对 4.4.2 版本创建 Android avd 以进行进一步测试时,问题才浮出水面。” -- 你一直有安全问题,使用现在已弃用的
MODE_WORLD_WRITEABLE。您可能会查看Uri是否确实有效,以确定问题出在哪里。 -
@CommonsWare 感谢您的意见。看来 uri 不起作用。如有任何建议,我将不胜感激。
-
@CommonsWare 关于 MODE_WORLD_WRITEABLE 的观点。你是在暗示文档是错误的developer.android.com/guide/topics/data/data-storage.html 我对我应该做什么感到困惑
-
“如果有任何建议,我将不胜感激”——尝试将您的图像存储在外部存储设备上。 “您是在暗示文档是错误的吗?” - 如果您希望文件是世界可写的,请将文件放在外部存储上。您可能还希望阅读the documentation for
MODE_WORLD_WRITEABLE,其中显示自 Android 4.2 以来已弃用此功能,不推荐使用。 -
@CommonsWare 我首先尝试存储在外部存储上,如果不可用,我存储在内部存储上。所以我需要一个适用于两者的解决方案。
标签: android android-mediascanner