一次Android WebView使用的苦逼体验之旅

原创 2016年06月02日 00:07:28

有时候有这么样的需求,我们想在自己的原生android app中嵌入其它功能模块,而这些模块的实现往往早就有BS模式的了,所以简单期间,直接拿过来用吧。

多亏了webView控件,让我们的app可以充当浏览器的功能浏览网页,如果网页已经是屏幕自适应的(各种框架bootstrap啊,amazeui啊,不拉不拉不拉的),那么效果更好!


那么问题来了,我们要怎么使用webView呢?

版本1:

【首先webView控件准备好,其次<uses-permission android:name="android.permission.INTERNET" /> 也不要忘了!】

WebView webView= (WebView) findViewById(R.id.webview);
webView.loadUrl(http://www.baidu.com);

哈哈哈哈,代码太简单了,是不是马上就有效果了得意

高兴得太早了!

怎么有些按钮点了没效果,网页显示出来好像和预想的差太多!!!!

版本2:【添加一些设置项】

 //允许JS执行

webView.getSettings().setJavaScriptEnabled(true);

类似的还有如下这些设置【用到的时候查文档吧!】

//设置WebView的一些缩放功能点
webView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
webView.setHorizontalScrollBarEnabled(false);
webView.getSettings().setSupportZoom(true);
//设置WebView可触摸放大缩小
webView.getSettings().setBuiltInZoomControls(true);
webView.setInitialScale(70);
webView.setHorizontalScrollbarOverlay(true);
//WebView双击变大,再双击后变小,当手动放大后,双击可以恢复到原始大小
//webView.getSettings().setUseWideViewPort(true);
//提高渲染的优先级
webView.getSettings().setRenderPriority(RenderPriority.HIGH);
//把图片加载放在最后来加载渲染
//webView.getSettings().setBlockNetworkImage(true);
//用WebView将字符串以HTML的形式显示出来
webView.loadDataWithBaseURL("fake://not/needed", <p>zzz</p>, "text/html", "utf-8", "");

//listview,webview中滚动拖动到顶部或者底部时的阴影
webView.setOverScrollMode(View.OVER_SCROLL_NEVER);
webView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);//使用缓存
WebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE); //默认不使用缓存!
webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY); //取消滚动条白边效果

好了,大致满足我们的需求了。

等等,怎么点击超链接都是用的外部浏览器打开的啊,我还是想继续用webView打开!!!

下面介绍一个东西:webview.setWebViewClient(new WebViewClient());

WebViewClient就是帮助WebView处理各种通知、请求事件的,我们可以自定义WebViewClient,并重写里面的方法

常见的如下:

版本3:

webview1.setWebViewClient(new WebViewClient()
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
         view.loadUrl(url);
         return true;
     }

);
当点击超链接时会触发该方法,返回true表明还是在webView中进行跳转不会跳到浏览器打开!

等等,我的页面有个按钮不起作用了:

<a href="tel:110">110报警!</a>

试了一下用浏览器打开可以直接掉出拨号软件,怎么放到webView中就GG了呢?

版本4:

   webview1.setWebViewClient(new MyWebViewClient());

    //自定义 WebViewClient 辅助WebView设置处理关于页面跳转,页面请求等操作
    private class MyWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            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{
                view.loadUrl(url);
            }
            return true;
        }
    }

这样就可以控制tel协议了。

既然到了这一步其实还可以做更多控制,比如我就遇到过这种:有一个按钮对应的超链接偏偏就不要用webView打开,而是用手机自带的浏览器打开!

【具体原因就不细说了,总之就是webView和浏览器还是有一定的差距的,正好我当时要实现的东西就被卡在那个节骨眼上了。。。。。】

不过处理起来也不是很难:

版本5:

   webview1.setWebViewClient(new MyWebViewClient());

//自定义 WebViewClient 辅助WebView设置处理关于页面跳转,页面请求等操作【处理tel协议和视频通讯请求url的拦截转发】
    private class MyWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            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://domainName: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;
        }
    }
其实就是利用了这条url和其它url相比的独特性大笑(端口号不同),当然大家可能遇到的情况得根据实际情况来定。

写到这里是不是就玩完了呢?

no no no,好戏还在后头!

玩着玩着发现又有问题了,又有一个按钮不起作用。。。。。。

<input type="file">文件上传</input>

我的天哪,怎么总是有这么多破事。

下面再介绍一个东西

webView.setWebChromeClient(new WebChromeClient());

说明:WebChromeClient主要辅助WebView处理Javascript的对话框、网站图标、网站title、加载进度等比等,不过它还能处理文件上传操作

下面借用一下别人的代码:.

版本6:

webView.setWebChromeClient(new MyChromeWebClient());

//自定义 WebChromeClient 辅助WebView处理图片上传操作【<input type=file> 文件上传标签】
    public class MyChromeWebClient extends WebChromeClient {
        // For Android 3.0-
        public void openFileChooser(ValueCallback<Uri> uploadMsg) {
            Log.d(TAG, "openFileChoose(ValueCallback<Uri> uploadMsg)");
            mUploadMessage = uploadMsg;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("*/*");
            MainActivity.this.startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
        }

        // For Android 3.0+
        public void openFileChooser( ValueCallback uploadMsg, String acceptType ) {
            Log.d(TAG, "openFileChoose( ValueCallback uploadMsg, String acceptType )");
            mUploadMessage = uploadMsg;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("*/*");
            MainActivity.this.startActivityForResult(
                    Intent.createChooser(i, "File Browser"),
                    FILECHOOSER_RESULTCODE);
        }
        //For Android 4.1
        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
            Log.d(TAG, "openFileChoose(ValueCallback<Uri> uploadMsg, String acceptType, String capture)");
            mUploadMessage = uploadMsg;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("*/*");
            MainActivity.this.startActivityForResult( Intent.createChooser( i, "File Browser" ), MainActivity.FILECHOOSER_RESULTCODE );
        }
        // For Android 5.0+
        public boolean onShowFileChooser (WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
            Log.d(TAG, "onShowFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture)");
            mUploadCallbackAboveL = filePathCallback;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("*/*");
            MainActivity.this.startActivityForResult(
                    Intent.createChooser(i, "File Browser"),
                    FILECHOOSER_RESULTCODE);
            return true;
        }
    }


最后来个大杂烩吧:

版本7:

public class MainActivity extends AppCompatActivity{
    private final static String TAG = "MainActivity";
    private WebView webView;
    private ValueCallback<Uri> mUploadMessage;
    private ValueCallback<Uri[]> mUploadCallbackAboveL;
    private final static int FILECHOOSER_RESULTCODE = 1;
    private final static String url = "http://xxxx.com";
    
    //初始化webView
    private void initWebView(){
        //从布局文件中扩展webView
        webView=(WebView)this.findViewById(R.id.webView);
        WebSettings settings = webView.getSettings();
        settings.setUseWideViewPort(true);
        settings.setLoadWithOverviewMode(true);
        settings.setDefaultTextEncodingName("UTF-8");
        //开启JavaScript支持
        settings.setJavaScriptEnabled(true);
        // 支持缩放
        settings.setSupportZoom(true);
        //辅助WebView设置处理关于页面跳转,页面请求等操作
        webView.setWebViewClient(new MyWebViewClient());
        //辅助WebView处理图片上传操作
        webView.setWebChromeClient(new MyChromeWebClient());
        //加载地址
        webView.loadUrl(url);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initWebView();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode==FILECHOOSER_RESULTCODE)
        {
            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;
            }
        }
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void onActivityResultAboveL(int requestCode, int resultCode, Intent data) {
        if (requestCode != FILECHOOSER_RESULTCODE
                || mUploadCallbackAboveL == null) {
            return;
        }

        Uri[] results = null;
        if (resultCode == Activity.RESULT_OK) {
            if (data == null) {

            } 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;
        return;
    }

    //自定义 WebViewClient 辅助WebView设置处理关于页面跳转,页面请求等操作【处理tel协议和视频通讯请求url的拦截转发】
    private class MyWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            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;
        }
    }

    //自定义 WebChromeClient 辅助WebView处理图片上传操作【<input type=file> 文件上传标签】
    public class MyChromeWebClient extends WebChromeClient {
        // For Android 3.0-
        public void openFileChooser(ValueCallback<Uri> uploadMsg) {
            Log.d(TAG, "openFileChoose(ValueCallback<Uri> uploadMsg)");
            mUploadMessage = uploadMsg;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("*/*");
            MainActivity.this.startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
        }

        // For Android 3.0+
        public void openFileChooser( ValueCallback uploadMsg, String acceptType ) {
            Log.d(TAG, "openFileChoose( ValueCallback uploadMsg, String acceptType )");
            mUploadMessage = uploadMsg;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("*/*");
            MainActivity.this.startActivityForResult(
                    Intent.createChooser(i, "File Browser"),
                    FILECHOOSER_RESULTCODE);
        }
        //For Android 4.1
        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
            Log.d(TAG, "openFileChoose(ValueCallback<Uri> uploadMsg, String acceptType, String capture)");
            mUploadMessage = uploadMsg;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("*/*");
            MainActivity.this.startActivityForResult( Intent.createChooser( i, "File Browser" ), MainActivity.FILECHOOSER_RESULTCODE );
        }
        // For Android 5.0+
        public boolean onShowFileChooser (WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
            Log.d(TAG, "onShowFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture)");
            mUploadCallbackAboveL = filePathCallback;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("*/*");
            MainActivity.this.startActivityForResult(
                    Intent.createChooser(i, "File Browser"),
                    FILECHOOSER_RESULTCODE);
            return true;
        }
    }
}


参考

http://blog.saymagic.cn/2015/11/08/webview-upload.html?utm_source=tuicool&utm_medium=referral

版权声明:本文为博主原创文章,未经博主允许不得转载。

Android:最全面的 Webview 详解

前言 现在很多App里都内置了Web网页(Hyprid App),比如说很多电商平台,淘宝、京东、聚划算等等,如下图 那么这种该如何实现呢?其实这是Android里一个叫WebView的组件实现的。今...
  • carson_ho
  • carson_ho
  • 2016年09月28日 19:58
  • 102430

WebView详解与简单实现Android与H5互调

混合开发就是在一个App中内嵌一个轻量级的浏览器,一部分原生的功能改为Html 5来开发。 优势:使用H5实现的功能能够在不升级App的情况下动态更新,而且可以在Android或iOS的App上同时运...
  • qq_24530405
  • qq_24530405
  • 2016年10月13日 16:41
  • 24943

安卓webview的一些坑

WebView可以很好地帮助我们展示html页面,但是webview使用不当的话还是可能产生一定问题的,下面就以下几个方面说说我的优化技巧 1、展示webview的activity可以另开一个进程...
  • hytfly
  • hytfly
  • 2015年09月16日 09:29
  • 13478

Android WebView 详解

本文记录 Android 中 WebView 控件的相关使用,不断完善中…主要包括: 基本属性的配置 WebView 缓存相关内容 Java 与 Js 的交互 WebView 打开本地应用(支付宝等)...
  • chendong_
  • chendong_
  • 2017年07月15日 12:53
  • 572

Android WebView 开发详解(一)

详细介绍Android WebView开发,介绍WebView开发各个注意事项及其解决方法。
  • typename
  • typename
  • 2014年09月07日 01:17
  • 120038

android WebView总结

浏览器控件是每个开发环境都具备的,这为马甲神功提供了用武之地,windows的有webbrowser,android和ios都有webview。只是其引擎不同,相对于微软的webbrowser,and...
  • chenshijun0101
  • chenshijun0101
  • 2011年12月06日 11:37
  • 152920

android设置webview的适配比例,setInitialScale 方法神奇的功能

android webview setInitialScale 方法神奇的功能.  web.setInitialScale(25);//为25%,最小缩放等级          解释:  里面的数...
  • huohu1007
  • huohu1007
  • 2016年05月16日 11:15
  • 3008

android WebView设置setInitialScale(...)后,修改设置的值,问题解决

  • 2013年03月13日 12:52
  • 55KB
  • 下载

Android 关于WebView全方面的使用

相关类介绍     ·          ·        WebResourceRequest ·        添加于API21,封装了一个Web资源的请求信息,包含:请求地址,请求方法,请求...
  • u011275280
  • u011275280
  • 2017年12月06日 14:51
  • 194

android webview中上传控件点击无效的解决办法

一、介绍 当我们在使用webview控件打开一个web网页时,如果we页面中带有的控件,在webview中能正常显示这个上传控件,但是你会发现无论你如何点击都无效果,这个是很让人恼火的,一时也不知道...
  • ATangSir
  • ATangSir
  • 2016年05月13日 00:09
  • 7168
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:一次Android WebView使用的苦逼体验之旅
举报原因:
原因补充:

(最多只允许输入30个字)