修改cordova底层以支持input直接打开摄像机或视频库
文章目录
需求背景
cordova环境下,调用摄像机或视频库的代码与纯h5环境下不一致,这使得我们要写很多额外代码。本文用以解决这个问题。
相关照片和相册问题已经有另一篇文档:修改cordova底层以支持input直接打开照相机或图片库
当前时间:20210111
cordova版本: v.9.0+
android sdk: >=24
改造过程
最终目标是兼容摄像和照相的处理。
增加操作类型判断函数getActType
private int getActType(Intent selectIntent){
if (selectIntent != null) {
String intent_type = selectIntent.getType();
if (intent_type != null) {
if (intent_type.indexOf("image/") == 0) {
return 1;
} else if (intent_type.indexOf("video/") == 0) {
return 2;
}
}
}
return 0;
}
增加返回值处理函数__getFileUrisByIntent
处理选择相册文件之后数据处理。此外摄像的返回值也会经过这里的intent.getData()
部分
private Uri[] __getFileUrisByIntent(Intent intent){
Uri[] result = null;
if (intent != null) {
选择文件
if (intent.getClipData() != null) {
// handle multiple-selected files
final int numSelectedFiles = intent.getClipData().getItemCount();
result = new Uri[numSelectedFiles];
for (int i = 0; i < numSelectedFiles; i++) {
result[i] = intent.getClipData().getItemAt(i).getUri();
LOG.d(LOG_TAG, "getFilesResultByIntent Receive file chooser URL: " + result[i]);
}
} else if (intent.getData() != null) {
// handle single-selected file
result = WebChromeClient.FileChooserParams.parseResult(Activity.RESULT_OK, intent);
LOG.d(LOG_TAG, "getFilesResultByIntent Receive file chooser URL: " + result);
}
}
return result;
}
修改函数onShowFileChooser
@Override
public boolean onShowFileChooser(WebView webView,
final ValueCallback<Uri[]> filePathsCallback,
final WebChromeClient.FileChooserParams fileChooserParams) {
// Check if multiple-select is specified
Boolean selectMultiple = false;
if (fileChooserParams.getMode() == WebChromeClient.FileChooserParams.MODE_OPEN_MULTIPLE) {
selectMultiple = true;
}
Intent intent = fileChooserParams.createIntent();
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, selectMultiple);
boolean isCapture = fileChooserParams.isCaptureEnabled();
// Uses Intent.EXTRA_MIME_TYPES to pass multiple mime types.
String[] acceptTypes = fileChooserParams.getAcceptTypes();
if (acceptTypes.length > 1) {
intent.setType("*/*"); // Accept all, filter mime types by Intent.EXTRA_MIME_TYPES.
intent.putExtra(Intent.EXTRA_MIME_TYPES, acceptTypes);
}
try {
if (getActType(intent)> 0){
showCameraSelectIntent(isCapture, filePathsCallback, intent);
}else{
//正常筛选
parentEngine.cordova.startActivityForResult(new CordovaPlugin() {
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
Uri[] result = null;
if (resultCode == Activity.RESULT_OK && intent != null) {
result = __getFileUrisByIntent(intent);
}
filePathsCallback.onReceiveValue(result);
}
}, intent, FILECHOOSER_RESULTCODE);
}
} catch (ActivityNotFoundException e) {
LOG.w("No activity found to handle file chooser intent.", e);
filePathsCallback.onReceiveValue(null);
}
return true;
}
调整函数showCameraSelectIntent
上篇博文中,原函数是showImageSelectIntent,修改函数名称,调整内容
public void showCameraSelectIntent(boolean onlyCapture,
final ValueCallback<Uri[]> filePathsCallback,
Intent selectIntent){
try {
int Act_type = getActType(selectIntent);//操作类型
Intent captureIntent = null; //照相或者摄像,捕获用的Intent
String mCameraPhotoPath = null; //照相时候的Path
String showTitle = "";
if (Act_type == 1){
captureIntent = getTakePictureIntent();//拍照Intent
mCameraPhotoPath = captureIntent.getStringExtra("filepath") + "";
showTitle = "Image Chooser";
}else if (Act_type == 2){
captureIntent = getTakeVideoIntent();//摄像Intent 返回值会走intent.getData()
showTitle = "video Chooser";
}
Intent[] intentArray = (captureIntent != null)? new Intent[]{captureIntent} : new Intent[2];
//发起选择
Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
chooserIntent.putExtra(Intent.EXTRA_INTENT, selectIntent);
chooserIntent.putExtra(Intent.EXTRA_TITLE, showTitle);
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
Intent f_intent = null;
if (onlyCapture) f_intent = captureIntent;
else f_intent = Intent.createChooser(chooserIntent, showTitle);
String finalMCameraPhotoPath = mCameraPhotoPath;
parentEngine.cordova.startActivityForResult(new CordovaPlugin() {
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
Uri[] result = null;
if (resultCode == Activity.RESULT_OK) {
if (intent != null) {选择文件
result = __getFileUrisByIntent(intent);
} else {照片
添加图片到相册
MediaScannerConnection.scanFile(parentEngine.cordova.getContext().getApplicationContext(),
new String[]{finalMCameraPhotoPath}, null,
new MediaScannerConnection.OnScanCompletedListener() {
@Override
public void onScanCompleted(String path, Uri uri) {
}
});
// File retFile = new File(mCameraPhotoPath);
result = new Uri[]{Uri.parse("file:" + finalMCameraPhotoPath)};
}
}
filePathsCallback.onReceiveValue(result);
}
}, f_intent, IMAGE_FILECHOOSER_RESULTCODE);
}catch (Exception e){
LOG.e(LOG_TAG, "showCameraSelectIntent error", e);
e.printStackTrace();
filePathsCallback.onReceiveValue(null);
}
}
获取image的intent
private Intent getTakePictureIntent(){
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(parentEngine.cordova.getActivity().getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = getFileForCameraCapture("IMG_", "jpg");
Log.w(LOG_TAG, "getTakePictureIntent photoFile="+photoFile);
// Continue only if the File was successfully created
if (photoFile != null) {
String mCameraPhotoPath = photoFile.getAbsolutePath();
Log.w(LOG_TAG, "getTakePictureIntent mCameraPhotoPath="+mCameraPhotoPath);
Uri photoUri = FileProvider.getUriForFile(
parentEngine.cordova.getContext(),
parentEngine.cordova.getActivity().getPackageName() + ".provider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
takePictureIntent.putExtra(MediaStore.AUTHORITY, true);
takePictureIntent.putExtra("return-data", true);
takePictureIntent.putExtra("filepath", mCameraPhotoPath);
takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
} else {
takePictureIntent = null;
}
}
return takePictureIntent;
}
获取video的Intent
private Intent getTakeVideoIntent(){
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
//设置视频录制的最长时间
intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 15);
//设置视频录制的画质
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
return intent;
}
参考文档
H5中有拍摄视频或者选择视频 onShowFileChooser
android视频录制MediaStore.ACTION_VIDEO_CAPTURE