默认情况

WebView 不支持,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

Android WebView 全面干货指南

更多相关文章

  1. android 系统定制的小技巧
  2. Android(安卓)调用系统相机部分源码分析
  3. 获取手机屏幕大小(DisplayMetrics类取得画面宽高)
  4. Android(安卓)Bitmap保存为.bmp格式,图像转化为黑白图片
  5. Android实战(七)------myeclipse发布Android项目-------Android
  6. Android入门教程(二十三)------之Gallery
  7. 基于Android的Word文档阅读器
  8. 【Android】Android之修改app标题与图标
  9. Android 网络通信框架Volley的简单使用

随机推荐

  1. Android prototype Q&A video and transc
  2. Android 简单购物车
  3. 38 Android actionbar 简单使用
  4. android正确使用killProcess完全退出应用
  5. android的四种点击事件的设置
  6. 用Kotlin实现Android点击事件
  7. Android apps应用检查更新代码
  8. Android异常捕获防止崩溃弹框
  9. Android――ContentProvider (一)创建conte
  10. Android ClickableRoundedBackground Spa