我正在使用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 accessible和Android 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上调试检索到的数据,如果我已经更改