最新坑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
好了,就寫這麼多吧。