Android 6.0.1无法创建目录(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),“MyCameraApp”);?

时间:2016-02-17 10:58:32

标签: android android-intent android-camera

我正在使用WebView和Camera功能构建应用程序我的第一个Android应用程序。我一直在关注官方文档,我遇到了很多问题。

例如Saving Media Files根据文档提供的示例代码,我按照提供的方式使用它:

/** Create a file Uri for saving an image or video */
private static Uri getOutputMediaFileUri(int type){
      return Uri.fromFile(getOutputMediaFile(type));
}

/** Create a File for saving an image or video */
private static File getOutputMediaFile(int type){
    // To be safe, you should check that the SDCard is mounted
    // using Environment.getExternalStorageState() before doing this.

    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
              Environment.DIRECTORY_PICTURES), "MyCameraApp");
    // This location works best if you want the created images to be shared
    // between applications and persist after your app has been uninstalled.

    // Create the storage directory if it does not exist
    if (! mediaStorageDir.exists()){
        if (! mediaStorageDir.mkdirs()){
            Log.d("MyCameraApp", "failed to create directory");
            return null;
        }
    }

    // Create a media file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    File mediaFile;
    if (type == MEDIA_TYPE_IMAGE){
        mediaFile = new File(mediaStorageDir.getPath() + File.separator +
        "IMG_"+ timeStamp + ".jpg");
    } else if(type == MEDIA_TYPE_VIDEO) {
        mediaFile = new File(mediaStorageDir.getPath() + File.separator +
        "VID_"+ timeStamp + ".mp4");
    } else {
        return null;
    }

    return mediaFile;
}

它在我运行Android 5.0.2的设备上运行良好,但无法在Android Android 6.0.1上创建目录。我正在调试该过程,我注意到它在代码的这一部分返回null

if (! mediaStorageDir.mkdirs()){
            Log.d("MyCameraApp", "failed to create directory");
            return null;
        }

我在网上搜索,我发现了有关此问题的类似帖子,例如(Why can i not make a directory inside Environment.DIRECTORY_PICTURES?android environment.directory_pictures not accessibleAndroid getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) returns path to /storage/emulated/0 instead of pictures path)等...

如果您阅读评论,请在最后一个帖子中说:

如果您正在寻找存储卡路径,则不会在所有设备上获取它。根据官方文档public static String DIRECTORY_PICTURES标准目录,用于放置用户可用的图片。你无法控制返回的路径

这是有道理的,这就是我想使用默认值的原因,但由于它不适用于Android 6.0.1,我想通过指定保存文件的位置来应用解决方法。摘自官方文档Image capture intent

MediaStore.EXTRA_OUTPUT - 此设置需要一个Uri对象,指定您要保存图片的路径和文件名。此设置是可选的,但强烈建议使用。如果未指定此值,则摄像头应用程序会将所请求的图片保存在默认位置,并使用在返回的intent的Intent.getData()字段中指定的默认名称。

如果我理解正确,我可以指定备用文件路径位置,例如mediaFile = File.createTempFile(timeStamp, extension, mWebViewActivity.getExternalCacheDir());

这个小的解决方法帮助我克服了Android 6.0.1和Android 5.0.2中的问题,但是当我检索数据时,这两个问题都是空的。

从文档Receiving camera intent result检索数据的代码示例:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
        if (resultCode == RESULT_OK) {
            // Image captured and saved to fileUri specified in the Intent
            Toast.makeText(this, "Image saved to:\n" +
                     data.getData(), Toast.LENGTH_LONG).show();
        } else if (resultCode == RESULT_CANCELED) {
            // User cancelled the image capture
        } else {
            // Image capture failed, advise user
        }
    }

    if (requestCode == CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE) {
        if (resultCode == RESULT_OK) {
            // Video captured and saved to fileUri specified in the Intent
            Toast.makeText(this, "Video saved to:\n" +
                     data.getData(), Toast.LENGTH_LONG).show();
        } else if (resultCode == RESULT_CANCELED) {
            // User cancelled the video capture
        } else {
            // Video capture failed, advise user
        }
    }
}

如果我更改了位置以将数据从File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyCameraApp");保存到mediaFile = File.createTempFile(timeStamp, extension, mWebViewActivity.getExternalCacheDir());,则两个环境(5.0.2和6.0.1)都可以解决问题并“假装工作正常”。通过说假装我的意思是我没有得到任何错误或APP没有崩溃,但有一个问题。

正如文件所述:

如果未指定此值,摄像头应用程序会将所请求的图片保存在默认位置,并使用在返回的intent的Intent.getData()字段中指定的默认名称。

在可能的情况下,究竟发生了什么。两个版本都无法理解我正在使用的Uri。在5.0.2上,它可以采用默认位置并“以某种方式”完成该过程,但在6.0.1上,因为它找不到默认位置,它只需要图片/视频,但它不会将它存储在任何地方,所以它可以检索并且数据是空的。

我已将其包含在我的清单文件中:

<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-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

**更新:**添加选择器,

public Intent makeChooserIntent(String title, WebChromeClient.FileChooserParams fileChooserParams) {

        Intent galleryIntent = new Intent(Intent.ACTION_CHOOSER, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

        Intent chooser = Intent.createChooser(galleryIntent, title);

        List<Intent> intentActivitiesList = new ArrayList<>();
        if (checkCameraHardware(mWebViewActivity.getApplicationContext())) {
            Log.d(TAG, "Device has camera.");

            //create new Intent
            Intent videoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
            Intent imageIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);

            intentActivitiesList.add(imageIntent);
            intentActivitiesList.add(videoIntent);
            intentActivitiesList.add(fileChooserParams.createIntent());

            try {
                imageFileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); // create a file to save the image
                videoFileUri = getOutputMediaFileUri(MEDIA_TYPE_VIDEO);  // create a file to save the video
            } catch (IOException e) {
                Log.e(TAG, "Error creating tmp file: " + e);
            }

            chooser.putExtra(MediaStore.EXTRA_OUTPUT, videoFileUri); // set the image file name
            chooser.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1); // set the video image quality to high
            chooser.putExtra(MediaStore.EXTRA_OUTPUT, imageFileUri);
            chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentActivitiesList.toArray(new Parcelable[]{}));
        }
        return chooser;
    }

我认为错误来自选择器,因为没有找到正确的Uri。

所以我的问题是,这是一个错误,还是我设置了一些完全错误的东西?

很抱歉这个很长的问题/帖子,但我试图解释我已应用的所有问题/解决方案。

如果我在Android 5.0.2上调试检索到的数据,如果我已经更改

0 个答案:

没有答案