美文网首页Android开发
webview支持input标签

webview支持input标签

作者: 陈桐Caliburn | 来源:发表于2019-08-28 14:26 被阅读0次

webview input说明

安卓webview禁用input,网上查看各种方案,都存在弊端。
经过实践,完整可用调研了支持拍照和图片选择上传。

1、webview支持input标签
2、安卓拍照支持适配7.0 takePhoto

1、webview 初始化和销毁

    //webview初始化
    @SuppressLint("SetJavaScriptEnabled")
    public static void initX5Web(WebView x5Webview) {
        Context context = x5Webview.getContext();
        WebSettings webSetting = x5Webview.getSettings();
        webSetting.setJavaScriptEnabled( true );
        webSetting.setAllowFileAccess( true );
        webSetting.setLayoutAlgorithm( WebSettings.LayoutAlgorithm.NARROW_COLUMNS );
        webSetting.setSupportZoom( false );
        webSetting.setBuiltInZoomControls( false );
        webSetting.setDisplayZoomControls(false);   //不显示webview缩放按钮
        webSetting.setUseWideViewPort( true );
        //多窗口问题
        webSetting.setSupportMultipleWindows( false );
        webSetting.setJavaScriptCanOpenWindowsAutomatically( true );

        //h5数据存储
        webSetting.setAppCacheEnabled( true );
        webSetting.setDomStorageEnabled( true );
        webSetting.setDatabaseEnabled(true);
        webSetting.setAppCachePath(context.getDir("appcache", 0).getPath());

        webSetting.setGeolocationEnabled( true );
        webSetting.setAppCacheMaxSize( Long.MAX_VALUE );
        webSetting.setDatabasePath(context.getDir("databases", 0).getPath());
        webSetting.setGeolocationDatabasePath(context.getDir("geolocation", 0).getPath());
        webSetting.setPluginState( WebSettings.PluginState.ON_DEMAND );
        webSetting.setRenderPriority( WebSettings.RenderPriority.HIGH );
        webSetting.setCacheMode( WebSettings.LOAD_NO_CACHE );
        //sonic
        x5Webview.removeJavascriptInterface("searchBoxJavaBridge_");
        webSetting.setAllowContentAccess(true);
        webSetting.setSavePassword(false);
        webSetting.setSaveFormData(false);
        webSetting.setLoadWithOverviewMode(true);
        webSetting.setDefaultTextEncodingName("utf-8");
        webSetting.setLoadsImagesAutomatically(true);
    }

    //webview销毁方法
    public static void onDestroy(WebView mWebView){
        if (mWebView != null) {
            mWebView.clearHistory();
            ((ViewGroup) mWebView.getParent()).removeView(mWebView);
            mWebView.loadUrl("about:blank");
            mWebView.stopLoading();
            mWebView.setWebChromeClient(null);
            mWebView.setWebViewClient(null);
            mWebView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
            mWebView.clearHistory();
            mWebView.destroy();
        }
    }

2、webchrome特别支持

  • 1、 initWebChrome
    //webview input 特别支持帮助类
    private WebViewUploadFileHelper helper = new WebViewUploadFileHelper(this);

    private void initWebChrome() {
        webview.setWebChromeClient( new InputFileWebChromeClient() );
    }

public class InputFileWebChromeClient extends WebChromeClient {
    //设置 进度条
    @Override
    public void onProgressChanged(WebView view, int newProgress) {
        super.onProgressChanged( view, newProgress );
    }

    // For Android < 3.0
    public void openFileChooser(ValueCallback<Uri> uploadMsg) {
        helper.setUploadMessage( uploadMsg );
        permission( () -> {
            helper.openImageActivity();
        } );
    }

    // For Android 3.0+
    public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
        helper.setUploadMessage( uploadMsg );
        permission( () -> {
            helper.openImageActivity( acceptType );
        } );
    }

    // For Android  > 4.1.1
    public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
        helper.setUploadMessage( uploadMsg );
        permission( () -> {
            helper.openImageActivity( acceptType, capture );
        } );
    }

    // For Android  >= 5.0
    public boolean onShowFileChooser(com.tencent.smtt.sdk.WebView webView,
                                     ValueCallback<Uri[]> filePathCallback,
                                     WebChromeClient.FileChooserParams fileChooserParams) {
        helper.setUploadMessageAboveL( filePathCallback );
        permission( () -> {
            helper.openImageActivity( fileChooserParams.getAcceptTypes(), fileChooserParams.isCaptureEnabled() );
        } );
        return true;
    }

    //==多窗口的问题
    @Override
    public boolean onCreateWindow(WebView view, boolean isDialog,
                                  boolean isUserGesture, Message resultMsg) {
        WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
        transport.setWebView( view );
        resultMsg.sendToTarget();
        return true;
    }
}
  • 2 、回调
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
       //回调支持
        super.onActivityResult(requestCode, resultCode, data);
        helper.onActivityResult(requestCode, resultCode, data);
    }
  • 3 、权限
    @SuppressLint("CheckResult")
    public void permission(CallBack callBack){
       // 权限支持
        RxPermissions rxPermissions = new RxPermissions( this );
        rxPermissions.request(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE)
                .subscribe(grant -> {
                    if (grant) {
                        //全部通过
                        try {
                            if (callBack!=null){
                                callBack.onSucess();
                            }
                        } catch (Throwable throwable) {
                            throwable.printStackTrace();
                        }
                    } else {
                            ToastUtils.show("请同意权限");
                    }
                });
    }

    public interface CallBack{
        void onSucess();
    }

3、WebViewUploadFileHelper 帮助类

将input相关方法封装在一个帮助类中,便于多处复用


public class WebViewUploadFileHelper {

    private ValueCallback<Uri> uploadMessage;
    private ValueCallback<Uri[]> uploadMessageAboveL;
    private final static int FILE_CHOOSER_RESULT_CODE = 10011;//文件选择
    private Uri imageUri;
    private Activity activity;

    private WebViewUploadFileHelper() {
    }

    public WebViewUploadFileHelper(Activity activity) {
        this.activity = activity;
    }

    public void setUploadMessage(ValueCallback<Uri> uploadMessage) {
        this.uploadMessage = uploadMessage;
    }

    public void setUploadMessageAboveL(ValueCallback<Uri[]> uploadMessageAboveL) {
        this.uploadMessageAboveL = uploadMessageAboveL;
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode != FILE_CHOOSER_RESULT_CODE) return;

        // 经过上边(1)、(2)两个赋值操作,此处即可根据其值是否为空来决定采用哪种处理方法
        if (uploadMessage != null) {
            chooseBelow( resultCode, data );
        } else if (uploadMessageAboveL != null) {
            chooseAbove( resultCode, data );
        }

    }

    public void openImageActivity() {
        chooseImage( "image/*" );
    }

    public void openImageActivity(String acceptType) {
        chooseImage( acceptType );
    }

    public void openImageActivity(String acceptType, String capture) {
        if (StringUtils.equals( capture, "camera" )) {
            takePhoto();
        } else {
            chooseImage( acceptType );
        }
    }

    public void openImageActivity(String[] acceptType, boolean isCaptureEnabled) {
        if (isCaptureEnabled) {
            takePhoto();
        } else {
            chooseImage( acceptType );
        }
    }

    private void chooseBelow(int resultCode, Intent data) {

        if (RESULT_OK == resultCode) {
            updatePhotos();

            if (data != null) {
                // 这里是针对文件路径处理
                Uri uri = data.getData();
                if (uri != null) {
                    uploadMessage.onReceiveValue( uri );
                } else {
                    uploadMessage.onReceiveValue( null );
                }
            } else {
                // 以指定图像存储路径的方式调起相机,成功后返回data为空
                uploadMessage.onReceiveValue( imageUri );
            }
        } else {
            uploadMessage.onReceiveValue( null );
        }
        uploadMessage = null;
    }

    private void chooseAbove(int resultCode, Intent data) {
        if (RESULT_OK == resultCode) {
            updatePhotos();

            if (data != null) {
                // 这里是针对从文件中选图片的处理
                Uri[] results;
                Uri uriData = data.getData();
                if (uriData != null) {
                    results = new Uri[]{uriData};
                    uploadMessageAboveL.onReceiveValue( results );
                } else {
                    uploadMessageAboveL.onReceiveValue( null );
                }
            } else {
                uploadMessageAboveL.onReceiveValue( new Uri[]{imageUri} );
            }
        } else {
            uploadMessageAboveL.onReceiveValue( null );
        }
        uploadMessageAboveL = null;
    }

    private void updatePhotos() {
        // 该广播即使多发(即选取照片成功时也发送)也没有关系,只是唤醒系统刷新媒体文件
        Intent intent = new Intent( Intent.ACTION_MEDIA_SCANNER_SCAN_FILE );
        intent.setData( imageUri );
        activity.sendBroadcast( intent );
    }

    //调用相机
    private void takePhoto() {
        String fileName = "IMG_" + DateFormat.format( "yyyyMMdd_hhmmss", Calendar.getInstance( Locale.CHINA ) ) + ".jpg";
        // 步骤一:创建存储照片的文件
        String imagePath = activity.getFilesDir() + File.separator + "images" + File.separator + fileName;
        File file = new File( imagePath );
        //创建文件夹
        if (!file.getParentFile().exists())
            file.getParentFile().mkdirs();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            //步骤二:Android 7.0及以上获取文件 Uri
            imageUri = FileProvider.getUriForFile( activity, activity.getPackageName() + ".fileprovider", file );
        } else {
            //步骤三:获取文件Uri
            imageUri = Uri.fromFile( file );
        }

        Intent intent = new Intent();
        intent.addFlags( Intent.FLAG_GRANT_READ_URI_PERMISSION );
        intent.setAction( MediaStore.ACTION_IMAGE_CAPTURE );//设置Action为拍照
        intent.putExtra( MediaStore.EXTRA_OUTPUT, imageUri );//将拍取的照片保存到指定URI
        activity.startActivityForResult( intent, FILE_CHOOSER_RESULT_CODE );
    }

    //图片选择器
    private void chooseImage(String[] acceptType) {
        Intent i = new Intent( Intent.ACTION_GET_CONTENT );
        i.addCategory( Intent.CATEGORY_OPENABLE );
        i.setType( "*/*" );
        i.putExtra( Intent.EXTRA_MIME_TYPES, acceptType );
        activity.startActivityForResult( i, FILE_CHOOSER_RESULT_CODE );
    }

    //图片选择器
    private void chooseImage(String acceptType) {
        Intent i = new Intent( Intent.ACTION_GET_CONTENT );
        i.addCategory( Intent.CATEGORY_OPENABLE );
        if (TextUtils.isEmpty( acceptType )) {
            i.setType( "*/*" );
        } else {
            i.setType( acceptType );
        }
        activity.startActivityForResult( Intent.createChooser( i, "Image Chooser" ), FILE_CHOOSER_RESULT_CODE );
    }

}

相关文章

网友评论

    本文标题:webview支持input标签

    本文链接:https://www.haomeiwen.com/subject/rhwpectx.html