【发布时间】:2020-07-28 18:57:56
【问题描述】:
我正在使用 Android Studio,用 Java 编写代码。我正在尝试编写一个软件,该软件将根据事件从相机中拍照。所以第一步首先是弄清楚API。相机折旧,所以有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"]
我四处搜索,寻找保存文件的不同方法,当我使用 camera2 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 文件定义了一个 jpg 文件,但随后您使用 file.mkdirs();在它上面创建一个目录。
-
file.mkdirs();检查返回值,因为它可能是 fsil。如果是这样,则显示敬酒以告知用户并返回。不要继续! -
@blackapps 你好。所以 file.mkdirs() 的返回总是假的。仔细查看文档,它特别指出“如果创建目录则返回 true,否则返回 false”。所以看看我是如何在 mkdirs() 之前检查它是否存在的,我假设它意味着 True 是成功创建的,而 false 意味着创建失败。
-
请在此处调整您的代码。并决定是否应该成为一个目录。我觉得它不对。
-
@blackapps 我修复了与创建带有 jpeg 文件名称的导演相关的问题,但似乎仍然存在某种性质的权限错误。我更新了我的帖子以反映我所做的和发现的。