"java.io.FileNotFoundException: Permission denied" 在 Android 内部缓存目录中
"java.io.FileNotFoundException: Permission denied" in Android Internal Cache Dir
我正在尝试拍照并将其保存到应用程序的内部缓存中,因为它会在上传后立即被删除。我正在使用以下代码创建文件:
public static File createInternalCacheImageFile(Context context, String imageFileName) throws IOException {
return File.createTempFile(
imageFileName,
context.getString(R.string.image_extension),
context.getCacheDir()
);
}
检查具有 root 权限的文件管理器显示文件创建正常。然后我使用以下代码启动相机意图,这通常会将图像保存到我创建的文件中:
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(imageFile));
activity.startActivityForResult(takePictureIntent, REQUEST_CODE_IMAGE_CAPTURE);
显示相机activity,接受图片后,activity的结果为0。查看logcat
时显示如下:
07-21 13:19:51.093 12889-12889/? E/CAM_StateSavePic﹕ exception while saving result to URI: Optional.of(file:///data/data/org.serengetitracker.androidapp/cache/image_random_205854910-2018234447.jpg)
java.io.FileNotFoundException: Permission denied
at android.os.Parcel.openFileDescriptor(Native Method)
at android.os.ParcelFileDescriptor.openInternal(ParcelFileDescriptor.java:253)
at android.os.ParcelFileDescriptor.open(ParcelFileDescriptor.java:199)
at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:916)
at android.content.ContentResolver.openOutputStream(ContentResolver.java:686)
at android.content.ContentResolver.openOutputStream(ContentResolver.java:662)
at com.android.camera.captureintent.state.StateSavingPicture.onEnter(StateSavingPicture.java:84)
at com.android.camera.captureintent.stateful.StateMachineImpl.jumpToState(StateMachineImpl.java:62)
at com.android.camera.captureintent.stateful.StateMachineImpl.processEvent(StateMachineImpl.java:110)
at com.android.camera.captureintent.state.StateOpeningCamera.onClick(StateOpeningCamera.java:307)
at android.view.View.performClick(View.java:4780)
at android.view.View$PerformClick.run(View.java:19866)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
为什么不允许我将图像写入应用程序的内部缓存目录?
注意:我在我的应用程序中确实拥有 android.permission.WRITE_EXTERNAL_STORAGE
权限,尽管这无关紧要,因为我不处理外部存储。
来自以下 link http://developer.android.com/reference/android/content/Context.html#getCacheDir() getCacheDir()
Returns the absolute path to the application specific cache directory on the filesystem
您的应用程序可以完全访问此路径,但在这里您通过 intent 将缓存目录中的 URI 传递给相机应用程序,它正在尝试访问您的应用程序的 cacheDir 以存储它捕获的图像,但它无法访问它。
一种解决方案是使用外部目录中的文件夹。
相机 activity 在另一个应用程序中运行,该应用程序无权访问您应用程序的内部缓存目录。您必须使用外部目录或让相机应用程序自己选择目录 - 然后查询该路径(另一个主题)以便能够将其复制到您的缓存目录。
没有 CAMERA
和 WRITE_EXTERNAL_STORAGE
权限, 是 可能的。
您可以在应用的缓存目录中创建一个临时文件,并授予其他应用访问权限。这使得文件可由相机应用程序写入:
File tempFile = File.createTempFile("photo", ".jpg", context.getCacheDir());
tempFile.setWritable(true, false);
现在您只需将此文件作为相机意图的输出文件传递:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTempFile)); // pass temp file
startActivityForResult(intent, REQUEST_CODE_CAMERA);
注意:文件 Uri 不会在 Activity 结果中传递给您,您必须保留对 tempFile 的引用并从那里检索它。
我正在尝试拍照并将其保存到应用程序的内部缓存中,因为它会在上传后立即被删除。我正在使用以下代码创建文件:
public static File createInternalCacheImageFile(Context context, String imageFileName) throws IOException {
return File.createTempFile(
imageFileName,
context.getString(R.string.image_extension),
context.getCacheDir()
);
}
检查具有 root 权限的文件管理器显示文件创建正常。然后我使用以下代码启动相机意图,这通常会将图像保存到我创建的文件中:
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(imageFile));
activity.startActivityForResult(takePictureIntent, REQUEST_CODE_IMAGE_CAPTURE);
显示相机activity,接受图片后,activity的结果为0。查看logcat
时显示如下:
07-21 13:19:51.093 12889-12889/? E/CAM_StateSavePic﹕ exception while saving result to URI: Optional.of(file:///data/data/org.serengetitracker.androidapp/cache/image_random_205854910-2018234447.jpg)
java.io.FileNotFoundException: Permission denied
at android.os.Parcel.openFileDescriptor(Native Method)
at android.os.ParcelFileDescriptor.openInternal(ParcelFileDescriptor.java:253)
at android.os.ParcelFileDescriptor.open(ParcelFileDescriptor.java:199)
at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:916)
at android.content.ContentResolver.openOutputStream(ContentResolver.java:686)
at android.content.ContentResolver.openOutputStream(ContentResolver.java:662)
at com.android.camera.captureintent.state.StateSavingPicture.onEnter(StateSavingPicture.java:84)
at com.android.camera.captureintent.stateful.StateMachineImpl.jumpToState(StateMachineImpl.java:62)
at com.android.camera.captureintent.stateful.StateMachineImpl.processEvent(StateMachineImpl.java:110)
at com.android.camera.captureintent.state.StateOpeningCamera.onClick(StateOpeningCamera.java:307)
at android.view.View.performClick(View.java:4780)
at android.view.View$PerformClick.run(View.java:19866)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
为什么不允许我将图像写入应用程序的内部缓存目录?
注意:我在我的应用程序中确实拥有 android.permission.WRITE_EXTERNAL_STORAGE
权限,尽管这无关紧要,因为我不处理外部存储。
来自以下 link http://developer.android.com/reference/android/content/Context.html#getCacheDir() getCacheDir()
Returns the absolute path to the application specific cache directory on the filesystem
您的应用程序可以完全访问此路径,但在这里您通过 intent 将缓存目录中的 URI 传递给相机应用程序,它正在尝试访问您的应用程序的 cacheDir 以存储它捕获的图像,但它无法访问它。
一种解决方案是使用外部目录中的文件夹。
相机 activity 在另一个应用程序中运行,该应用程序无权访问您应用程序的内部缓存目录。您必须使用外部目录或让相机应用程序自己选择目录 - 然后查询该路径(另一个主题)以便能够将其复制到您的缓存目录。
没有 CAMERA
和 WRITE_EXTERNAL_STORAGE
权限, 是 可能的。
您可以在应用的缓存目录中创建一个临时文件,并授予其他应用访问权限。这使得文件可由相机应用程序写入:
File tempFile = File.createTempFile("photo", ".jpg", context.getCacheDir());
tempFile.setWritable(true, false);
现在您只需将此文件作为相机意图的输出文件传递:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTempFile)); // pass temp file
startActivityForResult(intent, REQUEST_CODE_CAMERA);
注意:文件 Uri 不会在 Activity 结果中传递给您,您必须保留对 tempFile 的引用并从那里检索它。