bluejww

android-webview开发中的各种使用方法(持续更,尽量全)

  最新坑A:(没看过的可以从下面开始处看起):  测试部门测出来一个坑,当多次点击退出后,会出现app崩溃现象,报如下错误:

java.lang.IllegalArgumentException: Receiver not registered: android

  经过四处查资料,才知道这是android系统里的一个bug.这些咱都不管,只说解决办法,各种查找,找到如下办法,在webview所在Acitivity的onDestory()方法中加入如下方法。

@Override
	protected void onDestroy() {
		super.onDestroy();
		infoWebView.setVisibility(View.GONE);
		
	}

  解决原理好像是不让zoombutton什么的显示,反正我也不清楚就这样解决了。

 

  开始:不知道你有没有注意,最近的app中越来越多的使用webview了,个人感觉,一方面是因为微信公众号开发增多的促进,让很多页面开发后用到微信上面后,还要吣在公司的app中使用,又加上html5的进一步火热,可以跨平台使用,一次开发,可以用在Ios,android客户端上,这样,极大的节省了公司的开发成本,缩小了开发周期,让公司的产品可以进快的投入市场中,在与同类产品竞争中拔得一个先机。同时,在一个页面中,想要做一个广告活动,也不必像原生控件写的app那样必须升级,让用户体验非常之不好,只要在页面中加上一个链接就可以了,就是这么简单,就是这么esay。至于目前在app内嵌html页面最大的掣肘,可能个人感觉还是中国移动,中国联通,与中国电信三家公司,试想,如果有一天,我们的移动网络可以普遍的像pc互联网一样高速,低费用,那么,我感觉那时就是html5的天下了。

  所以,html5的学习,应该被广大安卓开发提上日程,试想,如果一个安卓开发人员,同时又精通html5,是不是可以给你所在的公司节省一名专门的开发人员,是不是要节省一大笔工资开销,那这节省下来的工资开销怎么着是不是也要分给你点。同时,在你找工作时,会html5至少可以为你的薪资在你期望薪资的基础上提高20个百  

分点。

  目前我也打算开始学习html5了,不过之前在做安卓开发中,也有内嵌了一些网页,用了webview,则在此先总结下,此控件的一些常用方法。费话不多说,开始。

  1.webview控件的使用:在layout的布局文件中,如同常用的安卓原生控件一样的使用,如listview,textview,button等。 

 <WebView
        android:id="@+id/wv_page"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerHorizontal="true" />

  2.在java代码中初始化:

WebView infoWebView= (WebView) findViewById(R.id.wv_page);  

  3.设置webview的屏幕适配:有自己的理解,也有参考:http://www.cnblogs.com/bluestorm/archive/2013/04/15/3021996.html

 1 //a方法
 2 WebSettings settings = webView.getSettings(); 
 3 settings.setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN); 
 4 //LayoutAlgorithm是一个枚举用来控制页面的布局,有三个类型:
 5 //1.NARROW_COLUMNS:可能的话使所有列的宽度不超过屏幕宽度
 6 //2.NORMAL:正常显示不做任何渲染
 7 //3.SINGLE_COLUMN:把所有内容放大webview等宽的一列中
 8 //用SINGLE_COLUMN类型可以设置页面居中显示,页面可以放大缩小,但这种方法不怎么
 9 //好,有时候会让你的页面布局走样而且我测了一下,只能显示中间那一块,超出屏幕的部分
10 //都不能显示。
11 
12 
13 //b:加上这两句基本上就可以做到屏幕适配了
14 infoWebView.getSettings().setUseWideViewPort(true);
15 infoWebView.getSettings().setLoadWithOverviewMode(true);
16 
17 //c:(主要用于平板,针对特定屏幕代码调整分辨率)
18     DisplayMetrics metrics = new DisplayMetrics();
19     getWindowManager().getDefaultDisplay().getMetrics(metrics);
20     int mDensity = metrics.densityDpi;
21 
22 
23     if (mDensity == 120) {
24               settings.setDefaultZoom(ZoomDensity.CLOSE);
25           }else if (mDensity == 160) {
26               settings.setDefaultZoom(ZoomDensity.MEDIUM);
27           }else if (mDensity == 240) {
28               settings.setDefaultZoom(ZoomDensity.FAR);
29           } 

 4.设置html页面定位的支持

1 infoWebView.getSettings.setGeolocationEnabled(true);  
2 //同时也要在清单文件里设置定位的权限支持
3 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
4     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />  

  如今,页面中包含js的情况也很多,所以要添加对js功能的支持

1 infoWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
2 infoWebView.getSettings().setBuiltInZoomControls(true);

  5.当要对网页内的源码进行解析功能时,要加上:

1 infoWebView.getSettings().setDomStorageEnabled(true);

  6.当页面有拨打电话号码功能时(电话号已经显示的那种),可以用如下代码判断

 1 wv_page.setWebViewClient(new WebViewClient() {
 2 
 3                 @Override
 4                 public boolean shouldOverrideUrlLoading(WebView view, String url) {
 5                     if (url.startsWith("tel")) {
 6                         Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
 7                         startActivity(intent);
 8                     } else if (url.startsWith("http:") || url.startsWith("https:")) {
 9                         view.loadUrl(url);
10                     }
11                     return true;
12                 }
13 
14             }); 

  7.当你要设置html页面的返回键点击后返回上一层页面,而不是 退出当前activity,可以加上如下代码 

 1 @Override
 2     public boolean onKeyDown(int keyCode, KeyEvent event) {
 3         // 设置webview页面时设置后退时,回退到上一web页面。
 4         if (keyCode == KeyEvent.KEYCODE_BACK && infoWebView.canGoBack()) {
 5             infoWebView.goBack();
 6             if (View.VISIBLE == shareRel.getVisibility()) {
 7                 shareRel.setVisibility(View.GONE);
 8             }
 9             return true;
10         }
11         return super.onKeyDown(keyCode, event);
12     }  

  8.若要在当前activity的webview中加载url,而不是跳转到手机别的浏览器中,可以在代码中添加如下代码: 

1 infoWebView.setWebViewClient(new WebViewClient() {
2 
3             @Override
4             public boolean shouldOverrideUrlLoading(WebView view, String url) {
5                 // TODO 设置不加载外面的浏览器
6                 view.loadUrl(url);
7                 return true;
8             }
  } 

  9.webViewClient中有一些方法,可以用来对webview加载的状态等的一些监听,等功能,如可以用来判断一个页面加载前,后

 1 infoWebView.setWebViewClient(new WebViewClient() {
 2 
 3             @Override
 4             public boolean shouldOverrideUrlLoading(WebView view, String url) {
 5                 // TODO 设置不加载外面的浏览器
 6                 view.loadUrl(url);
 7                 return true;
 8             }
 9 
10             @Override
11             public void onPageStarted(WebView view, String url, Bitmap favicon) {
12                 // TODO Auto-generated method stub
13                 super.onPageStarted(view, url, favicon);
14                 LogUtil.debug(activity.class, "get start url地址----------:" + infoWebView.getUrl());
15           //这里可以用来判断页面加载前的url地址,等 ,也可以在这里来启动一个progressbar,用来显示正在加载。
16             }
17 
18             @Override
19             public void onPageFinished(WebView view, String url) {
20                 super.onPageFinished(view, url);
           //这里是webview加载结束时调用的,可以在这里结束前面设置的一个progressbar.
            //也可以做一些别的功能的处理,如得到源码中的一些数据,下面会详细说下。
21 } 22 } 

  从这里开始都是一些比较含坑的方法了,老纳也是静心苦经书,才有点体会。

  10.对源码进行一些解析。首先,如果项目对安全性要求不高的话,可以用第三方的库,josup.但当页面中有一些sesson权限的操作时,这种方法就有点不知道还能不能用了。

  josup的jar包,还是我的360网盘 JSOUP 访问密码 4e3d 

  josup的详细使用方法:啦啦啦

  简单的说下,jsoup的解析可以实现两种,一种是对本地的html文件的解析。另一种是对url的解析,具体的方法上面都很清楚。不过,有时对非jsp页面的解析好像支持的不太好,本次开发中就遇到了这种情况,让我着实的无语了很长时间,才导致了下面的方法的查找。

 

   11.通过webview本身的infoWebView.load()方法进行一些document解析方法,来进行解析。

  example:a得到全部的html源码的方法:

1 //1先在class类中定义一个内部类(非内部类应该也可以,没有试)
2 public class InCalssForHtml{
3       public void showHtmlStr(String html){
4          //在这里打下log就行了。
5      }
6 
7 }
8 //下面当js解析出来网页源码时,就会回调用此类中的方法,并将数据传入。

  然后在

webRecruits.setWebViewClient(new WebViewClient(){
   
         
        @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                
 //1,先创建上面定义方法的对象
    InClassForHtml inForHtml = new InClassForHtml();
//添加js接口支持
infoWebView.addJavascriptInterface(inForHtml , "getHtml");

//通过webview.load();方法来进行源码解析,并返回string类型的数据
view.loadUrl("javascript:window.getHtml.showHtmlStr('<head>'+" +
                    "document.getElementsByTagName('html')[0].innerHTML+'</head>');");
                LogUtil.debug(RecruitsTestActivity.this, "加载完成后的url-----------"+url);
            }
            
        });
//注意,view.loadUrl()中的window.getHtml(与上面添加接口支持的第
//二个参数相同,用来代码本地类对象).showHtmlStr(与本地类中的方法
//名要相同。)
//这样,解析后会自动调用本地类中的方法,并把string类型的源码回调

 

  12.对title的二种获得方式

 

 1     //方法1(多用这种)
 2     infoWebView.setWebViewClient(new WebViewClient() {
 3         @Override
 4         public void onPageFinished(WebView view, String url) {
 5             super.onPageFinished(view, url);
 6             
 7             String title = infoWebView.getTitle();
 8         }
 9     }
10      
12     //方法2
13     public class InJavaSetTitle {
14         public void setTetle(String title) {
15             Log.d("title"+title);
16         }
17 }
18     //onPageFinished()方法中
19     InJavaSetTitle inJST = new InJavaSetTitle();
20     
21     infoWebView.addJavascriptInterface(inJST, "get_title");
22     view.loadUrl("javascript:window.get_title.setTetle("
23             + "document.getElementsByTagName('title')[0].innerHTML);");
24 
25     //方法3,不常用,就不写了。主要还是用方法一。
26     

 

  13.对html源码中的标签进行获取,对标签中的属性值进行获取

 

//比如,要得到属性name="type"的<input  xxxxxxxxxxxxxxxxxxxx>标签中的value
//值,取得方法如下
02-24 15:11:13.440: D/InformationActivity(24499): <script type="text/javascript" src="js/jweixin-1.0.0.js"></script>
02-24 15:11:13.440: D/InformationActivity(24499): 	<input type="hidden" name="cardId" value="241">
02-24 15:11:13.440: D/InformationActivity(24499): 	<input type="hidden" name="type" value="02">
02-24 15:11:13.440: D/InformationActivity(24499): 	<input id="listPicUrl" type="hidden" name="listPicUrl" value="http:/xxxxxxooooe.com.cn/map/images/weixin_share_card.png">
02-24 15:11:13.440: D/InformationActivity(24499): 	<input id="title" type="hidden" name="title" value="国庆节贺卡">

      //a
	public class InJavaScriptLocalObj {
		public void showSource(String html) {
			Log.e(tag, html);
			//"type----xxxxx",
		}
	}
	//b.创建对象
	InJavaScriptLocalObj ijslo = new InIjavaScriptLocalObj();
	infoWebView.addJavascriptInterface(ijslo, "local_obj");// 用来得到网页源代码
	// c.这句在onPageFinish方法中。type走完这一步,就会把结果传给上面a中定义的方法,这时可以通过截取结果的方式,进行操作。结果形式"type----xxxxx",
	//如果不加下面语句中的'type'+'----'这点,传递的就只有"xxxxx",
	view.loadUrl("javascript:window.local_obj.showSource('type'+'----'+"
			+ "document.querySelector('input[name=\"type\"]').getAttribute('value')" + ");");

  14.当html网页中有alter弹框时,有时会弹不内容,要加上下面这句话。

	 webRecruits.setWebChromeClient(new WebChromeClient() {
		 @Override
		 public boolean onJsAlert(WebView view, String url, String message,
		 JsResult result) {
		 //加这段可以证webview中的alert弹出来
		 return super.onJsAlert(view, url, message, result);
		 }
		 });

  14.续,另外可以在android中定义弹框的类型,代替默认的.

可以看看这篇博客:噶噶噶

  15.另外,其实可以在js中定义接口方法,然后调用安卓本地写的一些方法,个人觉得这篇文章写的不错,自己就不写了。

这篇:呵呵呵

 

  16.最后就是一个大坑,当apk签名后,会造成js代码无法调用本地定义的类,与类中的方法,而导致的无法到解析数据。

方法就是对这定义的类与方法进行不混淆设置。

-keep public class <Package Name>.MainActivity$InJavaScriptLocalObj{
    public void showSource(java.lang.String);
}
//.MainAcitivy是指的,当前存放定义返回数据接口InJavaScriptLocalObj的类名如果是独立的类,
//就不用加MainAcitivy类直接写后面的就行,$后的是接口类名InJavaScriptLocalObj

  好了,就写这么多吧。

 

posted on 2016-02-17 10:11  bluejww  阅读(12268)  评论(0编辑  收藏  举报

导航