Android 6.0.1无法创建目录(Environment.getExternalStoragePublicDirectory(Environment.directory_PICTURES),“MyCameraApp”;?
我正在使用WebView和摄像头功能构建我的第一个Android应用程序。我一直在关注官方文件,遇到了很多问题 例如,根据文档,我使用下面提供的示例代码:Android 6.0.1无法创建目录(Environment.getExternalStoragePublicDirectory(Environment.directory_PICTURES),“MyCameraApp”;?,android,android-intent,android-camera,Android,Android Intent,Android Camera,我正在使用WebView和摄像头功能构建我的第一个Android应用程序。我一直在关注官方文件,遇到了很多问题 例如,根据文档,我使用下面提供的示例代码: /** Create a file Uri for saving an image or video */ private static Uri getOutputMediaFileUri(int type){ return Uri.fromFile(getOutputMediaFile(type)); } /** Create
/** 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;
}
它在我运行安卓5.0.2的设备上运行得非常好,但它无法在安卓6.0.1上创建目录。我正在调试这个过程,我注意到它在代码的这一部分返回null
:
if (! mediaStorageDir.mkdirs()){
Log.d("MyCameraApp", "failed to create directory");
return null;
}
我在网上搜索,我发现了关于这个问题的类似线索,比如(,和)等等
在最后一个线程中,如果你读到一条评论,它会说:
如果您正在寻找存储卡路径,则无法在所有设备上找到它。根据官方文件,公共静态字符串目录\图片标准目录,用于放置用户可用的图片。您无法控制返回的路径
这是有道理的,这就是为什么我想使用默认值,但由于它在Android 6.0.1上不起作用,我想通过指定保存文件的位置来应用一种变通方法。摘自官方文件:
MediaStore.EXTRA_输出-此设置需要一个Uri对象,指定保存图片的路径和文件名。此设置是可选的,但强烈建议使用。如果未指定此值,相机应用程序将使用返回的intent的intent.getData()字段中指定的默认名称将请求的图片保存在默认位置
如果我理解正确,我可以指定另一个文件路径位置,例如mediaFile=file.createTempFile(时间戳、扩展名、mWebViewActivity.getExternalCacheDir())代码>
这个小的变通方法帮助我克服了安卓6.0.1和安卓5.0.2中的问题,但当我检索到的数据为空时,这两种情况都有不利的一面
从文档中检索数据的代码示例:
如果我更改了位置以从File mediaStorageDir=new文件(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),“MyCameraApp”)保存数据
tomediaFile=File.createTempFile(时间戳,扩展名,mWebViewActivity.getExternalCacheDir())代码>,这两种环境(5.0.2和6.0.1)都可以克服问题并“假装工作正常”。所谓假装,我的意思是我没有收到任何错误或应用程序没有崩溃,但有一个问题
如文件所述:
如果未指定此值,相机应用程序将使用返回的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;
}
public Intent makechooserint(字符串标题,WebChromeClient.FileChooserParams FileChooserParams){
Intent gallerycontent=新意图(Intent.ACTION\u选择器、MediaStore.Images.Media.EXTERNAL\u内容\u URI);
Intent chooser=Intent.createChooser(gallerycontent,title);
List intentActivitiesList=新建ArrayList();
如果(选中CameraHardware(mWebViewActivity.getApplicationContext()){
Log.d(标签“设备有摄像头”);
//创造新的意图
意向视频意向=新意向(MediaStore.ACTION\u VIDEO\u CAPTURE);
Intent-imageIntent=newintent(android.provider.MediaStore.ACTION\u-IMAGE\u-CAPTURE);
intentActivitiesList.add(imageIntent);
意向性列表。添加(视频意向);
添加(fileChooserParams.createIntent());
试一试{
imageFileUri=getOutputMediaFileUri(媒体类型图像);//创建一个文件以保存图像
videoFileUri=getOutputMediaFileUri(媒体类型视频);//创建一个文件以保存视频
}捕获(IOE异常){
Log.e(标记“创建tmp文件时出错:”+e);
}
chooser.putExtra(MediaStore.EXTRA_OUTPUT,videoFileUri);//设置图像文件名
chooser.putExtra(MediaStore.EXTRA_VIDEO_QUALITY,1);//将视频图像质量设置为高
putExtra(MediaStore.EXTRA_输出,imageFileUri);
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS,intentActivitiesList.toArray(新地块[]{}));
}
返回选择器;
}
我认为错误来自选择器,因为它没有寻找正确的Uri
所以我的问题是,这是一个错误,还是我设置了一些完全错误的东西
很抱歉问了这么长的问题/帖子,但我试图解释我应用的所有问题/解决方案
如果我在Android 5.0.2上调试检索到的数据,如果我更改了,如果您的目标是SDK 23并使用棉花糖(只要清单中有正确的权限,棒棒糖就可以正常工作),那么您需要在运行时获得危险的权限:考虑录制音频/读取/写入外部存储(正确的做法)作为“危险权限”。Hello@MarkKeen是的,我注意到,最初我的应用程序崩溃了,但后来我发现了解决方法,正如你从链接中指出的,它实际上非常简单。我修改了build.gradle以使用targetSdkVersion 22
,它在两个Android版本(5.0.2和6.0.1)上都运行良好。但你说的是真的。你面临的具体问题是什么?如果你
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;
}