问题1:将二维码图片从手机或SD卡上删除后,在媒体库中仍然可以看到被删除图片的预览缩略图。
参考:Android: remove an image from sd card
http://stackoverflow.com/questions/6707197/android-remove-an-image-from-sd-card
问题2:
(new File(filePath)).deleteOnExit();
我一直以为deleteOnExit()是在文件存在的时候删除。大错特错,源于我对一直把这个方法当作deleteonExist(),仅仅差一个字母。终于在今天被我发现,以后不会再犯这个低级错误了吧。
正确删除文件应该这么实现:
File file = new File(filePath); if(file.exists()) file.delete();
代码片段:保存图片到文件系统中
private String getSaveDirectory() { if(!sdCardIsExist()) { return context.getFilesDir().getPath() + "/" + "user"; } else { return ImageManager.USER_INFO_DIRECTORY; } } private void deleteMyFile(String directory, String filename) { Logger.v(TAG, "invoke deleteMyFile"); File file = new File(directory, filename); if(file.exists()) { Logger.v(TAG, "File is exist. Begin to delete it. Its path is >> " + file.getPath()); if(file.delete()) { Logger.v(TAG, "Delete success."); } else { Logger.v(TAG, "Delete fail."); } } else { Logger.v(TAG, "File is not exist."); } } private void saveBitmapToFile(Bitmap source, String directory, String filename) { Logger.v(TAG, "invoke saveBitmapToFile"); OutputStream outputStream = null; try { File dir = new File(directory); if (!dir.exists()) dir.mkdirs(); File file = new File(directory, filename); Logger.v(TAG, "Begin to save bitmap to file which its path is >> " + file.getPath()); outputStream = new FileOutputStream(file); if (source != null) { source.compress(CompressFormat.JPEG, 100, outputStream); } } catch (FileNotFoundException ex) { Log.w(TAG, ex); } finally { StreamUtil.Release(outputStream); } } private void saveZxingImage() { Logger.v(TAG, "invoke saveZxingImage"); if(source == null) return; String filename = "user("+user.getUsername()+").png"; String directory = getSaveDirectory(); Logger.v(TAG, "sdCardIsExist >> " + sdCardIsExist()); // 删除文件 deleteMyFile(directory, filename); // 保存文件 saveBitmapToFile(source, directory, filename); // 通知媒体库刷新 sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory()))); UIUtils.showToast(context, "保存二维码图片成功"); }
其中常量USER_INFO_DIRECTORY为:
public static final String USER_INFO_DIRECTORY = Environment.getExternalStorageDirectory().toString() + "/ivideo/user";
判断SD卡是否存在代码实现
private boolean sdCardIsExist() { return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); }
代码片段:从媒体库中获取并解析二维码图片
if (requestCode == SELECT_ZXING_PICTURE) { Logger.v(TAG, "return back from media store."); if (resultCode == RESULT_OK) { try { Uri dataUri = data.getData(); Logger.v(TAG, "open input stream from data which its URI is >> " + dataUri.toString()); InputStream istream = getContentResolver().openInputStream(dataUri); if (zxingBitmap != null) { Logger.v(TAG, "zxing bitmap is not null, begin to recycle it."); zxingBitmap.recycle(); } else { Logger.v(TAG, "zxing bitmap is null."); } Logger.v(TAG, "decode stream from input stream."); zxingBitmap = BitmapFactory.decodeStream(istream); Logger.v(TAG, "get user infomation from zxing bitmap."); String zxingInfo = getUserFromBitmap(zxingBitmap); Logger.v(TAG, "login with ukey >> " + zxingInfo); loginFromZxingInfo(zxingInfo); } catch (FileNotFoundException e) { Logger.e(TAG, "caught exception about file not found."); Logger.e(TAG, e); showToast("文件未找到"); } catch (OutOfMemoryError err) { Logger.e(TAG, "caught error about out of memory."); Logger.e(TAG, err); showToast("解析出错"); } catch (NotFoundException e) { Logger.e(TAG, "caught exception about zxing not found."); Logger.e(TAG, e); } catch (ChecksumException e) { Logger.e(TAG, "caught exception about zxing check sum."); Logger.e(TAG, e); } catch (FormatException e) { Logger.e(TAG, "caught exception about zxing format."); Logger.e(TAG, e); } if (zxingBitmap != null) { Logger.v(TAG, "zxing bitmap is not null, begin to recycle it."); zxingBitmap.recycle(); zxingBitmap = null; } } return; }
问题:在手机没有关机的情况下,将SD卡从手机上拿走,然后也不重启手机。程序中判断SD卡是否存在,结果会显示SD卡还存在。于是导致:保存二维码图片不成功。此时重启手机,再打开程序,程序中片段SD卡是否存在,结果就会显示SD卡不存在。
问题:当SD卡不存在时,程序将二维码图片保存到手机上,再打开媒体库,结果:媒体库无法显示出手机上的图片。可能原因:保存二维码之后,仅仅通知重新扫描SD卡,没有去扫描手机。
问题:当SD卡不存在时,将二维码图片保存到手机内存卡上目录为data/data/xxx/files/user/xxx.png,然后调用chmod命令修改文件的权限,经过验证修改权限的操作已经执行成功,在File Explorer中可以看到此文件的权限是-rwxrwxrwx即777权限。但是,在手机的媒体库应用中无法预览到此png文件。
问题:当SD卡在开机状态下卸载或者挂载,并且手机没有重启,媒体库不做任何监听。所以会出现以下情况:刚开始手机没有SD卡,在开机状态下挂载上SD卡后,打开媒体库应用,媒体库应用仍然显示SD卡不存在或者SD卡不可用。
问题:检测SD卡是否可用最理想办法。使用Environment.getExternalStorageState()和Environment.getExternalStorageDirectory().canWrite()等方法检测不出实际效果。当SD卡拔掉后,canWrite()仍然返回true,且getExternalStorageState()返回值仍然是Environment.MEDIA_MOUNTED。最理想的办法是在SD上创建一个文件,如果文件能够创建成功,那就表示SD卡可用,反之不可用。
代码片段:检测SD卡是否可用
private boolean sdCardIsAvailable() { String fileName = new Date().getTime() + ".test"; String filePath = Environment.getExternalStorageDirectory() + "/" + fileName; File file = new File(filePath); try { if(file.createNewFile()) { Logger.v(TAG, "create new file success. filepath >> " + filePath); } else { Logger.v(TAG, "create new file fail. filepath >> " + filePath); return false; } if(file.exists()) { if(file.delete()) { Logger.v(TAG, "delete file success. filepath >> " + filePath); } else { Logger.v(TAG, "delete file fail. filepath >> " + filePath); return false; } } } catch (IOException e) { Logger.v(TAG, "caught " + e.getClass().getName() + " >> " + e.getMessage()); return false; } return true; }
代码片段:在程序中调用上述方法来检测SD卡是否可用
if(!sdCardIsAvailable()) { UIUtils.showToast(context, "SD卡不可用"); Logger.v(TAG, "sd card is unavailable."); return; } else { Logger.v(TAG, "sd card is available."); }
调试日志:当SD卡不可用时打印出sd card is unavaliable.
11-15 18:21:32.019: V/SaveZxingActivity(15205): caught java.io.IOException >> I/O error 11-15 18:21:32.029: V/SaveZxingActivity(15205): sd card is unavailable.
参考资料:
1. android中对SD卡挂载和卸载的监听
http://blog.csdn.net/guoying_/article/details/6618277
2.android 监听SDCard安装和卸载的代码片段(测试通过)
http://www.cnblogs.com/error404/archive/2011/09/08/2170998.html
3. android sd卡状态、路径、可用空间,内存
http://blog.csdn.net/ureygo/article/details/7064030