英文:
Android programatically stored image has invalid format on PC
问题
我正在尝试拍照并按照Android文档保存照片。
主要区别在于我的代码扩展了Fragment
,而不是Activity
。而且,我将照片存储在私有的应用程序文件夹中,而不是公共的外部存储。
我的代码:
private void dispatchTakePictureIntent() {
PackageManager packageManager = getActivity().getPackageManager();
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// 确保有相机应用可以处理该意图
if (takePictureIntent.resolveActivity(packageManager) != null) {
// 创建照片应该存储的文件
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
Log.d(TAG, "创建文件时出现错误:" + ex.toString());
}
// 只有在成功创建文件时才继续
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(getActivity(),
"com.eric.nativetoolkit.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
private File createImageFile() throws IOException {
// 创建图像文件名
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = getActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* 前缀 */
".jpeg", /* 后缀 */
storageDir /* 目录 */
);
// 为使用ACTION_VIEW意图保存文件路径
currentPhotoPath = image.getAbsolutePath();
return image;
}
由于权限问题,每次尝试将图片保存在外部存储上时,Android Studio的Logcat都会显示“创建文件时出现错误”。我在AndroidManifest.xml中具有以下权限,并且还有一个请求权限的方法,但是都不起作用。
AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.eric.nativetoolkit">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
<application
android:allowBackup="true"
android:supportsRtl="true">
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.eric.nativetoolkit.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
</manifest>
file_paths.xml:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path name="my_images" path="." />
</paths>
但是主要问题是,即使将图片正确存储在包名/files/Pictures目录下,当我尝试通过将设备连接到计算机并浏览文件夹来查看图像时,会显示“无法打开文件”的消息:
我无法理解的是,为什么我可以在设备上正确查看图像。我尝试过更改格式(JPG、JPEG、PNG...),但没有任何区别。
英文:
I'm trying to take a picture and save it following Android Documentation.
The main difference is that my code is extending Fragment
, not Activity
. And the fact that I'm storing pictures on the private app folder instead of the public external storage.
My Code:
private void dispatchTakePictureIntent() {
PackageManager packageManager = getActivity().getPackageManager();
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(packageManager) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
Log.d(TAG, "Error occurred while creating the File:"+ex.toString());
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(getActivity(),
"com.eric.nativetoolkit.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
private File createImageFile() throws IOException
{
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = getActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpeg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
currentPhotoPath = image.getAbsolutePath();
return image;
}
This is basically cause every time I try to save pictures on the external Storage, AndroidStudio logcat shows the error "Error occurred while creating the File" due to permisions, I've the following permisions in my AndroidManifest.xml, and I also have a method to request it, but nothing works.
AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.eric.nativetoolkit">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
<application
android:allowBackup="true"
android:supportsRtl="true">
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.eric.nativetoolkit.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
</manifest>
file_paths.xml:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path name="my_images" path="." />
</paths>
But the main problem is that even correctly storing pictures inside my package/files/Pictures directory, when I try to see the image plugging my device onto the computer and navigating to the folder, it shows the message (in spanish) "Can't open file":
What I can not understand is why in my device I can correctly visualize the image. I've tried changing format (JPG, JPEG, PNG...) but no diference.
答案1
得分: 2
> 检查 FLAG_GRANT 是否起作用。但为什么我只需要在外部使用那个标志?这与我无法在桌面上看到图片的事实有什么关系?
您正在通过 ACTION_IMAGE_CAPTURE
启动第三方相机应用。它没有权利写入由您的 FileProvider
提供的 Uri
指定的位置。添加 FLAG_GRANT_WRITE_URI_PERMISSION
告诉 Android 您的应用希望将写访问权限授予相机应用。
如果没有该权限,相机应用将以某种错误失败。您仍将拥有一个文件,因为您在尝试 ACTION_IMAGE_CAPTURE
之前使用 File.createTempFile()
创建了一个不必要的空文件。如果您通过桌面文件管理器查看文件大小,您应该会看到它是 0 字节。0 字节的文件不是有效的图像,这就是为什么桌面无法显示它。
英文:
> Checking if that FLAG_GRANT works. But why I need that flag only for external? And where is the relation with the fact that I can not visualize my pictures on Desktop?
You are launching a third-party camera app via ACTION_IMAGE_CAPTURE
. It has no rights to write to the location specified by your FileProvider
-supplied Uri
. Adding FLAG_GRANT_WRITE_URI_PERMISSION
tells Android that your app wishes to give write access to that location to the camera app.
Without that permission, the camera app will fail with some sort of error. You will still have a file, since you are using File.createTempFile()
to create an unnecessary empty file before you try ACTION_IMAGE_CAPTURE
. If you look at the file size via your desktop file manager, you should see that it is 0 bytes. A 0-byte file is not a valid image, which is why the desktop cannot display it.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论