我正在使用Android Studio编写Java代码。 我想编写一个软件,基于某个事件从相机中拍摄照片。所以首先要做的是找到API。Camera已经过时了,现在有Camera2和更高版本的CameraX。我尝试使用CameraX和Camera2,但是出现了无法保存任何图像的问题。我相信拍摄功能是正常的,但问题在于保存文件。我不知道发生了什么。
首先,让我们谈一下权限。是的,我已经为相机和外部存储设置了权限。
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
现在我们来看看代码本身。
我以前从未保存过照片,但我已经处理过文本文件,例如.txt和.csv文件。我已经成功地完成了这些工作。
现在我只需要点击一个简单的按钮来捕获图像,这只是一个onclicklistener。按下按钮后,将执行以下操作。
SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
File file = new File(Environment.getDataDirectory(), mDateFormat.format(new Date())+ ".jpg");
if(!file.exists())
file.mkdirs();
ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions.Builder(file).build();
imageCapture.takePicture(outputFileOptions, executor, new ImageCapture.OnImageSavedCallback () {
@Override
public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {
Toast.makeText(MainActivity.this, "TEST", Toast.LENGTH_SHORT).show();
new Handler().post(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "Image Saved successfully", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void onError(@NonNull ImageCaptureException error) {
error.printStackTrace();
// Toast.makeText(MainActivity.this, "Image save FAILED!!!!", Toast.LENGTH_SHORT).show();
}
});
当应用程序第一次启动时,它会请求权限,我同意了。但是,当我按下捕获按钮时,在Android Studio ID的运行选项卡中看到以下输出结果。
D/ImageCapture: Send image capture request [current, pending] = [0, 1]
D/CaptureSession: Issuing capture request.
W/example.camera: JNI critical lock held for 21.148ms on Thread[14,tid=10076,Runnable,Thread*=0xdc743000,peer=0x13184cf8,"Binder:10045_2"]
W/ExifInterface: Stop reading file since a wrong offset may cause an infinite loop: 0
Skip the tag entry since data format (ULONG) is unexpected for tag: GPSAltitudeRef
W/ExifInterface: Stop reading file since a wrong offset may cause an infinite loop: 0
Stop reading file since a wrong offset may cause an infinite loop: 0
W/System.err: androidx.camera.core.ImageCaptureException: Failed to write or close the file
W/System.err: at androidx.camera.core.ImageCapture$3.onError(ImageCapture.java:669)
at androidx.camera.core.ImageSaver.lambda$postError$1$ImageSaver(ImageSaver.java:263)
at androidx.camera.core.-$$Lambda$ImageSaver$eAp-cZyzsEk-LVLazzLE-ezQzwo.run(Unknown Source:8)
W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
Caused by: java.io.FileNotFoundException: /data/20200728142756.jpg: open failed: EACCES (Permission denied)
at libcore.io.IoBridge.open(IoBridge.java:496)
at java.io.FileOutputStream.<init>(FileOutputStream.java:235)
at java.io.FileOutputStream.<init>(FileOutputStream.java:186)
at androidx.camera.core.ImageSaver.run(ImageSaver.java:97)
... 3 more
W/System.err: Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
at libcore.io.Linux.open(Native Method)
at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:252)
at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7255)
at libcore.io.IoBridge.open(IoBridge.java:482)
... 6 more
W/example.camera: JNI critical lock held for 17.651ms on Thread[16,tid=10083,Runnable,Thread*=0xdc74bc00,peer=0x13184de8,"Binder:10045_4"]
我已经搜索过了,寻找了保存文件的不同方法,并且使用相机2 api并使用outputstream保存文件时,我在保存图像方面取得了一定的成功。
当我使用Camera2时,它似乎保存得很好,但我不知道它保存在哪里,我找不到它。 我指出这一点,因为它仍然似乎是一个权限被拒绝的错误,因为当我打开设备文件浏览器时,它不让我查看/storage/emulator/,它只会显示。
ls: /storage/emulated/: Permission denied.
我找到的所有示例都假定可以无问题地访问模拟文件系统。
有人能否解释一下为什么我会遇到“权限被拒绝”的错误?
更新
至今我仍未解决与失败的 mkdir() 调用相关的问题。然而,我确实修复了一个可能导致问题的问题。我创建目录和文件本身的方式不正确。
SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
File file = new File(getBatchDirectoryName(), mDateFormat.format(new Date())+ ".jpg");
public String getBatchDirectoryName() {
String app_folder_path = "";
app_folder_path = Environment.getExternalStorageDirectory() + "/images";
File dir = new File(app_folder_path);
if (!dir.exists() && !dir.mkdirs()) {
Toast.makeText(MainActivity.this, "Trip", Toast.LENGTH_SHORT).show();
}
return app_folder_path;
}
然而,它仍然无法创建目录。这使我回到了权限问题。
Environment.getExternalStorageDirectory()似乎已被弃用。文档建议使用getExternalFilesDir(string)或MediaStore。然而,我在寻找示例用例时遇到了问题。我无法想象,尽管被弃用,它会完全停止工作。市场上大多数设备的API版本不会高于29。
file.mkdirs();
创建文件夹。检查返回值,因为它可能失败。如果失败,请显示一个toast通知用户并返回。不要继续执行! - blackapps