安卓内核开发
其实是Android的webview默认是不支持<input type="file"/>文件上传的。现在的前端页面需要处理的是:
权限
文件路径AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
宿主返回代码
private ValueCallback<Uri> uploadMessage;private ValueCallback<Uri[]> uploadMessageAboveL;private final static int FILE_CHOOSER_RESULT_CODE = 10000;// 2.回调方法触发本地选择文件private void openImageChooserActivity() {Intent i = new Intent(Intent.ACTION_GET_CONTENT);i.addCategory(Intent.CATEGORY_OPENABLE);
// i.setType("image/*");//图片上传
// i.setType("file/*");//文件上传i.setType("*/*");//文件上传startActivityForResult(Intent.createChooser(i, "Image Chooser"), FILE_CHOOSER_RESULT_CODE);}// 3.选择图片后处理@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (requestCode == FILE_CHOOSER_RESULT_CODE) {if (null == uploadMessage && null == uploadMessageAboveL) return;Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();// Uri result = (((data == null) || (resultCode != RESULT_OK)) ? null : data.getData());if (uploadMessageAboveL != null) {onActivityResultAboveL(requestCode, resultCode, data);} else if (uploadMessage != null) {uploadMessage.onReceiveValue(result);uploadMessage = null;}} else {//这里uploadMessage跟uploadMessageAboveL在不同系统版本下分别持有了//WebView对象,在用户取消文件选择器的情况下,需给onReceiveValue传null返回值//否则WebView在未收到返回值的情况下,无法进行任何操作,文件选择器会失效if (uploadMessage != null) {uploadMessage.onReceiveValue(null);uploadMessage = null;} else if (uploadMessageAboveL != null) {uploadMessageAboveL.onReceiveValue(null);uploadMessageAboveL = null;}}}// 4. 选择内容回调到Html页面@TargetApi(Build.VERSION_CODES.LOLLIPOP)private void onActivityResultAboveL(int requestCode, int resultCode, Intent intent) {if (requestCode != FILE_CHOOSER_RESULT_CODE || uploadMessageAboveL == null)return;Uri[] results = null;if (resultCode == Activity.RESULT_OK) {if (intent != null) {String dataString = intent.getDataString();ClipData clipData = intent.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)};}}uploadMessageAboveL.onReceiveValue(results);uploadMessageAboveL = null;}
webview完整扩展
private class Cyber_ChromeClient extends WebChromeClient {
{@Overridepublic void onProgressChanged(WebView view, int newProgress) {super.onProgressChanged(view, newProgress);// mProgress.setProgress(newProgress);}@Overridepublic void onReceivedTitle(WebView view, String title) {super.onReceivedTitle(view, title);// mTitle.setText(title);}@Overridepublic void onReceivedIcon(WebView view, Bitmap icon) {super.onReceivedIcon(view, icon);}@Overridepublic boolean onJsAlert(WebView view, String url, String message, final android.webkit.JsResult result) {new AlertDialog.Builder(cyber_instance).setTitle("悠然智慧管理4.0").setMessage(message).setPositiveButton(android.R.string.ok,new AlertDialog.OnClickListener() {public void onClick(DialogInterface arg0, int arg1) {// TODO Auto-generated method stubresult.confirm();}}).setCancelable(false).create().show();return true;}//2020-5-15/*** 对网络连接状态进行判断* @return true, 可用; false, 不可用*/private boolean isOpenNetwork() {ConnectivityManager connManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);NetworkInfo networkInfo = connManager.getActiveNetworkInfo(); if(networkInfo!= null) {//2.获取当前网络连接的类型信息//int networkType = networkInfo.getType();if(ConnectivityManager.TYPE_WIFI == networkType){//当前为wifi网络}else if(ConnectivityManager.TYPE_MOBILE == networkType){//当前为mobile网络}return connManager.getActiveNetworkInfo().isAvailable(); }return false;}/*** 覆盖默认的window.confirm展示界面,避免title里显示为“:来自file:”*/public boolean onJsConfirm(WebView view, String url, String message,final JsResult result) {final AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext());builder.setTitle("优然智慧管理系统").setMessage(message).setPositiveButton("确定", new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int which) {result.confirm();}}).setNeutralButton("取消", new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int which) {result.cancel();}});builder.setOnCancelListener(new DialogInterface.OnCancelListener() {@Overridepublic void onCancel(DialogInterface dialog) {result.cancel();}});// 屏蔽keycode等于84之类的按键,避免按键后导致对话框消息而页面无法再弹出对话框的问题builder.setOnKeyListener(new DialogInterface.OnKeyListener() {@Overridepublic boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {//Log.v("onJsConfirm", "keyCode==" + keyCode + "event="+ event);return true;}});// 禁止响应按back键的事件// builder.setCancelable(false);AlertDialog dialog = builder.create();dialog.show();return true;// return super.onJsConfirm(view, url, message, result);}/*** 覆盖默认的window.prompt展示界面,避免title里显示为“:来自file:”* window.prompt('请输入您的域名地址', '618119.com');*/public boolean onJsPrompt(WebView view, String url, String message,String defaultValue, final JsPromptResult result) {final AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext());builder.setTitle("优然智慧管理系统").setMessage(message);final EditText et = new EditText(view.getContext());et.setSingleLine();et.setText(defaultValue);builder.setView(et).setPositiveButton("确定", new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int which) {result.confirm(et.getText().toString());}}).setNeutralButton("取消", new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int which) {result.cancel();}});// 屏蔽keycode等于84之类的按键,避免按键后导致对话框消息而页面无法再弹出对话框的问题builder.setOnKeyListener(new DialogInterface.OnKeyListener() {public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {//Log.v("onJsPrompt", "keyCode==" + keyCode + "event="+ event);if (keyCode == KeyEvent.KEYCODE_ENTER) {result.confirm(et.getText().toString());dialog.dismiss();return true;}else{return false;}//}});// 禁止响应按back键的事件// builder.setCancelable(false);final AlertDialog dialog = builder.create();//2021-3-18 回车检测et.setOnKeyListener(new View.OnKeyListener() {@Overridepublic boolean onKey(View v, int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_ENTER) {// 监听到回车键,会执行2次该方法。按下与松开result.confirm(et.getText().toString());dialog.dismiss();}return false;}});dialog.show();return true;// return super.onJsPrompt(view, url, message, defaultValue,// result);}/2020-5-15//20240604 文件// For Android < 3.0public void openFileChooser(ValueCallback<Uri> valueCallback) {uploadMessage = valueCallback;openImageChooserActivity();}// For Android >= 3.0public void openFileChooser(ValueCallback valueCallback, String acceptType) {uploadMessage = valueCallback;openImageChooserActivity();}//For Android >= 4.1public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType, String capture) {uploadMessage = valueCallback;openImageChooserActivity();}// For Android >= 5.0@Overridepublic boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {uploadMessageAboveL = filePathCallback;openImageChooserActivity();return true;}}
}
调用浏览
//非常重要cwpd_Web.setWebViewClient(new Cyber_WebviewClient());cwpd_Web.setWebChromeClient(new Cyber_ChromeClient());