android-webview開發中的各類使用方法(持續更,儘可能全)

  最新坑A:(沒看過的能夠從下面開始處看起):  測試部門測出來一個坑,當屢次點擊退出後,會出現app崩潰現象,報以下錯誤:javascript

java.lang.IllegalArgumentException: Receiver not registered: android

  通過四處查資料,才知道這是android系統裏的一個bug.這些咱都無論,只說解決辦法,各類查找,找到以下辦法,在webview所在Acitivity的onDestory()方法中加入以下方法。html

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

  解決原理好像是不讓zoombutton什麼的顯示,反正我也不清楚就這樣解決了。html5

 

  開始:不知道你有沒有注意,最近的app中愈來愈多的使用webview了,我的感受,一方面是由於微信公衆號開發增多的促進,讓不少頁面開發後用到微信上面後,還要唚在公司的app中使用,又加上html5的進一步火熱,能夠跨平臺使用,一次開發,能夠用在Ios,android客戶端上,這樣,極大的節省了公司的開發成本,縮小了開發週期,讓公司的產品能夠進快的投入市場中,在與同類產品競爭中拔得一個先機。同時,在一個頁面中,想要作一個廣告活動,也沒必要像原生控件寫的app那樣必須升級,讓用戶體驗很是之很差,只要在頁面中加上一個連接就能夠了,就是這麼簡單,就是這麼esay。至於目前在app內嵌html頁面最大的掣肘,可能我的感受仍是中國移動,中國聯通,與中國電信三家公司,試想,若是有一天,咱們的移動網絡能夠廣泛的像pc互聯網同樣高速,低費用,那麼,我感受那時就是html5的天下了。java

  因此,html5的學習,應該被廣大安卓開發提上日程,試想,若是一個安卓開發人員,同時又精通html5,是否是能夠給你所在的公司節省一名專門的開發人員,是否是要節省一大筆工資開銷,那這節省下來的工資開銷怎麼着是否是也要分給你點。同時,在你找工做時,會html5至少能夠爲你的薪資在你指望薪資的基礎上提升20個百  android

分點。web

  目前我也打算開始學習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

  好了,就寫這麼多吧。

相關文章
相關標籤/搜索