前言

安卓原生组件webview加载h5的URL,若要h5调用安卓原生相机和相册有效需要做以下操作。

测试机:魅蓝note2  系统5.1.1

华为荣耀畅玩7x  系统8.0.0

一、h5页面相关

方便与安卓原生代码相对应且拿到相对应的file值,避免之后不必要的不匹配麻烦。

1、标签设置 [相机、相册]

<input type="file" accept="image/*" capture="camera">
<input type="file" accept="image/*" >

2、函数代码

(1)js方法,使用FormData方法避免安卓端兼容更多的机型

// 实例化一个空对象
var data = new FormData();
//获取file文件
var file=document.getElementById(yourInputId).files[0];
//将文件加入到data中,一般FormData对象中添加数据使用append()方法
data.append(file)
// 创建一个HTTP请求
var request = new XMLHttpRequest();
// 然后使用open方法,选择传送的method和后台的URL
request.open("POST|GET", "URL");
// 最后,向后台发送我们的数据
request.send(data)

(2)如果是jquery写法如下

// 获取要传输的文件------假设只有一个文件
var file = document.getElementById(yourInputId).files[0];
// ajax传输
$.ajax({url: URL,type: "POST",  async: false,  cache: false, processData: false,// 告诉jQuery不要去处理发送的数据contentType: false,// 告诉jQuery不要去设置Content-Type请求头data: file,success: function(data){alert(data);},error: function(err) {alert(err);}
});

二、Android端原生相关

(1)webview配置

 WebSettings settings = webView.getSettings();//开启JavaScript支持settings.setJavaScriptEnabled(true);settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);settings.setBuiltInZoomControls(true);settings.setDisplayZoomControls(false);settings.setAppCacheEnabled(false);settings.setUseWideViewPort(true);settings.setLoadWithOverviewMode(true);settings.setDomStorageEnabled(true);settings.setDefaultTextEncodingName("UTF-8");settings.setAllowContentAccess(true); //是否可访问Content Provider的资源,默认值 truesettings.setAllowFileAccess(true);    //是否可访问本地文件,默认值 true//是否允许通过file url加载的Javascript读取本地文件,默认值 falsesettings.setAllowFileAccessFromFileURLs(false);//是否允许通过file url加载的Javascript读取全部资源(包括文件,http,https),默认值 falsesettings.setAllowUniversalAccessFromFileURLs(false);//支持缩放settings.setSupportZoom(true);//辅助WebView设置处理关于页面跳转,页面请求等操作webView.setWebViewClient(new MyWebViewClient());//辅助WebView处理图片上传操作webView.setWebChromeClient(new MyChromeWebClient());//加载地址[你自己的加载url地址]webView.loadUrl(loadUrl);

(2)自定义MyChromeWebClient辅助webview处理除视频外调用相机的图片上传操作,如上文的文件上传标签

private class MyChromeWebClient extends WebChromeClient {// For Android 3.0-@SuppressWarnings("static-access")public void openFileChooser(ValueCallback<Uri> uploadMsg) {Log.i("MainNewActivity", "openFileChoose(ValueCallback<Uri> uploadMsg)");mUploadMessage = uploadMsg;if (videoFlag) {recordVideo();} else {takePhoto();}}// For Android 3.0+@SuppressWarnings("static-access")public void openFileChooser(ValueCallback uploadMsg, String acceptType) {Log.d("MainNewActivity", "openFileChoose( ValueCallback uploadMsg, String acceptType )");mUploadMessage = uploadMsg;if (videoFlag) {recordVideo();} else {takePhoto();}}//For Android 4.1@Overridepublic void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {Log.d("MainNewActivity", "openFileChoose(ValueCallback<Uri> uploadMsg, String acceptType, String capture)");mUploadMessage = uploadMsg;if (videoFlag) {recordVideo();} else {takePhoto();}}// For Android 5.0+@Overridepublic boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {Log.d("MainNewActivity", "onShowFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture)");mUploadCallbackAboveL = filePathCallback;if (videoFlag) {recordVideo();} else {onenFileChooseImpleForAndroid(filePathCallback);}return true;}@Overridepublic void onProgressChanged(WebView view, int newProgress) {if (newProgress == 100) {progressbar.setVisibility(GONE);} else {if (progressbar.getVisibility() == GONE)progressbar.setVisibility(VISIBLE);progressbar.setProgress(newProgress);}super.onProgressChanged(view, newProgress);}}

1⃣ 其中调用录像功能相关代码

private void recordVideo() {Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);//限制时长intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 10);//开启摄像机startActivityForResult(intent, VIDEO_REQUEST);
}

2⃣ 其中调用安卓系统小于5.0的相机功能相关代码

private void takePhoto() {File fileUri = new File(Environment.getExternalStorageDirectory().getPath() + "/" + SystemClock.currentThreadTimeMillis() + ".jpg");imageUri = Uri.fromFile(fileUri);Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);startActivityForResult(cameraIntent, PHOTO_REQUEST);
}

3⃣ 其中调用安卓系统大于5.0的相机功能相关代码

private void onenFileChooseImpleForAndroid(ValueCallback<Uri[]> filePathCallback) {mUploadMessageForAndroid5 = filePathCallback;cameraIntents = new ArrayList<Intent>();File fileUri = new File(Environment.getExternalStorageDirectory().getPath() + "/" + SystemClock.currentThreadTimeMillis() + ".jpg");imageUri = Uri.fromFile(fileUri);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {imageUri = FileProvider.getUriForFile(this, getPackageName() + ".provider", fileUri);//通过FileProvider创建一个content类型的Uri}if (Build.VERSION.SDK_INT >= 23) {int checkCallPhonePermission = ContextCompat.checkSelfPermission(MainNewActivity.this, Manifest.permission.CAMERA);if (checkCallPhonePermission != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(MainNewActivity.this, new String[]{Manifest.permission.CAMERA}, 222);return;} else {openCamera();}} else {openCamera();}
}private void openCamera() {Intent intentCamera = new Intent();if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {intentCamera.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//添加这一句表示对目标应用临时授权该Uri所代表的文件}intentCamera.setAction(MediaStore.ACTION_IMAGE_CAPTURE);//将拍照结果保存至photo_file的Uri中,不保留在相册中intentCamera.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);cameraIntents.add(intentCamera);Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);contentSelectionIntent.setType("*/*");Intent i = new Intent(Intent.ACTION_CHOOSER);i.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);i.putExtra(Intent.EXTRA_TITLE, "File Chooser");Intent chooserIntent = Intent.createChooser(i, "Image Chooser");chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[]{}));startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE_FOR_ANDROID_5);
}

4⃣ 重写权限回调方法 onRequestPermissionsResult(),避免部分机型安卓系统6.0自动阻止相关权限设置,现强制开启相关权限

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {switch (requestCode) {//就像onActivityResult一样这个地方就是判断你是从哪来的。case 222:if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {// Permission GrantedopenCamera();} else {// Permission DeniedToast.makeText(MainNewActivity.this, "很遗憾你把相机权限禁用了。请务必开启相机权限享受我们提供的服务吧。", Toast.LENGTH_SHORT).show();}break;default:super.onRequestPermissionsResult(requestCode, permissions, grantResults);}
}

(3)给webview设置安卓原生进度条progressbar

//创建进度条
progressbar = new ProgressBar(this,null,android.R.attr.progressBarStyleHorizontal);
//设置加载进度条的高度
progressbar.setLayoutParams(new AbsoluteLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, progressHeight, 0, 0));
webView.addView(progressbar);

(4)安卓系统返回按钮设置点击按钮返回h5上个页面、h5首页点击按钮退出整个应用

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) {webView.goBack();return true;} else {onBackPressed();}return super.onKeyDown(keyCode, event);
}@Override
public void onBackPressed() {showExit();
}private void showExit() {AlertDialog dialog = new AlertDialog.Builder(this).setTitle("提示").setMessage("是否确定退出xx应用吗?").setNegativeButton("确定", (dialog1, i) -> {//彻底关闭整个APPint currentVersion = android.os.Build.VERSION.SDK_INT;if (currentVersion > android.os.Build.VERSION_CODES.ECLAIR_MR1) {Intent startMain = new Intent(Intent.ACTION_MAIN);startMain.addCategory(Intent.CATEGORY_HOME);startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);startActivity(startMain);System.exit(0);} else {// android2.1ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);am.restartPackage(getPackageName());}dialog1.dismiss();}).setPositiveButton("取消", (dialog12, i) ->      dialog12.dismiss()).create();dialog.setCanceledOnTouchOutside(false);dialog.show();
}

(5)兼容安卓系统8.0

1⃣ 在工程目录res 文件夹下面创建xml文件夹,且在对应的xml文件夹下面创建file_paths.xml配置文件

配置文件目录结构图

file_paths.xml配置文件内容如下

<?xml version="1.0" encoding="utf-8"?>
<resources><paths><external-pathname="camera_photos"path="" /></paths>
</resources>

2⃣ AndoirdManifest.xml文件相关配置

<providerandroid:name="android.support.v4.content.FileProvider"android:authorities="com.itouch.mywebview.provider"android:exported="false"android:grantUriPermissions="true"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/file_paths" />
</provider>

3⃣ 调用相关

imageUri = Uri.fromFile(fileUri);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {imageUri = FileProvider.getUriForFile(this, getPackageName() + ".provider", fileUri);//通过FileProvider创建一个content类型的Uri
}

(6)配置部分机型调用sd卡的读取权限工具类

public class PermissionUtils {// Storage Permissionsprivate static final int REQUEST_EXTERNAL_STORAGE = 1;private static String[] PERMISSIONS_STORAGE = {Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE};/*** Checks if the app has permission to write to device storage* If the app does not has permission then the user will be prompted to* grant permissions** @param activity*/public static void verifyStoragePermissions(Activity activity) {// Check if we have write permissionint permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);if (permission != PackageManager.PERMISSION_GRANTED) {// We don't have permission so prompt the userActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);}
}

(7)最后放上完整的view层代码

public class MainNewActivity extends AppCompatActivity {private final static int PHOTO_REQUEST = 100;private final static int VIDEO_REQUEST = 120;private final static int FILECHOOSER_RESULTCODE_FOR_ANDROID_5 = 200;private WebView webView;private ProgressBar progressbar;private int progressHeight = 10;private String loadUrl = "https://www.baidu.com";private ValueCallback<Uri> mUploadMessage;private ValueCallback<Uri[]> mUploadCallbackAboveL;private boolean videoFlag = false;private Uri imageUri;public static void launch(Context context) {context.startActivity(new Intent(context, MainNewActivity.class));}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);PermissionUtils.verifyStoragePermissions(this);setContentView(R.layout.activity_main_new);initWebView();}private void initWebView() {webView = (WebView) findViewById(R.id.webView);//创建进度条progressbar = new ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal);//设置加载进度条的高度progressbar.setLayoutParams(new AbsoluteLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, progressHeight, 0, 0));initWebViewSetting();}//初始化webViewSetting@SuppressLint("SetJavaScriptEnabled")private void initWebViewSetting() {webView.addView(progressbar);WebSettings settings = webView.getSettings();//开启JavaScript支持settings.setJavaScriptEnabled(true);settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);settings.setBuiltInZoomControls(true);settings.setDisplayZoomControls(false);settings.setAppCacheEnabled(false);settings.setUseWideViewPort(true);settings.setLoadWithOverviewMode(true);settings.setDomStorageEnabled(true);settings.setDefaultTextEncodingName("UTF-8");settings.setAllowContentAccess(true); //是否可访问Content Provider的资源,默认值 truesettings.setAllowFileAccess(true);    //是否可访问本地文件,默认值 true//是否允许通过file url加载的Javascript读取本地文件,默认值 falsesettings.setAllowFileAccessFromFileURLs(false);//是否允许通过file url加载的Javascript读取全部资源(包括文件,http,https),默认值 falsesettings.setAllowUniversalAccessFromFileURLs(false);//支持缩放settings.setSupportZoom(true);//辅助WebView设置处理关于页面跳转,页面请求等操作webView.setWebViewClient(new MyWebViewClient());//辅助WebView处理图片上传操作webView.setWebChromeClient(new MyChromeWebClient());//加载地址webView.loadUrl(loadUrl);}//自定义 WebViewClient 辅助WebView设置处理关于页面跳转,页面请求等操作【处理tel协议和视频通讯请求url的拦截转发】private class MyWebViewClient extends WebViewClient {@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {Log.e("=url", url);if (!TextUtils.isEmpty(url)) {videoFlag = url.contains("vedio");}if (url.trim().startsWith("tel")) {//特殊情况tel,调用系统的拨号软件拨号【<a href="tel:1111111111">1111111111</a>】Intent i = new Intent(Intent.ACTION_VIEW);i.setData(Uri.parse(url));startActivity(i);} else {String port = url.substring(url.lastIndexOf(":") + 1, url.lastIndexOf("/"));//尝试要拦截的视频通讯url格式(808端口):【http://xxxx:808/?roomName】if (port.equals("808")) {//特殊情况【若打开的链接是视频通讯地址格式则调用系统浏览器打开】Intent i = new Intent(Intent.ACTION_VIEW);i.setData(Uri.parse(url));startActivity(i);} else {//其它非特殊情况全部放行view.loadUrl(url);}}return true;}@Overridepublic void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {//https忽略证书问题handler.proceed();}@Overridepublic void onPageFinished(WebView view, String url) {progressbar.setVisibility(GONE);super.onPageFinished(view, url);}}//自定义 WebChromeClient 辅助WebView处理图片上传操作【<input type=file> 文件上传标签】private class MyChromeWebClient extends WebChromeClient {// For Android 3.0-@SuppressWarnings("static-access")public void openFileChooser(ValueCallback<Uri> uploadMsg) {Log.i("MainNewActivity", "openFileChoose(ValueCallback<Uri> uploadMsg)");mUploadMessage = uploadMsg;if (videoFlag) {recordVideo();} else {takePhoto();}}// For Android 3.0+@SuppressWarnings("static-access")public void openFileChooser(ValueCallback uploadMsg, String acceptType) {Log.d("MainNewActivity", "openFileChoose( ValueCallback uploadMsg, String acceptType )");mUploadMessage = uploadMsg;if (videoFlag) {recordVideo();} else {takePhoto();}}//For Android 4.1@Overridepublic void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {Log.d("MainNewActivity", "openFileChoose(ValueCallback<Uri> uploadMsg, String acceptType, String capture)");mUploadMessage = uploadMsg;if (videoFlag) {recordVideo();} else {takePhoto();}}// For Android 5.0+@Overridepublic boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {Log.d("MainNewActivity", "onShowFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture)");mUploadCallbackAboveL = filePathCallback;if (videoFlag) {recordVideo();} else {onenFileChooseImpleForAndroid(filePathCallback);}return true;}@Overridepublic void onProgressChanged(WebView view, int newProgress) {if (newProgress == 100) {progressbar.setVisibility(GONE);} else {if (progressbar.getVisibility() == GONE)progressbar.setVisibility(VISIBLE);progressbar.setProgress(newProgress);}super.onProgressChanged(view, newProgress);}}private ValueCallback<Uri[]> mUploadMessageForAndroid5;private List<Intent> cameraIntents;private void onenFileChooseImpleForAndroid(ValueCallback<Uri[]> filePathCallback) {mUploadMessageForAndroid5 = filePathCallback;cameraIntents = new ArrayList<Intent>();File fileUri = new File(Environment.getExternalStorageDirectory().getPath() + "/" + SystemClock.currentThreadTimeMillis() + ".jpg");imageUri = Uri.fromFile(fileUri);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {imageUri = FileProvider.getUriForFile(this, getPackageName() + ".provider", fileUri);//通过FileProvider创建一个content类型的Uri}if (Build.VERSION.SDK_INT >= 23) {int checkCallPhonePermission = ContextCompat.checkSelfPermission(MainNewActivity.this, Manifest.permission.CAMERA);if (checkCallPhonePermission != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(MainNewActivity.this, new String[]{Manifest.permission.CAMERA}, 222);return;} else {openCamera();}} else {openCamera();}}@Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {switch (requestCode) {//就像onActivityResult一样这个地方就是判断你是从哪来的。case 222:if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {// Permission GrantedopenCamera();} else {// Permission DeniedToast.makeText(MainNewActivity.this, "很遗憾你把相机权限禁用了。请务必开启相机权限享受我们提供的服务吧。", Toast.LENGTH_SHORT).show();}break;default:super.onRequestPermissionsResult(requestCode, permissions, grantResults);}}private void openCamera() {Intent intentCamera = new Intent();if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {intentCamera.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//添加这一句表示对目标应用临时授权该Uri所代表的文件}intentCamera.setAction(MediaStore.ACTION_IMAGE_CAPTURE);//将拍照结果保存至photo_file的Uri中,不保留在相册中intentCamera.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);cameraIntents.add(intentCamera);Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);contentSelectionIntent.setType("*/*");Intent i = new Intent(Intent.ACTION_CHOOSER);i.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);i.putExtra(Intent.EXTRA_TITLE, "File Chooser");Intent chooserIntent = Intent.createChooser(i, "Image Chooser");chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[]{}));startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE_FOR_ANDROID_5);}private void takePhoto() {File fileUri = new File(Environment.getExternalStorageDirectory().getPath() + "/" + SystemClock.currentThreadTimeMillis() + ".jpg");imageUri = Uri.fromFile(fileUri);Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);startActivityForResult(cameraIntent, PHOTO_REQUEST);}//录像private void recordVideo() {Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);//限制时长intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 10);//开启摄像机startActivityForResult(intent, VIDEO_REQUEST);}@Overridepublic void onBackPressed() {showExit();}private void showExit() {AlertDialog dialog = new AlertDialog.Builder(this).setTitle("提示").setMessage("是否确定退出xx应用吗?").setNegativeButton("确定", (dialog1, i) -> {//彻底关闭整个APPint currentVersion = android.os.Build.VERSION.SDK_INT;if (currentVersion > android.os.Build.VERSION_CODES.ECLAIR_MR1) {Intent startMain = new Intent(Intent.ACTION_MAIN);startMain.addCategory(Intent.CATEGORY_HOME);startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);startActivity(startMain);System.exit(0);} else {// android2.1ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);am.restartPackage(getPackageName());}dialog1.dismiss();}).setPositiveButton("取消", (dialog12, i) -> dialog12.dismiss()).create();dialog.setCanceledOnTouchOutside(false);dialog.show();}@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) {webView.goBack();return true;} else {onBackPressed();}return super.onKeyDown(keyCode, event);}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (requestCode == PHOTO_REQUEST) {if (null == mUploadMessage && null == mUploadCallbackAboveL) return;Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();if (mUploadCallbackAboveL != null) {onActivityResultAboveL(requestCode, resultCode, data);} else if (mUploadMessage != null) {mUploadMessage.onReceiveValue(result);mUploadMessage = null;}} else if (requestCode == VIDEO_REQUEST) {if (null == mUploadMessage && null == mUploadCallbackAboveL) return;Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();if (mUploadCallbackAboveL != null) {if (resultCode == RESULT_OK) {mUploadCallbackAboveL.onReceiveValue(new Uri[]{result});mUploadCallbackAboveL = null;} else {mUploadCallbackAboveL.onReceiveValue(new Uri[]{});mUploadCallbackAboveL = null;}} else if (mUploadMessage != null) {if (resultCode == RESULT_OK) {mUploadMessage.onReceiveValue(result);mUploadMessage = null;} else {mUploadMessage.onReceiveValue(Uri.EMPTY);mUploadMessage = null;}}} else if (requestCode == FILECHOOSER_RESULTCODE_FOR_ANDROID_5) {if (null == mUploadMessageForAndroid5)return;Uri result = (data == null || resultCode != RESULT_OK) ? null : data.getData();if (result != null) {mUploadMessageForAndroid5.onReceiveValue(new Uri[]{result});} else {Uri[] results = new Uri[]{imageUri};mUploadMessageForAndroid5.onReceiveValue(results);}mUploadMessageForAndroid5 = null;}}@TargetApi(Build.VERSION_CODES.LOLLIPOP)private void onActivityResultAboveL(int requestCode, int resultCode, Intent data) {if (requestCode != PHOTO_REQUEST || mUploadCallbackAboveL == null) {return;}Uri[] results = null;if (resultCode == Activity.RESULT_OK) {if (data == null) {results = new Uri[]{imageUri};} else {String dataString = data.getDataString();ClipData clipData = data.getClipData();if (clipData != null) {results = new Uri[clipData.getItemCount()];for (int i = 0; i < clipData.getItemCount(); i++) {ClipData.Item item = clipData.getItemAt(i);results[i] = item.getUri();}}if (dataString != null)results = new Uri[]{Uri.parse(dataString)};}}mUploadCallbackAboveL.onReceiveValue(results);mUploadCallbackAboveL = null;}@Overrideprotected void onDestroy() {if (webView != null) {// 如果先调用destroy()方法,则会命中if (isDestroyed()) return;这一行代码,需要先onDetachedFromWindow(),再// destory()ViewParent parent = webView.getParent();if (parent != null) {((ViewGroup) parent).removeView(webView);}webView.stopLoading();// 退出时调用此方法,移除绑定的服务,否则某些特定系统会报错webView.getSettings().setJavaScriptEnabled(false);webView.clearHistory();webView.clearView();webView.removeAllViews();webView.destroy();}super.onDestroy();}
}

完结

若有问题请留言,互助学习。

h5调用安卓原生相机、相册、电话、录像,且兼容安卓系统8.0相关推荐

  1. H5 调用android原生相机代码分析

    H5 页面在webView中调用原声相机: H5 端的代码:如下: <input id="upload" type="file" accept=" ...

  2. h5 调用ios原生相机拍照上传照片

    1.html中的点击按钮和回调显示标签---------------直接上代码 <!DOCTYPE html> <html lang="en"> <h ...

  3. React Native手动实现调用原生相机相册(Android端)

    前言 最近一直在学习RN的相关开发,想做一部分调用原生的实现,来练练手,于是就有了下面这个demo,由于本人是Android开发,所以只实现了Android端的效果. Demo 主要实现 这种调用原生 ...

  4. android native 相册,React Native手动实现调用原生相机相册(Android端)

    前言 最近一直在学习RN的相关开发,想做一部分调用原生的实现,来练练手,于是就有了下面这个demo,由于本人是Android开发,所以只实现了Android端的效果. Demo 主要实现 这种调用原生 ...

  5. h5 js调用移动端 相机 相册

    效果: 点击从手机相机获取图片或打开相机拍摄图片,  触屏缩放移动 加载的图片到合适位置 注意这里的几个坑: 1  在红米K40上 出现了  微信浏览器点击,触发change事件后只能调到相册,无法弹 ...

  6. H5调用Android原生Api

    Android 与H5交互之跳转拦截 Android拦截跳转,实现web调用原生Api 定义变量 在Android代码设置回调事件 前端代码 判断url是否合法 根据不同的type执行不同的操作 An ...

  7. android嵌套webview调原生相机相册

    //初始化webViewprivate void initWebView() {//从布局文件中扩展webViewwebView = (WebView) this.findViewById(R.id. ...

  8. H5调用微信原生扫码能力 (uniapp版本)

    技术背景 在uniapp打包成H5的过程中发现,uniapp提供的uni.scanCode扫码api不支持H5.不过微信原生的扫描真是又好用又方便,那有没有办法在h5下还能继续使用呢.答案是肯定的,方 ...

  9. 判断是否开启相机相册、定位权限并去系统开启权限

    #import <Foundation/Foundation.h> typedef NS_ENUM(NSInteger, ChosePhontType) { ChosePhontTypeA ...

最新文章

  1. flash 游戏 ui 制作方案
  2. select隐藏_数仓|几种SQL隐藏的错误,你遇到过吗?
  3. HTTP系列之:HTTP中的cookies
  4. hashCode()方法的作用使用分析
  5. Nodejs 博客系统遇到的问题及解决
  6. nd4j 向量_ND4J的基本操作
  7. ceph对接openstack环境
  8. 阿里云张建锋:如何管理超大规模研发团队?
  9. HTML5前端开发实战01-学生信息表
  10. 杨春立:基于数字孪生的智慧城市顶层设计探索与实践...
  11. 机器视觉培训教程-项目评估以及项目实施
  12. ajax传参后台中文乱码
  13. python时间计算天数差
  14. 开源的轻量级JSON存储Kinto介绍
  15. 设计模式中,MVC模式与MVT模式的区别
  16. 数据库关系代数思维导图
  17. C语言基础:if语句
  18. 树莓派:基于flask的远程视频监控
  19. 使用U盘安装 mac os
  20. npm 使用淘宝镜像及切换回官方源

热门文章

  1. 【汇编语言】从最底层的角度理解“堆栈”
  2. 亚马逊云科技依托人工智能进行游戏数据分析,解决游戏行业痛点,助力游戏增长
  3. 并行计算机原理实验报告,b计算机原理b实验报告.doc
  4. AD9361基础知识
  5. PPT基础(二十四)文字的边框和底色
  6. c语言用枪射气球小游戏,小程序,敲键盘,射气球(图形界面,第一次用汉字)
  7. 使用React头盔管理您的头脑
  8. R语言list.files
  9. 【博学谷学习记录】超强总结,用心分享 | 产品经理核心文档集锦
  10. 北京万博浩源小心车辆购置税退税骗子