Android - 无法保存图像

时间:2015-05-28 20:41:57

标签: android image android-external-storage

我目前正在尝试使用内置摄像头的设备进行图像保存。这是我正在使用的代码:

            PackageManager pm = getActivity().getPackageManager();
            if (pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)) {
                Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

                // * Ensure that there's a camera activity to handle the intent
                if (takePictureIntent.resolveActivity(pm) != null) {
                    // * Create the File where the photo should go
                    File photoFile = null;
                    try {
                        photoFile = ImageFileHelper.createImageFile();
                    } catch (IOException ex) {
                        // * Error occurred while creating the File
                        Timber.d("An error occurred while creating file: " + ex.getLocalizedMessage());
                    }
                    // * Continue only if the File was successfully created
                    if (photoFile != null) {
                        takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
                        startActivityForResult(takePictureIntent, REQUEST_CODE_TAKE_PICTURE);
                    } else {
                        alertUserOfError(0);
                    }
                }
            } else {
                // * Inform user that they need a camera 
                // * to use this feature
                alertUserOfError(1);
            }

这是ImageFileHelper.createImageFile()函数:

public static File createImageFile() throws IOException {

    // Create an image file name
    String timeStamp = new SimpleDateFormat("yyyy-MM-dd.ss", Locale.getDefault()).format(new Date());
    String imageFileName = "Original_Avatar_" + timeStamp;

    // * Create MyApp folder if not exist
    String path = Environment.getExternalStorageDirectory() + File.separator + Environment.DIRECTORY_PICTURES;
    File dir = new File(path + "/MyApp/Originals/");
    dir.mkdirs();

    File image = File.createTempFile(
        imageFileName,      /* prefix */
        ".png",             /* suffix */
        dir                 /* directory */
    );

    // Save a file: path for use with ACTION_VIEW intents
    filePath = "file:" + image.getAbsolutePath();
    Timber.d("image created at: " + filePath);
    return image;
}

我的权限&特性:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:glEsVersion="0x00020000" android:required="true"/>

这似乎在我的测试设备和我的大多数beta测试设备上运行良好。但是,有一个人报告他收到alertUserOfError(0)生成的错误消息(您将在上面的代码中看到),基本上是photoFile为空。

他使用的是根HTC One(M8)(htc_m8)。由于设备已植根,这可能是一个问题吗?

感谢任何帮助。

更新2015-05-30 我还没有机会向catch语句添加报告,但我确实添加了一个方法来测试有效的路径/目录。以下是它的工作原理:

    StringBuilder build = new StringBuilder();

    String path_1 = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + File.separator + "MyApp" + File.separator + "Cropped" + File.separator;
    File dir_1 = new File(path_1);

    dir_1.mkdirs();
    if (dir_1.exists()) {
        build.append("path 1 valid, ");
    } else {
        build.append("path 1 invalid, ");
    }

使用相同的设置我还测试了以下目录:

Environment.getExternalStorageDirectory() + File.separator + "MyApp" + File.separator + "Cropped" + File.separator;
Environment.getDataDirectory() + File.separator + "MyApp" + File.separator + "Cropped" + File.separator;

然后将StringBuilder.toString()用作警报中的消息,以便测试人员将结果发回给我们。

以上导致所有路径无效: path_1无效,path_2无效,path_3无效

这是否意味着这些目录在HTC One(M8)(htc_m8)上不存在且无法创建?

1 个答案:

答案 0 :(得分:0)

我有类似的情况。您正在实施官方文档中给出的示例。在某些设备中实现该示例存在问题。这就是我解决它的方法。

替换:

Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES)

使用:

private File createImageFile() throws IOException {
        // Create an image file name

最后,请务必致电:

mkdirs() // and not mkdir()

这里有适合您的代码:

        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "JPEG_" + timeStamp + "_";
        File storageDir = new File(Environment.getExternalStorageDirectory().toString(), "whatever_directory_existing_or_not/sub_dir_if_needed/");
        storageDir.mkdirs(); // make sure you call mkdirs() and not mkdir()
        File image = File.createTempFile(
                imageFileName,  // prefix
                ".jpg",         // suffix
                storageDir      // directory
        );

        // Save a file: path for use with ACTION_VIEW intents

        mCurrentPhotoPath = "file:" + image.getAbsolutePath();
        Log.e("our file", image.toString());
        return image;
    }

根据Android Studio Documentation中给出的示例,我遇到了不好的经历,我发现在stackoverflow中有很多其他人对此特定主题有相同的看法,这是因为即使我们设置了

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

某些设备问题仍然存在。

我的经验是,当我在调试模式下尝试它时,该示例有效,经过3次测试后,我的SD突然被破坏了,但我不认为它与他们的示例有关(滑稽)。我买了一张新的SD卡并再次尝试(因为我无法重新格式化我的SD,但我尝试过),只是意识到仍然发布和调试模式都执行相同的错误日志:目录不存在ENOENT。最后,我不得不自己创建目录,其中包含我手机摄像头拍摄的照片。我是对的,它的工作非常完美。

我希望这能帮助那些寻找答案的人,因为很明显,考虑到你的询问年龄,你必须已经解决了这个问题。