Android webview上传图片(调起相册/相机上传)
Posted 码云笔记
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android webview上传图片(调起相册/相机上传)相关的知识,希望对你有一定的参考价值。
概述
默认情况
WebView 不支持<input type=file>,WebView 点击没有反应。
兼容
重写 webview 的 webchromeClient 中的 openFileChooser 方法。android 版本的多样性,就理所当然的各种兼容。
// For Android < 3.0
public void openFileChooser(ValueCallback uploadMsg)
openFileChooser(uploadMsg, "");
//For Android 3.0 - 4.0
public void openFileChooser(ValueCallback uploadMsg, String acceptType)
// For Android 4.0 - 5.0
public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture)
openFileChooser(uploadMsg, acceptType);
// For Android > 5.0
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, FileChooserParams fileChooserParams)
return true;
具体代码实现
网上也有很多实现方式,这边记录一下自己用到的一种
webview 调用时,弹出本地弹框,选择(相册/相机/取消),选择相册跳转到文件选择页面、选择相机注意权限配置,返回照片要做压缩、选择取消注意给webview一个空回应,要不点击没有反应。
- ZpWebChromeClient
-
public class ZpWebChromeClient extends WebChromeClient private OpenFileChooserCallBack mOpenFileChooserCallBack; // For Android < 3.0 public void openFileChooser(ValueCallback uploadMsg) openFileChooser(uploadMsg, ""); //For Android 3.0 - 4.0 public void openFileChooser(ValueCallback uploadMsg, String acceptType) if (mOpenFileChooserCallBack != null) mOpenFileChooserCallBack.openFileChooserCallBack(uploadMsg, acceptType); // For Android 4.0 - 5.0 public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) openFileChooser(uploadMsg, acceptType); // For Android > 5.0 @TargetApi(Build.VERSION_CODES.LOLLIPOP) public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, FileChooserParams fileChooserParams) if (mOpenFileChooserCallBack != null) mOpenFileChooserCallBack.showFileChooserCallBack(filePathCallback, fileChooserParams); return true; public void setOpenFileChooserCallBack(OpenFileChooserCallBack callBack) mOpenFileChooserCallBack = callBack; public interface OpenFileChooserCallBack void openFileChooserCallBack(ValueCallback uploadMsg, String acceptType); void showFileChooserCallBack(ValueCallback filePathCallback, FileChooserParams fileChooserParams);
- ZpWebView
-
public class ZpWebView extends WebView private ZpWebChromeClient webChromeClient; public ZpWebView(Context context) super(context); initWebView(); public ZpWebView(Context context, AttributeSet attrs) super(context, attrs); initWebView(); public ZpWebView(Context context, AttributeSet attrs, int defStyleAttr) super(context, attrs, defStyleAttr); initWebView(); private void initWebView() webChromeClient = new ZpWebChromeClient(); setWebChromeClient(webChromeClient); WebSettings webviewSettings = getSettings(); // 不支持缩放 webviewSettings.setSupportZoom(false); // 自适应屏幕大小 webviewSettings.setUseWideViewPort(true); webviewSettings.setLoadWithOverviewMode(true); String cacheDirPath = getContext().getFilesDir().getAbsolutePath() + "cache/"; webviewSettings.setAppCachePath(cacheDirPath); webviewSettings.setAppCacheEnabled(true); webviewSettings.setDomStorageEnabled(true); webviewSettings.setAllowFileAccess(true); webviewSettings.setAppCacheMaxSize(1024 * 1024 * 8); webviewSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); public void setOpenFileChooserCallBack(ZpWebChromeClient.OpenFileChooserCallBack callBack) webChromeClient.setOpenFileChooserCallBack(callBack);
- MainActivity
-
public class MainActivity extends AppCompatActivity public static final int REQUEST_SELECT_FILE_CODE = 100; private static final int REQUEST_FILE_CHOOSER_CODE = 101; private static final int REQUEST_FILE_CAMERA_CODE = 102; // 默认图片压缩大小(单位:K) public static final int IMAGE_COMPRESS_SIZE_DEFAULT = 400; // 压缩图片最小高度 public static final int COMPRESS_MIN_HEIGHT = 900; // 压缩图片最小宽度 public static final int COMPRESS_MIN_WIDTH = 675; private ValueCallback mUploadMsg; private ValueCallback mUploadMsgs; // 相机拍照返回的图片文件 private File mFileFromCamera; private File mTakePhotoFile; private BottomSheetDialog selectPicDialog; @Override protected void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); private void initView() ZpWebView webView = findViewById(R.id.webview); webView.setOpenFileChooserCallBack(new ZpWebChromeClient.OpenFileChooserCallBack() @Override public void openFileChooserCallBack(ValueCallback uploadMsg, String acceptType) mUploadMsg = uploadMsg; showSelectPictrueDialog(0, null); @Override public void showFileChooserCallBack(ValueCallback filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) if (mUploadMsgs != null) mUploadMsgs.onReceiveValue(null); mUploadMsgs = filePathCallback; showSelectPictrueDialog(1, fileChooserParams); ); /** * 选择图片弹框 */ private void showSelectPictrueDialog(final int tag, final WebChromeClient.FileChooserParams fileChooserParams) selectPicDialog = new BottomSheetDialog(this, R.style.Dialog_NoTitle); selectPicDialog.setOnDismissListener(new DialogInterface.OnDismissListener() @Override public void onDismiss(DialogInterface dialogInterface) if (mUploadMsgs != null) mUploadMsgs.onReceiveValue(null); mUploadMsgs = null; ); View view = LayoutInflater.from(this).inflate(R.layout.dialog_bottom_select_pictrue, null); // 相册 TextView album = view.findViewById(R.id.tv_select_pictrue_album); // 相机 TextView camera = view.findViewById(R.id.tv_select_pictrue_camera); // 取消 TextView cancel = view.findViewById(R.id.tv_select_pictrue_cancel); album.setOnClickListener(new View.OnClickListener() @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public void onClick(View view) if (tag == 0) Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.addCategory(Intent.CATEGORY_OPENABLE); i.setType("*/*"); startActivityForResult(Intent.createChooser(i, "File Browser"), REQUEST_FILE_CHOOSER_CODE); else try Intent intent = fileChooserParams.createIntent(); startActivityForResult(intent, REQUEST_SELECT_FILE_CODE); catch (ActivityNotFoundException e) mUploadMsgs = null; ); camera.setOnClickListener(new View.OnClickListener() @Override public void onClick(View view) takeCameraPhoto(); ); cancel.setOnClickListener(new View.OnClickListener() @Override public void onClick(View view) selectPicDialog.dismiss(); ); selectPicDialog.setContentView(view); selectPicDialog.show(); public void takeCameraPhoto() if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)) Toast.makeText(this, "设备无摄像头", Toast.LENGTH_SHORT).show(); return; String filePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath(); Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); mFileFromCamera = new File(filePath, System.nanoTime() + ".jpg"); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTakePhotoFile)); startActivityForResult(intent, REQUEST_FILE_CAMERA_CODE); else try mTakePhotoFile = File.createTempFile("Zp" + System.nanoTime(), ".jpg", filePath); Uri contentUri = FileProvider.getUriForFile(InnerBrowserActivity.this, "com.zp.demo.ZpFileProvider", mTakePhotoFile); intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); startActivityForResult(intent, REQUEST_FILE_CAMERA_CODE); catch (IOException e) @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) super.onActivityResult(requestCode, resultCode, data); switch (requestCode) case REQUEST_SELECT_FILE_CODE: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) if (mUploadMsgs == null) return; mUploadMsgs.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data)); mUploadMsgs = null; break; case REQUEST_FILE_CHOOSER_CODE: if (mUploadMsg == null) return; Uri result = data == null || resultCode != RESULT_OK ? null : data.getData(); mUploadMsg.onReceiveValue(result); mUploadMsg = null; break; case REQUEST_FILE_CAMERA_CODE: takePictureFromCamera(); break; /** * 处理相机返回的图片 */ @TargetApi(Build.VERSION_CODES.LOLLIPOP) private void takePictureFromCamera() if (mFileFromCamera != null && mFileFromCamera.exists()) String filePath = mFileFromCamera.getAbsolutePath(); // 压缩图片到指定大小 File imgFile = ZpImageUtils.compressImage(this, filePath, COMPRESS_MIN_WIDTH, COMPRESS_MIN_HEIGHT, IMAGE_COMPRESS_SIZE_DEFAULT); Uri localUri = Uri.fromFile(imgFile); Intent localIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, localUri); this.sendBroadcast(localIntent); Uri result = Uri.fromFile(imgFile); if (mUploadMsg != null) mUploadMsg.onReceiveValue(Uri.parse(filePath)); mUploadMsg = null; if (mUploadMsgs != null) mUploadMsgs.onReceiveValue(new Uri[]result); mUploadMsgs = null; else if (mUploadMsg != null) mUploadMsg.onReceiveValue(null); mUploadMsg = null; if (mUploadMsgs != null) mUploadMsgs.onReceiveValue(null); mUploadMsgs = null;
备注:代码不规范的地方,自己抽取一下,这里就不做抽取了。
-
Github 地址
-
WebViewUploadFileDemo
微信小程序excel添加图片
首先要想到微信官方文档给的API,wx.uploadFile( )通过这个API来达到上传至服务器的效果:代码示例如下
接下来我们先来说说上传图片功能,这个比较简单一些
上传图片:wx.chooseImage( )从本地相册选择图片或使用相机拍照
代码示例如下:
在点击图片触发响应事件函数里写上以上代码,就会调起手机选择相册或者拍照。以上就达到了上传图片的功能
上传word/pdf等文件:
这个功能真是苦恼了我好久,因为项目中要用到上传word文件,找度娘查了半天,发现没有调起手机文件管理器去选择文件上传的API。
于是乎,想办法怎么能把这个功能先实现呢?微信官方文档给出了wx.chooseMessageFile(Object object)这个API。
wx.chooseMessageFile · 小程序
这个API是从微信聊天界面中选择文件上传。
选择文件的类型可以自行设置,这里我项目中只要求上传word文件,所以在设置上传文件类型的时候,给type赋值file
触发上传文件按钮点击事件,就会调起微信的聊天界面,如下图:
然后,找到你聊天界面中的文件,
勾选好文件,点击确定。选择文件上传的功能就完成了
注:如果是用模拟器选择微信会话里的文件,调用wx.chooseMessageFile()API,程序会报错。运行到真机上就没问题了 参考技术A 1步 上传附件
电脑浏览器上打开微件夹(uomo.cc),点击上传附件

第2步 复制直达路径

第3步 粘贴直达路径

经过以上三步,我们可以看到微信公众号文章中出现了一些带图标的蓝色文字,文字内容是附件的标题和后缀,这说明已经成功在公众号图文中插入excel表格了。
为了图文排版的完整性及确认表格是否可以下载,需要利用公众号的预览功能进一步确认。点击公众号的预览按钮,发送图文到手机微信上预览。预览图文时,点击附件链接,打开附件查看。



正常情况下,小程序的文件详情页会出现我们的附件,点击查看文件即可下载附件。
以上是关于Android webview上传图片(调起相册/相机上传)的主要内容,如果未能解决你的问题,请参考以下文章
Android webview 上传图片为啥 application/octet-stream