欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android WebView使用方法詳解 附j(luò)s交互調(diào)用方法

 更新時間:2021年04月22日 08:54:54   作者:星空武哥  
這篇文章主要為大家詳細(xì)介紹了Android WebView使用方法詳解,文中附j(luò)s交互調(diào)用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下

目前很多Android app都內(nèi)置了可以顯示web頁面的界面,會發(fā)現(xiàn)這個界面一般都是由一個叫做WebView的組件渲染出來的,學(xué)習(xí)該組件可以為你的app開發(fā)提升擴(kuò)展性。

先說下WebView的一些優(yōu)點(diǎn):

--可以直接顯示和渲染web頁面,直接顯示網(wǎng)頁
--webview可以直接用html文件(網(wǎng)絡(luò)上或本地assets中)作布局
--和JavaScript交互調(diào)用
 

一、基本使用

首先layout中即為一個基本的簡單控件:

<WebView
 android:id="@+id/webView1"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:layout_marginTop="10dp" />

同時,因?yàn)橐吭L問網(wǎng)絡(luò),所以manifest中必須要加uses-permission:

<uses-permission android:name="android.permission.INTERNET"/>

在activity中即可獲得webview的引用,同時load一個網(wǎng)址:

webview = (WebView) findViewById(R.id.webView1);
webview.loadUrl("http://www.baidu.com/");
//webview.reload();// reload page

這個時候發(fā)現(xiàn)一個問題,啟動應(yīng)用后,自動的打開了系統(tǒng)內(nèi)置的瀏覽器,解決這個問題需要為webview設(shè)置 WebViewClient,并重寫方法:

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

若自己定義了一個頁面加載進(jìn)度的progressbar,需要展示給用戶的時候,可以通過如下方式獲取webview內(nèi)頁面的加載進(jìn)度:

webview.setWebChromeClient(new WebChromeClient(){
 @Override
 public void onProgressChanged(WebView view, int newProgress) {
 //get the newProgress and refresh progress bar
 }
 });

每個頁面,都有一個標(biāo)題,比如www.baidu.com這個頁面的title即“百度一下,你就知道”,那么如何知道當(dāng)前webview正在加載的頁面的title呢:

webview.setWebChromeClient(new WebChromeClient(){
 @Override
 public void onReceivedTitle(WebView view, String title) {
 titleview.setText(title);//a textview
 }
 });

二、通過webview控件下載文件

通常webview渲染的界面中含有可以下載文件的鏈接,點(diǎn)擊該鏈接后,應(yīng)該開始執(zhí)行下載的操作并保存文件到本地中。webview來下載頁面中的文件通常有兩種方式:

1. 自己通過一個線程寫java io的代碼來下載和保存文件(可控性好)

2. 調(diào)用系統(tǒng)download的模塊(代碼簡單)

方法一:

首先要寫一個下載并保存文件的線程類

public class HttpThread extends Thread {


 private String mUrl;

 public HttpThread(String mUrl) {
 this.mUrl = mUrl;
 }
 
 @Override
 public void run() {
 URL url;
 try {
 url = new URL(mUrl);
 HttpURLConnection conn = (HttpURLConnection) url.openConnection();
 conn.setDoInput(true);
 conn.setDoOutput(true);
 InputStream in = conn.getInputStream();
 
 File downloadFile;
 File sdFile;
 FileOutputStream out = null;
 if(Environment.getExternalStorageState().equals(Environment.MEDIA_UNMOUNTED)){
 downloadFile = Environment.getExternalStorageDirectory();
 sdFile = new File(downloadFile, "test.file");
 out = new FileOutputStream(sdFile);
 }
 
 //buffer 4k
 byte[] buffer = new byte[1024 * 4];
 int len = 0;
 while((len = in.read(buffer)) != -1){
 if(out != null)
 out.write(buffer, 0, len);
 }
 
 //close resource
 if(out != null)
 out.close();
 
 if(in != null){
 in.close();
 }
 
 
 
 } catch (IOException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 }
 }
 
}

隨后要實(shí)現(xiàn)一個DownloadListener接口,這個接口實(shí)現(xiàn)方法OnDownloadStart(),當(dāng)用戶點(diǎn)擊一個可以下載的鏈接時,該回調(diào)方法被調(diào)用同時傳進(jìn)來該鏈接的URL,隨后即可以對該URL塞入HttpThread進(jìn)行下載操作:

//創(chuàng)建DownloadListener (webkit包)
class MyDownloadListenter implements DownloadListener{

 @Override
 public void onDownloadStart(String url, String userAgent,
 String contentDisposition, String mimetype, long contentLength) {
 System.out.println("url ==== >" + url);
 new HttpThread(url).start();
 }
 
 }

//給webview加入監(jiān)聽
webview.setDownloadListener(new MyDownloadListenter());

方法二:

直接發(fā)送一個action_view的intent即可:

class MyDownloadListenter implements DownloadListener{

 @Override
 public void onDownloadStart(String url, String userAgent,
 String contentDisposition, String mimetype, long contentLength) {
 System.out.println("url ==== >" + url);
 //new HttpThread(url).start();
 
 Uri uri = Uri.parse(url);
 Intent intent = new Intent(Intent.ACTION_VIEW, uri);
 startActivity(intent);
 }
 
 }

三、錯誤處理

當(dāng)我們使用瀏覽器的時候,通常因?yàn)榧虞d的頁面的服務(wù)器的各種原因?qū)е赂鞣N出錯的情況,最平常的比如404錯誤,通常情況下瀏覽器會提示一個錯誤提示頁面。事實(shí)上這個錯誤提示頁面是瀏覽器在加載了本地的一個頁面,用來提示用戶目前已經(jīng)出錯了。

但是當(dāng)我們的app里面使用webview控件的時候遇到了諸如404這類的錯誤的時候,若也顯示瀏覽器里面的那種錯誤提示頁面就顯得很丑陋了,那么這個時候我們的app就需要加載一個本地的錯誤提示頁面,即webview如何加載一個本地的頁面。

1. 首先我們需要些一個html文件,比如error_handle.html,這個文件里面就是當(dāng)出錯的時候需要展示給用戶看的一個錯誤提示頁面,盡量做的精美一些。然后將該文件放置到代碼根目錄的assets文件夾下。

2. 隨后我們需要復(fù)寫WebViewClient的onRecievedError方法,該方法傳回了錯誤碼,根據(jù)錯誤類型可以進(jìn)行不同的錯誤分類處理

webview.setWebViewClient(new WebViewClient(){
 
 @Override
 public void onReceivedError(WebView view, int errorCode,
 String description, String failingUrl) {
 switch(errorCode)
 {
 case HttpStatus.SC_NOT_FOUND:
 view.loadUrl("file:///android_assets/error_handle.html");
 break;
 }
 }
 });

其實(shí),當(dāng)出錯的時候,我們可以選擇隱藏掉webview,而顯示native的錯誤處理控件,這個時候只需要在onReceivedError里面顯示出錯誤處理的native控件同時隱藏掉webview即可。

四、webview同步cookies

cookies是服務(wù)器用來保存每個客戶的常用信息的,下次客戶進(jìn)入一個諸如登陸的頁面時服務(wù)器會檢測cookie信息,如果通過則直接進(jìn)入登陸后的頁面。

在webview中,如果之前已經(jīng)登陸過了,那么下次再進(jìn)入同樣的登陸界面時,若需要再次登陸的話,一定會很惱人,所以這里提供一個webview同步cookies的方法。 

1.首先,我們假設(shè)某個網(wǎng)站的登陸界面需要提供兩個參數(shù),一個是name,一個是pwd,那么要是對這個頁面進(jìn)行登陸,那么必須給與這兩個信息。我們假設(shè)服務(wù)器已經(jīng)注冊了name為jason,pwd為123456這個賬號。

2.下面,寫一個Thread用來將name和pwd自動的登入,在服務(wù)器返回的response中獲得cookie信息,稍后對這個cookie進(jìn)行保存,這里先給出這個Thread的代碼:

public class HttpCookie extends Thread {

 private Handler mHandler;

 public HttpCookie(Handler mHandler) {
 this.mHandler = mHandler;
 }
 
 @Override
 public void run() {
 HttpClient client = new DefaultHttpClient();
 HttpPost post = new HttpPost("");//this place should add the login address
 
 List<NameValuePair> list = new ArrayList<NameValuePair>();
 list.add(new BasicNameValuePair("name", "jason"));
 list.add(new BasicNameValuePair("pwd", "123456"));
 
 try {
 post.setEntity(new UrlEncodedFormEntity(list));
 HttpResponse reponse = client.execute(post);
 if(reponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
 AbstractHttpClient absClient = (AbstractHttpClient) client;
 List<Cookie> cookies = absClient.getCookieStore().getCookies();
 
 for(Cookie cookie:cookies){
 if(cookie != null){
 //TODO
 //this place would get the cookies
 }
 }
 }
 
 } catch (UnsupportedEncodingException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 } catch (ClientProtocolException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 } catch (IOException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 }
 }
 
}

由于這是一個子線程,所以需要在主線程中創(chuàng)建并執(zhí)行。

同時,因?yàn)槠鋵?shí)子線程,那么里面必須含有一個handler的元素,用來當(dāng)成功獲取cookie后通知主線程進(jìn)行同步和保存。初始化這個子線程的時候需要將主線程上的handler給傳過來,隨后在以上代碼的TODO中發(fā)送消息,讓主線程記錄cookie,發(fā)送的這個消息需要將cookie信息包含進(jìn)去:

if(cookie != null){
 //TODO
 //this place would get the cookies
 Message msg = new Message();
 msg.obj = cookie;
 if(mHandler != null){
 mHandler.sendMessage(msg);
 return;
 }
}

隨后在主線程中(webview加載登陸界面前),在handler中將會獲取到cookie信息,下面將對該cookie進(jìn)行保存和同步:

 private Handler mHandler = new Handler(){
 public void handleMessage(android.os.Message msg) 
 {
 
 CookieSyncManager.createInstance(MainActivity.this);
 CookieManager cookieMgr = CookieManager.getInstance();
 cookieMgr.setAcceptCookie(true);
 cookieMgr.setCookie("", msg.obj.toString());// this place should add the login host address(not the login index address)
 CookieSyncManager.getInstance().sync();
 
 webview.loadUrl("");// login index address
 };
 };

這個時候發(fā)現(xiàn)webview加載的login index頁面中可以自動的登陸了并顯示登陸后的界面。 

五、 WebView與JavaScript的交互

1. webview調(diào)用js

mWebView.loadUrl("javascript:do()");
以上是webview在調(diào)用js中的一個叫做do的方法,該js所在的html文件大致如下:

<html>
 <script language="javascript">
 /* This function is invoked by the webview*/
 function do() {
 alert("1");
 }
 </script>
 <body>
 <a onClick="window.demo.clickOnAndroid()"><div style="width:80px;
 margin:0px auto;
 padding:10px;
 text-align:center;
 border:2px solid #111111;" >
 <img id="droid" src="xx.png"/><br>
 Click me!
 </div></a>
 </body>
</html>

2. js調(diào)用webview

我們假設(shè)下列的本地類是要給js調(diào)用的:

package com.test.webview;
class DemoJavaScriptInterface {

 DemoJavaScriptInterface() {
 }

 /**
 * This is not called on the UI thread. Post a runnable to invoke
 * loadUrl on the UI thread.
 */
 public void clickOnAndroid() {
 mHandler.post(new Runnable() {
 public void run() {
 //TODO
 }
 });

 }
 }

首先給webview設(shè)置:

mWebview.setJavaScriptEnabled(true);
隨后將本地的類(被js調(diào)用的)映射出去:

mWebView.addJavascriptInterface(new DemoJavaScriptInterface(), "demo");
“demo”這個名字就是公布出去給JS調(diào)用的,那么js久可以直接用下列代碼調(diào)用本地的DemoJavaScriptInterface類中的方法了:

<body onload="javascript:demo.clickOnAndroid()"> 
    ...
</body> 

六、WebView與JavaScript相互調(diào)用混淆問題

若webview中的js調(diào)用了本地的方法,正常情況下發(fā)布的debug包js調(diào)用的時候是沒有問題的,但是通常發(fā)布商業(yè)版本的apk都是要經(jīng)過混淆的步驟,這個時候會發(fā)現(xiàn)之前調(diào)用正常的js卻無法正常調(diào)用本地方法了。

這是因?yàn)榛煜臅r候已經(jīng)把本地的代碼的引用給打亂了,導(dǎo)致js中的代碼找不到本地的方法的地址。

解決這個問題很簡單,即在proguard.cfg文件中加上一些代碼,聲明本地中被js調(diào)用的代碼不被混淆。下面舉例說明:

第五節(jié)中被js調(diào)用的那個類DemoJavaScriptInterface的包名為com.test.webview,那么就要在proguard.cfg文件中加入:

-keep public class com.test.webview.DemoJavaScriptInterface{
    public <methods>;
}
若是內(nèi)部類,則大致寫成如下形式:

-keep public class com.test.webview.DemoJavaScriptInterface$InnerClass{
    public <methods>;
}
若android版本比較新,可能還需要添加上下列代碼:

-keepattributes *Annotation* 
-keepattributes *JavascriptInterface*

另一種講解:

一、基本用法

1、加載在線URL

void loadUrl(String url) 

這個函數(shù)主要加載url所對應(yīng)的網(wǎng)頁地址,或者用于調(diào)用網(wǎng)頁中的指定的JS方法(調(diào)用js方法的用法,后面會講),但有一點(diǎn)必須注意的是:loadUrl()必須在主線程中執(zhí)行?。。》駝t就會報錯?。?!。
注意:加載在線網(wǎng)頁地址是會用到聯(lián)網(wǎng)permission權(quán)限的,所以需要在AndroidManifest.xml中寫入下面代碼申請權(quán)限:
<uses-permission android:name="android.permission.INTERNET" /> 
本示例效果為:

從效果圖中可以明顯看出本示例的布局:
main.xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
 android:orientation="vertical" 
 android:layout_width="fill_parent" 
 android:layout_height="fill_parent" 
 > 
 <Button 
 android:id="@+id/btn" 
 android:layout_width="match_parent" 
 android:layout_height="wrap_content" 
 android:text="加載URL"/> 
 
 <WebView 
 android:id="@+id/webview" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent"/> 
</LinearLayout> 

對應(yīng)的處理代碼如下

public class MyActivity extends Activity { 
 
 private WebView mWebView; 
 private Button mBtn; 
 @Override 
 public void onCreate(Bundle savedInstanceState) { 
 super.onCreate(savedInstanceState); 
 setContentView(R.layout.main); 
 
 mWebView = (WebView)findViewById(R.id.webview); 
 mBtn = (Button)findViewById(R.id.btn); 
 
 mBtn.setOnClickListener(new View.OnClickListener() { 
 @Override 
 public void onClick(View v) { 
 mWebView.loadUrl("http://www.baidu.com"); 
 } 
 }); 
 } 
} 

代碼很簡單,就是在點(diǎn)擊按鈕的時候加載網(wǎng)址,但需要注意的是:網(wǎng)址必須完整即以http://或者ftp://等協(xié)議開頭,不能省略!不然將加載不出來,這是因?yàn)閣ebview是沒有自動補(bǔ)全協(xié)議功能的,所以如果我們不加,它將識別不出來網(wǎng)址類型,也就加載不出來了。
但如果我們運(yùn)行上面的代碼,效果卻是利用瀏覽器來打開網(wǎng)址,卻不是使用webview打開網(wǎng)址:

如果我們想實(shí)現(xiàn)像示例一樣在webview中打開網(wǎng)址需要怎么做呢?
我們需要設(shè)置WebViewClient:
修改后的代碼為:

public class MyActivity extends Activity { 
 
 private WebView mWebView; 
 private Button mBtn; 
 @Override 
 public void onCreate(Bundle savedInstanceState) { 
 super.onCreate(savedInstanceState); 
 setContentView(R.layout.main); 
 
 mWebView = (WebView)findViewById(R.id.webview); 
 mBtn = (Button)findViewById(R.id.btn); 
 
 mWebView.setWebViewClient(new WebViewClient()); 
 
 mBtn.setOnClickListener(new View.OnClickListener() { 
 @Override 
 public void onClick(View v) { 
 mWebView.loadUrl("http://www.baidu.com"); 
 } 
 }); 
 } 
} 

在上面的基礎(chǔ)上,我們添加了下面一段代碼:
mWebView.setWebViewClient(new WebViewClient()); 
在這里我們利用mWebView.setWebViewClient()函數(shù)僅僅設(shè)置了一個WebViewClient實(shí)例,就可以實(shí)現(xiàn)在WebView中打開鏈接了,至于原因我們下篇會講到,這里就先忽略了,大家只需要知道要在WebView中打開鏈接,就必須要設(shè)置WebViewClient;
最終的效果圖就與開篇時一樣的了,這里就不再帖效果圖了,下面我們來看看如何加載本地html網(wǎng)頁。

2、加載本地URL

一般而言,我們會將本地html文件放在assets文件夾下,比如:

web.html的內(nèi)容為:

<!DOCTYPE html> 
<html lang="en"> 
<head> 
 <meta charset="UTF-8"> 
 <title>Title</title> 
 <h1>歡迎光臨啟艦的blog</h1> 
</head> 
<body> 
</body> 
</html> 

即大標(biāo)題顯示一段文字
我們同樣在上面的示例的基礎(chǔ)上加以改造,在點(diǎn)擊按鈕的時候加載本地web.html文件

public class MyActivity extends Activity { 
 
 private WebView mWebView; 
 private Button mBtn; 
 @Override 
 public void onCreate(Bundle savedInstanceState) { 
 super.onCreate(savedInstanceState); 
 setContentView(R.layout.main); 
 
 mWebView = (WebView)findViewById(R.id.webview); 
 mBtn = (Button)findViewById(R.id.btn); 
 
 mBtn.setOnClickListener(new View.OnClickListener() { 
 @Override 
 public void onClick(View v) { 
 mWebView.loadUrl("file:///android_asset/web.html"); 
 } 
 }); 
 } 
} 

從這里可以看到與加載在線URL有兩點(diǎn)不同:

1)、URL類型不一樣

在加載本地URL時,是以“file:///”開頭的,而assets目錄所對應(yīng)的路徑名為anroid_asset,寫成其它的將識別不了,這是assets目錄的以file開頭的url形式的固定訪問形式。

2)、不需要設(shè)置WebViewClient

這里很明顯沒有設(shè)置WebViewClient函數(shù),但仍然是在webview中打開的本地文件。具體原因下篇文章講到WebViewClient時我們會具體解釋。

本例效果圖如下:

所以對于加載URL的總結(jié)就是:

1、如果是在線網(wǎng)址記得添加網(wǎng)絡(luò)訪問權(quán)限
2、在線網(wǎng)址中,如果要使用webview打開,記得設(shè)置WebViewClient
3、打開本地html文件時,是不需要設(shè)置WebViewClient,對應(yīng)的asstes目錄的url為:file:///android_asset/xxxxx

3、WebView基本設(shè)置

如果我們需要設(shè)置WebView的屬性,是通過WebView.getSettings()獲取設(shè)置WebView的WebSettings對象,然后調(diào)用WebSettings中的方法來實(shí)現(xiàn)的。
WebSettings的方法及說明如下:(這里先列出來所有的方法及解釋,大家可以先忽略,看后面的舉例中所使用的幾個常用方法即可,用到哪個函數(shù)的時候再回來查查就可以了)

/** 
 * 是否支持縮放,配合方法setBuiltInZoomControls使用,默認(rèn)true 
 */ 
setSupportZoom(boolean support) 
 
/** 
 * 是否需要用戶手勢來播放Media,默認(rèn)true 
 */ 
setMediaPlaybackRequiresUserGesture(boolean require) 
 
/** 
 * 是否使用WebView內(nèi)置的縮放組件,由浮動在窗口上的縮放控制和手勢縮放控制組成,默認(rèn)false 
 */ 
setBuiltInZoomControls(boolean enabled) 
 
/** 
 * 是否顯示窗口懸浮的縮放控制,默認(rèn)true 
 */ 
setDisplayZoomControls(boolean enabled) 
 
/** 
 * 是否允許訪問WebView內(nèi)部文件,默認(rèn)true 
 */ 
setAllowFileAccess(boolean allow) 
 
/** 
 * 是否允許獲取WebView的內(nèi)容URL ,可以讓W(xué)ebView訪問ContentPrivider存儲的內(nèi)容。 默認(rèn)true 
 */ 
setAllowContentAccess(boolean allow) 
 
/** 
 * 是否啟動概述模式瀏覽界面,當(dāng)頁面寬度超過WebView顯示寬度時,縮小頁面適應(yīng)WebView。默認(rèn)false 
 */ 
setLoadWithOverviewMode(boolean overview) 
 
/** 
 * 是否保存表單數(shù)據(jù),默認(rèn)false 
 */ 
setSaveFormData(boolean save) 
 
/** 
 * 設(shè)置頁面文字縮放百分比,默認(rèn)100% 
 */ 
setTextZoom(int textZoom) 
 
/** 
 * 是否支持ViewPort的meta tag屬性,如果頁面有ViewPort meta tag 指定的寬度,則使用meta tag指定的值,否則默認(rèn)使用寬屏的視圖窗口 
 */ 
setUseWideViewPort(boolean use) 
 
 
/** 
 * 是否支持多窗口,如果設(shè)置為true ,WebChromeClient#onCreateWindow方法必須被主程序?qū)崿F(xiàn),默認(rèn)false 
 */ 
setSupportMultipleWindows(boolean support) 
 
/** 
 * 指定WebView的頁面布局顯示形式,調(diào)用該方法會引起頁面重繪。默認(rèn)LayoutAlgorithm#NARROW_COLUMNS 
 */ 
setLayoutAlgorithm(LayoutAlgorithm l) 
 
/** 
 * 設(shè)置標(biāo)準(zhǔn)的字體族,默認(rèn)”sans-serif”。font-family 規(guī)定元素的字體系列。 
 * font-family 可以把多個字體名稱作為一個“回退”系統(tǒng)來保存。如果瀏覽器不支持第一個字體, 
 * 則會嘗試下一個。也就是說,font-family 屬性的值是用于某個元素的字體族名稱或/及類族名稱的一個 
 * 優(yōu)先表。瀏覽器會使用它可識別的第一個值。 
 */ 
setStandardFontFamily(String font) 
 
/** 
 * 設(shè)置混合字體族。默認(rèn)”monospace” 
 */ 
setFixedFontFamily(String font) 
 
/** 
 * 設(shè)置SansSerif字體族。默認(rèn)”sans-serif” 
 */ 
setSansSerifFontFamily(String font) 
 
/** 
 * 設(shè)置SerifFont字體族,默認(rèn)”sans-serif” 
 */ 
setSerifFontFamily(String font) 
 
/** 
 * 設(shè)置CursiveFont字體族,默認(rèn)”cursive” 
 */ 
setCursiveFontFamily(String font) 
 
/** 
 * 設(shè)置FantasyFont字體族,默認(rèn)”fantasy” 
 */ 
setFantasyFontFamily(String font) 
 
/** 
 * 設(shè)置最小字體,默認(rèn)8. 取值區(qū)間[1-72],超過范圍,使用其上限值。 
 */ 
setMinimumFontSize(int size) 
 
/** 
 * 設(shè)置最小邏輯字體,默認(rèn)8. 取值區(qū)間[1-72],超過范圍,使用其上限值。 
 */ 
setMinimumLogicalFontSize(int size) 
 
/** 
 * 設(shè)置默認(rèn)字體大小,默認(rèn)16,取值區(qū)間[1-72],超過范圍,使用其上限值。 
 */ 
setDefaultFontSize(int size) 
 
/** 
 * 設(shè)置默認(rèn)填充字體大小,默認(rèn)16,取值區(qū)間[1-72],超過范圍,使用其上限值。 
 */ 
setDefaultFixedFontSize(int size) 
 
/** 
 * 設(shè)置是否加載圖片資源,注意:方法控制所有的資源圖片顯示,包括嵌入的本地圖片資源。 
 * 使用方法setBlockNetworkImage則只限制網(wǎng)絡(luò)資源圖片的顯示。值設(shè)置為true后, 
 * webview會自動加載網(wǎng)絡(luò)圖片。默認(rèn)true 
 */ 
setLoadsImagesAutomatically(boolean flag) 
 
/** 
 * 是否加載網(wǎng)絡(luò)圖片資源。注意如果getLoadsImagesAutomatically返回false,則該方法沒有效果。 
 * 如果使用setBlockNetworkLoads設(shè)置為false,該方法設(shè)置為false,也不會顯示網(wǎng)絡(luò)圖片。 
 * 當(dāng)值從true改為false時。WebView會自動加載網(wǎng)絡(luò)圖片。 
 */ 
setBlockNetworkImage(boolean flag) 
 
/** 
 * 設(shè)置是否加載網(wǎng)絡(luò)資源。注意如果值從true切換為false后,WebView不會自動加載, 
 * 除非調(diào)用WebView#reload().如果沒有android.Manifest.permission#INTERNET權(quán)限, 
 * 值設(shè)為false,則會拋出java.lang.SecurityException異常。 
 * 默認(rèn)值:有android.Manifest.permission#INTERNET權(quán)限時為false,其他為true。 
 */ 
setBlockNetworkLoads(boolean flag) 
 
/** 
 * 設(shè)置是否允許執(zhí)行JS。 
 */ 
setJavaScriptEnabled(boolean flag) 
 
/** 
 * 是否允許Js訪問任何來源的內(nèi)容。包括訪問file scheme的URLs。考慮到安全性, 
 * 限制Js訪問范圍默認(rèn)禁用。注意:該方法只影響file scheme類型的資源,其他類型資源如圖片類型的, 
 * 不會受到影響。ICE_CREAM_SANDWICH_MR1版本以及以下默認(rèn)為true,JELLY_BEAN版本 
 * 以上默認(rèn)為false 
 */ 
setAllowUniversalAccessFromFileURLs(boolean flag) 
 
 
/** 
 * 是否允許Js訪問其他file scheme的URLs。包括訪問file scheme的資源。考慮到安全性, 
 * 限制Js訪問范圍默認(rèn)禁用。注意:該方法只影響file scheme類型的資源,其他類型資源如圖片類型的, 
 * 不會受到影響。如果getAllowUniversalAccessFromFileURLs為true,則該方法被忽略。 
 * ICE_CREAM_SANDWICH_MR1版本以及以下默認(rèn)為true,JELLY_BEAN版本以上默認(rèn)為false 
 */ 
setAllowFileAccessFromFileURLs(boolean flag) 
 
/** 
 * 設(shè)置存儲定位數(shù)據(jù)庫的位置,考慮到位置權(quán)限和持久化Cache緩存,Application需要擁有指定路徑的 
 * write權(quán)限 
 */ 
setGeolocationDatabasePath(String databasePath) 
 
/** 
 * 是否允許Cache,默認(rèn)false??紤]需要存儲緩存,應(yīng)該為緩存指定存儲路徑setAppCachePath 
 */ 
setAppCacheEnabled(boolean flag) 
 
/** 
 * 設(shè)置Cache API緩存路徑。為了保證可以訪問Cache,Application需要擁有指定路徑的write權(quán)限。 
 * 該方法應(yīng)該只調(diào)用一次,多次調(diào)用自動忽略。 
 */ 
setAppCachePath(String appCachePath) 
 
/** 
 * 是否允許數(shù)據(jù)庫存儲。默認(rèn)false。查看setDatabasePath API 如何正確設(shè)置數(shù)據(jù)庫存儲。 
 * 該設(shè)置擁有全局特性,同一進(jìn)程所有WebView實(shí)例共用同一配置。注意:保證在同一進(jìn)程的任一WebView 
 * 加載頁面之前修改該屬性,因?yàn)樵谶@之后設(shè)置WebView可能會忽略該配置 
 */ 
setDatabaseEnabled(boolean flag) 
 
/** 
 * 是否存儲頁面DOM結(jié)構(gòu),默認(rèn)false。 
 */ 
setDomStorageEnabled(boolean flag) 
 
/** 
 * 是否允許定位,默認(rèn)true。注意:為了保證定位可以使用,要保證以下幾點(diǎn): 
 * Application 需要有android.Manifest.permission#ACCESS_COARSE_LOCATION的權(quán)限 
 * Application 需要實(shí)現(xiàn)WebChromeClient#onGeolocationPermissionsShowPrompt的回調(diào), 
 * 接收J(rèn)s定位請求訪問地理位置的通知 
 */ 
setGeolocationEnabled(boolean flag) 
 
/** 
 * 是否允許JS自動打開窗口。默認(rèn)false 
 */ 
setJavaScriptCanOpenWindowsAutomatically(boolean flag) 
 
/** 
 * 設(shè)置頁面的編碼格式,默認(rèn)UTF-8 
 */ 
setDefaultTextEncodingName(String encoding) 
 
/** 
 * 設(shè)置WebView代理,默認(rèn)使用默認(rèn)值 
 */ 
setUserAgentString(String ua) 
 
/** 
 * 通知WebView是否需要設(shè)置一個節(jié)點(diǎn)獲取焦點(diǎn)當(dāng) 
 * WebView#requestFocus(int,android.graphics.Rect)被調(diào)用的時候,默認(rèn)true 
 */ 
setNeedInitialFocus(boolean flag) 
 
/** 
 * 基于WebView導(dǎo)航的類型使用緩存:正常頁面加載會加載緩存并按需判斷內(nèi)容是否需要重新驗(yàn)證。 
 * 如果是頁面返回,頁面內(nèi)容不會重新加載,直接從緩存中恢復(fù)。setCacheMode允許客戶端根據(jù)指定的模式來 
 * 使用緩存。 
 * LOAD_DEFAULT 默認(rèn)加載方式 
 * LOAD_CACHE_ELSE_NETWORK 按網(wǎng)絡(luò)情況使用緩存 
 * LOAD_NO_CACHE 不使用緩存 
 * LOAD_CACHE_ONLY 只使用緩存 
 */ 
setCacheMode(int mode) 
 
/** 
 * 設(shè)置加載不安全資源的WebView加載行為。KITKAT版本以及以下默認(rèn)為MIXED_CONTENT_ALWAYS_ALLOW方 
 * 式,LOLLIPOP默認(rèn)MIXED_CONTENT_NEVER_ALLOW。強(qiáng)烈建議:使用MIXED_CONTENT_NEVER_ALLOW 
 */ 
setMixedContentMode(int mode) 

下面我們就舉個例子來看下用法

示例1:在WebView中啟用JavaScript:

public class MyActivity extends Activity { 
 
 private WebView mWebView; 
 private Button mBtn; 
 
 @Override 
 public void onCreate(Bundle savedInstanceState) { 
 super.onCreate(savedInstanceState); 
 setContentView(R.layout.main); 
 
 mWebView = (WebView) findViewById(R.id.webview); 
 mBtn = (Button) findViewById(R.id.btn); 
 
 WebSettings webSettings = mWebView.getSettings(); 
 webSettings.setJavaScriptEnabled(true); 
 } 
} 

示例2:設(shè)置緩存

優(yōu)先使用緩存
webView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); 
不使用緩存:
webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE); 

示例3:打開頁面時,自適應(yīng)屏幕:

WebSettings webSettings = mWebView .getSettings(); 
webSettings.setUseWideViewPort(true);//設(shè)置此屬性,可任意比例縮放 
webSettings.setLoadWithOverviewMode(true); 

效果圖如下:

示例4:使頁面支持縮放:

WebSettings webSettings = mWebView.getSettings(); 
//開啟javascript支持 
webSettings.setJavaScriptEnabled(true); 
// 設(shè)置可以支持縮放 
webSettings.setSupportZoom(true); 
// 設(shè)置出現(xiàn)縮放工具 
webSettings.setBuiltInZoomControls(true); 

示例5:.如果webView中需要用戶手動輸入用戶名、密碼或其他,則webview必須設(shè)置支持獲取手勢焦點(diǎn)
webview.requestFocusFromTouch(); 
其它的設(shè)置就靠大家自己去嘗試?yán)?,這里就不再一一綴述了,大家只需要記著,如果需要設(shè)置webview就從WebSettings里面去找就可以啦。

二、JS調(diào)用Java代碼

在看了如何設(shè)置webview以后,我們來看下如何讓W(xué)ebview與網(wǎng)頁中的JS代碼交互的問題。

1、概述

更多時候,網(wǎng)頁中需要通過JS代碼來調(diào)用本地的Android代碼,比如H5頁面需要判斷當(dāng)前用戶是否登錄等。
利用JS代碼調(diào)用JAVA代碼,主要是用到WebView下面的一個函數(shù):
public void addJavascriptInterface(Object obj, String interfaceName) 

這個函數(shù)有兩個參數(shù):

--Object obj:interfaceName所綁定的對象
--String interfaceName:所綁定的對象所對應(yīng)的名稱
它有意義就是向WebView注入一個interfaceName的對象,這個對象綁定的是obj對象,通過interfaceName就可以調(diào)用obj對象中的方法,這個表述可能大家不太理解,因?yàn)閕nterfaceName是一個String,怎么被你說成對象了,理解不了沒關(guān)系,下面有具體示例

2、示例

下面同樣是上面的示例,我們對它加以更改,效果圖如下:

在原來html上面添加了一個按鈕,當(dāng)點(diǎn)擊按鈕時調(diào)用Android的Toast函數(shù)彈出一個toast消息。
先看Android代碼:

public class MyActivity extends Activity { 
 
 private WebView mWebView; 
 private Button mBtn; 
 
 @Override 
 public void onCreate(Bundle savedInstanceState) { 
 super.onCreate(savedInstanceState); 
 setContentView(R.layout.main); 
 
 mWebView = (WebView) findViewById(R.id.webview); 
 
 WebSettings webSettings = mWebView.getSettings(); 
 webSettings.setJavaScriptEnabled(true); 
 mWebView.addJavascriptInterface(this, "android"); 
 mWebView.loadUrl("file:///android_asset/web.html"); 
 } 
 
 public void toastMessage(String message) { 
 Toast.makeText(getApplicationContext(), "通過Natvie傳遞的Toast:"+message, Toast.LENGTH_LONG).show(); 
 } 
} 

這里最主要是的下面這句:

mWebView.addJavascriptInterface(this, "android"); 

這句的意思是把MyActivity對象注入到WebView中,在WebView中的對象別名叫android;另外,我們還在MyActivity中額外寫了一個函數(shù)toastMessage(String message),用于彈出MSG
下面我們看看html代碼:

<!DOCTYPE html> 
<html lang="en"> 
<head> 
 <meta charset="UTF-8"> 
 <title>Title</title> 
 <h1>歡迎光臨啟艦的blog</h1> 
 <input type="button" value="js調(diào)native" onclick="ok()"> 
</head> 
<body> 
<script type="text/javascript"> 
function ok() { 
 android.toastMessage("哈哈,i m webview msg"); 
} 
</script> 
</body> 
</html> 

在這個html中,我添加了一個button按鈕,當(dāng)點(diǎn)擊時調(diào)用ok函數(shù):

function ok() { 
 android.toastMessage("哈哈,i m webview msg"); 
} 

它的意義就是調(diào)用android對象里的toastMessage方法,這個android就是我們利用mWebView.addJavascriptInterface(this, “android”)注入到WebView的android,它所對應(yīng)的對象就將MyActivity;所以在JS中,我們就可以通過android這個別名來調(diào)用MyActivity對象中的任何public方法。

3、addJavascriptInterface自定義作用對象

在上面的示例中mWebView.addJavascriptInterface(this, “android”);我們直接通過this,把當(dāng)前整個類作為對象傳給WebView了,但這會有很大風(fēng)險,因?yàn)槲覀冞@個類中可能會有各種函數(shù),而這些函數(shù)是只有本地Native代碼才會用到,WebView是根本用不到的。所以如果通過全部注入給WebView的話,那么一些存心不良的同學(xué)就可以任意調(diào)用我們這個類中的方法,給我們APP帶來危害。

所以,一般而言,我們很少直接會傳this,把整個類注入給WebView,而是單獨(dú)寫一個類專門用于JS交互,比如:

public class MyActivity extends Activity { 
 
 private WebView mWebView; 
 private Button mBtn; 
 
 @Override 
 public void onCreate(Bundle savedInstanceState) { 
 super.onCreate(savedInstanceState); 
 setContentView(R.layout.main); 
 
 mWebView = (WebView) findViewById(R.id.webview); 
 mBtn = (Button) findViewById(R.id.btn); 
 
 WebSettings webSettings = mWebView.getSettings(); 
 webSettings.setJavaScriptEnabled(true); 
 mWebView.addJavascriptInterface(new JSBridge(), "android"); 
 mWebView.loadUrl("file:///android_asset/web.html"); 
 } 
 
 public class JSBridge{ 
 public void toastMessage(String message) { 
 Toast.makeText(getApplicationContext(), "通過Natvie傳遞的Toast:"+message, Toast.LENGTH_LONG).show(); 
 } 
 } 
} 

在這段代碼中,在通過addJavascriptInterface注入時:

mWebView.addJavascriptInterface(new JSBridge(), "android");  

指定android對象綁定的是JSBridge對象!所以在WebView中,通過JS只能訪問JSBridge中所定義的對象,如果訪問其它類的函數(shù),比如MyActivity中的函數(shù),就會報下面的錯誤(即方法找不到)

大家可以自己嘗試下;

然后對應(yīng)的html代碼:

<!DOCTYPE html> 
<html lang="en"> 
<head> 
 <meta charset="UTF-8"> 
 <title>Title</title> 
 <h1>歡迎光臨啟艦的blog</h1> 
 <input type="button" value="js調(diào)native" onclick="ok()"> 
</head> 
<body> 
<script type="text/javascript"> 
function ok() { 
 android.toastMessage("哈哈,i m webview msg"); 
 } 
</script> 
</body> 
</html> 

由于在注入時的對象別名和所調(diào)用的函數(shù)名都沒有變,所以HTML中的JS代碼是無需更改的。效果圖與上節(jié)一樣,就不再帖出了。

源碼在文章底部給出

4、addJavascriptInterface注入漏洞

上面我們說了在addJavascriptInterface注入時,為了防止WebView調(diào)用我們不想被它調(diào)用的函數(shù),所以我們需要單獨(dú)為WebView交互定義一個類,讓它只執(zhí)行這個類里面的函數(shù)
但……這真的能擋住黑客的攻擊嗎?
當(dāng)然是NO……,不然我就不會寫這一段了……
mWebView.addJavascriptInterface(new JSBridge(), "android"); 
在注入時,我們已經(jīng)把對象傳給了JS,在JS中當(dāng)然可以通過反射得到APP中的各種類的實(shí)例!現(xiàn)在反編譯Android代碼可不是什么難事(本文結(jié)尾附j(luò)adx反編譯方法),很容易拿到你有哪些類,有哪些函數(shù),通過這些就可以想執(zhí)行哪個執(zhí)行哪個了,有沒有細(xì)思極恐……
具體的細(xì)節(jié)我就不講了,不在本篇范圍,給大家找了篇文章,有興趣的同學(xué)可以參考下:《Android WebView的Js對象注入漏洞解決方案》

5、JavascriptInterface注解

為了解決addJavascriptInterface()函數(shù)的安全問題,在android:targetSdkVersion數(shù)值為17(Android4.2)及以上的APP中,JS只能訪問帶有 @JavascriptInterface注解的Java函數(shù),所以如果你的android:targetSdkVersion是17+,與JS交互的Native函數(shù)中,必須添加JavascriptInterface注解,不然無效,比如:

public class JSBridge { 
 @JavascriptInterface 
 public void toastMessage(String message) { 
 Toast.makeText(getApplicationContext(), "通過Natvie傳遞的Toast:" + message, Toast.LENGTH_LONG).show(); 
 } 
} 

這也就是很多同學(xué)在高target上,addJavascriptInterface()函數(shù)無效的主要原因。
注意:雖然在target 17以后,已經(jīng)修復(fù)了這個安全問題,但目前大多數(shù)APP都還是target 17以前的,所以大家可以嘗試著找一些APP來演示下這個漏洞哦……

三、JAVA調(diào)用JS代碼

1、JAVA調(diào)用JS代碼

前面給大家演示了如何通過JS調(diào)用Java代碼,這里就反過來看看,如何在Native中調(diào)用JS的代碼
本例的效果圖如下:

在點(diǎn)擊“加載URL”按鈕時,調(diào)用webview中的JavaScript求和函數(shù),將結(jié)果顯示在標(biāo)題中。

先看html代碼:

<!DOCTYPE html> 
<html lang="en"> 
<head> 
 <meta charset="UTF-8"> 
 <title>Title</title> 
 <h1 id="h">歡迎光臨啟艦的blog</h1> 
 <input type="button" value="js調(diào)native" onclick="ok()"> 
</head> 
<body> 
<script type="text/javascript"> 
function sum(i,m) 
{ 
 document.getElementById("h").innerHTML= (i+m); 
} 
</script> 
</body> 
</html> 

在這里,我們寫了一個求和函數(shù)sum(i,m)
結(jié)果中就是把h1標(biāo)簽的內(nèi)容改為求和后的結(jié)果值。
再來看看JAVA的調(diào)用代碼:

public class MyActivity extends Activity { 
 
 private WebView mWebView; 
 private Button mBtn; 
 
 @Override 
 public void onCreate(Bundle savedInstanceState) { 
 super.onCreate(savedInstanceState); 
 setContentView(R.layout.main); 
 
 mWebView = (WebView) findViewById(R.id.webview); 
 mBtn = (Button) findViewById(R.id.btn); 
 
 WebSettings webSettings = mWebView.getSettings(); 
 webSettings.setJavaScriptEnabled(true); 
 mWebView.loadUrl("file:///android_asset/web.html"); 
 
 mBtn.setOnClickListener(new View.OnClickListener() { 
 @Override 
 public void onClick(View v) { 
 mWebView.loadUrl("javascript:sum(3,8)"); 
 } 
 }); 
 } 
} 

在點(diǎn)擊按鈕時調(diào)用JS函數(shù):
mWebView.loadUrl("javascript:sum(3,8)"); 
這里也就是在JAVA中調(diào)用JS函數(shù)的方法:
String url = "javascript:methodName(params……);" 
webView.loadUrl(url); 
javascript:偽協(xié)議讓我們可以通過一個鏈接來調(diào)用JavaScript函數(shù)
中間methodName是JavaScript中實(shí)現(xiàn)的函數(shù)
jsonParams是傳入的參數(shù)列表
使用起來難度不大,就不再多講了

源碼在文章底部給出

2、JAVA中如何得到JS中的返回值(Android4.4以前)

現(xiàn)在我們再考慮一下,如果我們要在JAVA中需要得到JS的結(jié)果返回值要怎么辦?比如在上面的例子中,我們需要在JAVA中得到在計(jì)算后的結(jié)果值
Android在4.4之前并沒有提供直接調(diào)用js函數(shù)并獲取值的方法,也就是說,我們只能調(diào)用JS中的函數(shù),并不能得到該函數(shù)的返回值,想得到返回值我們就得想其它辦法,所以在此之前,常用的思路是 java調(diào)用js方法,js方法執(zhí)行完畢,再次調(diào)用java代碼將值返回。

1).Java調(diào)用js代碼

webView.addJavascriptInterface(this, "android"); 
mWebView.loadUrl("javascript:sum(3,8)"); 

注意,這里通過addJavascriptInterface將MyActiviy所對應(yīng)的對象注入到WebView中了。
2).js函數(shù)處理,并將結(jié)果通過調(diào)用java方法返回

function sum(i,m){ 
 var result = i+m; 
 document.getElementById("h").innerHTML= result; 
 android.onSumResult(result) 
} 

3)..Java在回調(diào)方法中獲取js函數(shù)返回值

public void onSumResult(int result) { 
 Log.i(LOGTAG, "onSumResult result=" + result); 
} 

先看下效果圖:

下面我們就完整地看一下代碼:

JS代碼:

<!DOCTYPE html> 
<html lang="en"> 
<head> 
 <meta charset="UTF-8"> 
 <title>Title</title> 
 <h1 id="h">歡迎光臨啟艦的blog</h1> 
 <input type="button" value="js調(diào)native" onclick="ok()"> 
</head> 
<body> 
<script type="text/javascript"> 
function sum(i,m){ 
 var result = i+m; 
 document.getElementById("h").innerHTML= result; 
 android.onSumResult(result); 
} 
</script> 
</body> 
</html> 

在function sum(i,m)中,先通過result得到結(jié)果,最后通過android.onSumResult(result);將結(jié)果傳給Native
然后再來看看JAVA代碼:

public class MyActivity extends Activity { 
 
 private WebView mWebView; 
 private Button mBtn; 
 
 @Override 
 public void onCreate(Bundle savedInstanceState) { 
 super.onCreate(savedInstanceState); 
 setContentView(R.layout.main); 
 
 mWebView = (WebView) findViewById(R.id.webview); 
 mBtn = (Button) findViewById(R.id.btn); 
 
 WebSettings webSettings = mWebView.getSettings(); 
 webSettings.setJavaScriptEnabled(true); 
 mWebView.addJavascriptInterface(this, "android"); 
 mWebView.loadUrl("file:///android_asset/web.html"); 
 
 mBtn.setOnClickListener(new View.OnClickListener() { 
  @Override 
  public void onClick(View v) { 
  mWebView.loadUrl("javascript:sum(3,8)"); 
  } 
 }); 
 } 
 
 public void onSumResult(int result) { 
 Toast.makeText(this,"received result:"+result,Toast.LENGTH_SHORT).show(); 
 } 
} 

這里主要做了兩件事:

第一:通過addJavascriptInterface注入MyActivity對象,以便JS訪問其中的函數(shù)
mWebView.addJavascriptInterface(this, "android"); 
第二:供JS調(diào)用,以返回結(jié)果的函數(shù)onSumResult():

public void onSumResult(int result) { 
 Toast.makeText(this,"received result:"+result,Toast.LENGTH_SHORT).show(); 
}

3、JAVA中如何得到JS中的返回值(Android4.4之后)

Android 4.4之后使用evaluateJavascript即可。這里展示一個簡單的交互示例
先寫一個具有返回值的js方法

function getGreetings() { 
 return 1; 
} 

java代碼時用evaluateJavascript方法調(diào)用:

private void testEvaluateJavascript(WebView webView) { 
 webView.evaluateJavascript("getGreetings()", new ValueCallback() { 
 @Override 
 public void onReceiveValue(String value) { 
  Log.i(LOGTAG, "onReceiveValue value=" + value); 
 } 
 }); 
} 

從上面的用法中很明顯看到,通過evaluateJavascript調(diào)用JS中的方法,可以向其中添加結(jié)果回調(diào),來接收J(rèn)S的return值。

注意:

上面限定了結(jié)果返回結(jié)果為String,對于簡單的類型會嘗試轉(zhuǎn)換成字符串返回,對于復(fù)雜的數(shù)據(jù)類型,建議以字符串形式的json返回。

evaluateJavascript方法必須在UI線程(主線程)調(diào)用,因此onReceiveValue也執(zhí)行在主線程。

好了,這篇文章中有關(guān)WebView的知識就先到這,下篇繼續(xù)講。下面給大家講講有關(guān)jadx-gui反編譯的知識。

四、jadx-gui反編譯

在遇到j(luò)adx-gui反編譯之前,都是使用apktools進(jìn)行反編譯的,apktools有些是反編譯不出來的,而且……難用……
想知道jadx-gui有多強(qiáng)?它都可以反編譯淘寶、微信代碼,是不是夠強(qiáng)了。下面我們就來看看它是如何反編譯的;

1)、下載、配置

jadx-gui是開源的,項(xiàng)目地址:《https://github.com/skylot/jadx
mac電腦:
打開終端,切到某個路徑下,輸入以下命令:

git clone https://github.com/skylot/jadx.git 
cd jadx 
./gradlew dist 

其實(shí)這里只是做了兩個動作:

第一,使用git命令將 項(xiàng)目clone下來(這里需要配置git環(huán)境,如果沒有,請先搜資料配置git環(huán)境,然后再來)
然后,執(zhí)行jadx目錄 下gradlew腳本,這個是shell腳本
windows電腦:

git clone https://github.com/skylot/jadx.git 
cd jadx 
gradlew.bat dist 

在windows電腦中,步驟與mac是一樣的,只是最后一步中,已經(jīng)不再是./gradlew所對應(yīng)的shell腳本了,而是windows平臺上的bat腳本。

可見作者有多牛X,shell腳本和bat腳本都會寫,真是屌的不能直視

整個編譯過程是比較慢的,這里需要耐心等待下。因?yàn)槟壳皶褂胓radle 2.7來編譯項(xiàng)目,如果沒有在環(huán)境變量中環(huán)境gradle 2.7的環(huán)境變量,會自己下載gradle 2.7

編譯成功后會打出BUILD SUCCESS字樣,如下圖所示:

在編譯成功后,在jadx目錄下,會生成一個build目錄,其中包含jadx目錄和一個jadx-xxx-dev.zip的打包文件。在build/jadx目錄下,就是源碼編譯出的jadx工具及所用jar包。jadx-xxx-dev.zip解壓后的內(nèi)容與build/jadx內(nèi)容一樣,只是將其打包了一下而已,方便移值,可見作者有多用心。build目錄結(jié)構(gòu)如下圖所示:

2)、開始反編譯

等完畢后,可以開始了,我就介紹個最簡單最常用的用法

(1)、把a(bǔ)pk改成zip
(2)、解壓zip獲取class.dex文件
(3)、將class.dex文件放到j(luò)adx目錄下

cd build/jadx/ 
bin/jadx -d out classes.dex # 反編譯后放入out文件夾下(如果out不存在它會自動創(chuàng)建) 
#or 
bin/jadx-gui classes.dex # 會反編譯,并且使用gui打開 

目錄結(jié)構(gòu)圖如下:

在使用jadx-gui反編譯時,左下角會顯示當(dāng)前反編譯的進(jìn)度:

在反編譯完成后,在左側(cè)就可以看到目錄結(jié)構(gòu)和對應(yīng)的代碼,目錄結(jié)構(gòu)中顯示的a,b,c,d這些字母是由于在生成apk時使用proguard混淆造成的,proguard混淆的類名是沒辦法反編譯出對應(yīng)的原類名的,這也是反編譯代碼中比較蛋疼的地方,下面給大家演示下結(jié)果:(還可以通過點(diǎn)擊搜索按鈕,搜索其中的代碼)

有關(guān)jadx-gui工具的更多用法,只有靠大家自己去研究啦,到這里我們的源碼就已經(jīng)反編譯出來了。
反編譯工具和微信的Classes文件,會在源碼中給出大家,源碼下載地址:Android WebView使用

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助。

相關(guān)文章

  • Android實(shí)戰(zhàn)教程第三篇之簡單實(shí)現(xiàn)撥打電話功能

    Android實(shí)戰(zhàn)教程第三篇之簡單實(shí)現(xiàn)撥打電話功能

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)戰(zhàn)教程第三篇之簡單實(shí)現(xiàn)撥打電話功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • Android開發(fā)注解排列組合出啟動任務(wù)ksp

    Android開發(fā)注解排列組合出啟動任務(wù)ksp

    這篇文章主要為大家介紹了Android開發(fā)注解排列組合出啟動任務(wù)ksp示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • Android開發(fā)使用RecyclerView添加點(diǎn)擊事件實(shí)例詳解

    Android開發(fā)使用RecyclerView添加點(diǎn)擊事件實(shí)例詳解

    這篇文章主要為大家介紹了Android開發(fā)使用RecyclerView添加點(diǎn)擊事件實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • android屏蔽按鈕連續(xù)點(diǎn)擊的示例代碼

    android屏蔽按鈕連續(xù)點(diǎn)擊的示例代碼

    這篇文章主要介紹了android屏蔽按鈕連續(xù)點(diǎn)擊的示例代碼,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • Android使用硬件加速的方式

    Android使用硬件加速的方式

    硬件加速是指利用設(shè)備的硬件資源來加速圖形渲染和圖像處理等操作,以提高應(yīng)用程序的性能和用戶體驗(yàn),Android使用硬件加速的目的是為了提高圖形渲染的性能和效果,本文給大家詳細(xì)介紹了Android如何使用硬件加速,需要的朋友可以參考下
    2023-10-10
  • Android編程滑動效果之Gallery仿圖像集瀏覽實(shí)現(xiàn)方法

    Android編程滑動效果之Gallery仿圖像集瀏覽實(shí)現(xiàn)方法

    這篇文章主要介紹了Android編程滑動效果之Gallery仿圖像集瀏覽實(shí)現(xiàn)方法,結(jié)合實(shí)例形式詳細(xì)分析了Gallery瀏覽圖片的原理、步驟與相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2016-02-02
  • Android中使用背景色Alpha值遇到的一個坑

    Android中使用背景色Alpha值遇到的一個坑

    通過修改Alpha值可以對透明度進(jìn)行設(shè)置,這個大家應(yīng)該都不陌生,下面這篇文章主要給大家介紹了關(guān)于Android中使用背景色Alpha值遇到的一個坑,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。
    2017-12-12
  • Android開發(fā)之登錄驗(yàn)證實(shí)例教程

    Android開發(fā)之登錄驗(yàn)證實(shí)例教程

    這篇文章主要介紹了Android開發(fā)之登錄驗(yàn)證實(shí)現(xiàn)方法,包括發(fā)送數(shù)據(jù)、服務(wù)器端驗(yàn)證、配置文件等,需要的朋友可以參考下
    2014-08-08
  • Android之ProgressBar即時顯示下載進(jìn)度詳解

    Android之ProgressBar即時顯示下載進(jìn)度詳解

    這篇文章主要為大家詳細(xì)介紹了Android之ProgressBar即時顯示下載進(jìn)度,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • Android入門教程之ListView的具體使用詳解

    Android入門教程之ListView的具體使用詳解

    列表作為最常用的控件之一,還是有必要好好學(xué)習(xí)的,本章以一個初學(xué)者的角度來學(xué)習(xí) ListView,ListView的屬性,以及BaseAdapter簡單定義,至于ListView優(yōu)化這些, 我們一步步來
    2021-10-10

最新評論