整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          Android:WebView與 JS 交互方式 都在這里了

          • 現(xiàn)在很多App里都內(nèi)置了Web網(wǎng)頁(Hybrid App),比如說很多電商平臺(tái),淘寶、京東、聚劃算等等,如下圖

          • 上述功能是由Android的WebView實(shí)現(xiàn)的,其中涉及到Android客戶端與Web網(wǎng)頁交互的實(shí)現(xiàn)
          • 今天我將全面介紹Android通過WebView與JS交互的全面方式

          閱讀本文前請(qǐng)先閱讀:Android開發(fā):最全面、最易懂的Webview詳解


          目錄


          1. 交互方式總結(jié)

          Android與JS通過WebView互相調(diào)用方法,實(shí)際上是:

          • Android去調(diào)用JS的代碼
          • JS去調(diào)用Android的代碼

          二者溝通的橋梁是WebView

          對(duì)于Android調(diào)用JS代碼的方法有2種:

          1. 通過WebView的loadUrl()

          2. 通過WebView的evaluateJavascript()

          對(duì)于JS調(diào)用Android代碼的方法有3種:

          1. 通過WebView的addJavascriptInterface()進(jìn)行對(duì)象映射

          2. 通過 WebViewClient 的shouldOverrideUrlLoading ()方法回調(diào)攔截 url

          3. 通過 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回調(diào)攔截JS對(duì)話框alert()、confirm()、prompt() 消息


          2. 具體分析

          2.1 Android通過WebView調(diào)用 JS 代碼

          對(duì)于Android調(diào)用JS代碼的方法有2種:

          1. 通過WebView的loadUrl()

          2. 通過WebView的evaluateJavascript()

          方式1:通過WebView的loadUrl()

          • 實(shí)例介紹:點(diǎn)擊Android按鈕,即調(diào)用WebView JS(文本名為javascript)中callJS()
          • 具體使用:

          步驟1:將需要調(diào)用的JS代碼以.html格式放到src/main/assets文件夾里

          • 為了方便展示,本文是采用Andorid調(diào)用本地JS代碼說明;
          • 實(shí)際情況時(shí),Android更多的是調(diào)用遠(yuǎn)程JS代碼,即將加載的JS代碼路徑改成url即可

          需要加載JS代碼:javascript.html

          // 文本名:javascript

          <!DOCTYPE html>

          <html>

          <head>

          <meta charset="utf-8">

          <title>Carson_Ho</title>

          // JS代碼

          <script>

          // Android需要調(diào)用的方法

          function callJS(){

          alert("Android調(diào)用了JS的callJS方法");

          }

          </script>

          </head>

          </html>

          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19

          步驟2:在Android里通過WebView設(shè)置調(diào)用JS代碼

          Android代碼:MainActivity.java

          注釋已經(jīng)非常清楚

          public class MainActivity extends AppCompatActivity {

          WebView mWebView;

          Button button;

          @Override

          protected void onCreate(Bundle savedInstanceState) {

          super.onCreate(savedInstanceState);

          setContentView(R.layout.activity_main);

          mWebView =(WebView) findViewById(R.id.webview);

          WebSettings webSettings = mWebView.getSettings();

          // 設(shè)置與Js交互的權(quán)限

          webSettings.setJavaScriptEnabled(true);

          // 設(shè)置允許JS彈窗

          webSettings.setJavaScriptCanOpenWindowsAutomatically(true);

          // 先載入JS代碼

          // 格式規(guī)定為:file:///android_asset/文件名.html

          mWebView.loadUrl("file:///android_asset/javascript.html");

          button = (Button) findViewById(R.id.button);

          button.setOnClickListener(new View.OnClickListener() {

          @Override

          public void onClick(View v) {

          // 通過Handler發(fā)送消息

          mWebView.post(new Runnable() {

          @Override

          public void run() {

          // 注意調(diào)用的JS方法名要對(duì)應(yīng)上

          // 調(diào)用javascript的callJS()方法

          mWebView.loadUrl("javascript:callJS()");

          }

          });

          }

          });

          // 由于設(shè)置了彈窗檢驗(yàn)調(diào)用結(jié)果,所以需要支持js對(duì)話框

          // webview只是載體,內(nèi)容的渲染需要使用webviewChromClient類去實(shí)現(xiàn)

          // 通過設(shè)置WebChromeClient對(duì)象處理JavaScript的對(duì)話框

          //設(shè)置響應(yīng)js 的Alert()函數(shù)

          mWebView.setWebChromeClient(new WebChromeClient() {

          @Override

          public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {

          AlertDialog.Builder b = new AlertDialog.Builder(MainActivity.this);

          b.setTitle("Alert");

          b.setMessage(message);

          b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {

          @Override

          public void onClick(DialogInterface dialog, int which) {

          result.confirm();

          }

          });

          b.setCancelable(false);

          b.create().show();

          return true;

          }

          });

          }

          }

          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37
          • 38
          • 39
          • 40
          • 41
          • 42
          • 43
          • 44
          • 45
          • 46
          • 47
          • 48
          • 49
          • 50
          • 51
          • 52
          • 53
          • 54
          • 55
          • 56
          • 57
          • 58
          • 59
          • 60
          • 61
          • 62
          • 63
          • 64
          • 65
          • 66
          • 67
          • 68
          • 69

          特別注意:JS代碼調(diào)用一定要在 onPageFinished() 回調(diào)之后才能調(diào)用,否則不會(huì)調(diào)用。

          onPageFinished()屬于WebViewClient類的方法,主要在頁面加載結(jié)束時(shí)調(diào)用

          方式2:通過WebView的evaluateJavascript()

          • 優(yōu)點(diǎn):該方法比第一種方法效率更高、使用更簡潔。
          • 因?yàn)樵摲椒ǖ膱?zhí)行不會(huì)使頁面刷新,而第一種方法(loadUrl )的執(zhí)行則會(huì)。
          • Android 4.4 后才可使用
          • 具體使用

          // 只需要將第一種方法的loadUrl()換成下面該方法即可

          mWebView.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {

          @Override

          public void onReceiveValue(String value) {

          //此處為 js 返回的結(jié)果

          }

          });

          }

          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8

          2.1.2 方法對(duì)比

          2.1.3 使用建議

          兩種方法混合使用,即Android 4.4以下使用方法1,Android 4.4以上方法2

          // Android版本變量

          final int version = Build.VERSION.SDK_INT;

          // 因?yàn)樵摲椒ㄔ?Android 4.4 版本才可使用,所以使用時(shí)需進(jìn)行版本判斷

          if (version < 18) {

          mWebView.loadUrl("javascript:callJS()");

          } else {

          mWebView.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {

          @Override

          public void onReceiveValue(String value) {

          //此處為 js 返回的結(jié)果

          }

          });

          }

          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13

          2.2 JS通過WebView調(diào)用 Android 代碼

          對(duì)于JS調(diào)用Android代碼的方法有3種:

          1. 通過WebView的addJavascriptInterface()進(jìn)行對(duì)象映射

          2. 通過 WebViewClient 的shouldOverrideUrlLoading ()方法回調(diào)攔截 url

          3. 通過 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回調(diào)攔截JS對(duì)話框alert()、confirm()、prompt() 消息

          2.2.1 方法分析

          方式1:通過 WebView的addJavascriptInterface()進(jìn)行對(duì)象映射

          步驟1:定義一個(gè)與JS對(duì)象映射關(guān)系的Android類:AndroidtoJs

          AndroidtoJs.java(注釋已經(jīng)非常清楚)

          // 繼承自O(shè)bject類

          public class AndroidtoJs extends Object {

          // 定義JS需要調(diào)用的方法

          // 被JS調(diào)用的方法必須加入@JavascriptInterface注解

          @JavascriptInterface

          public void hello(String msg) {

          System.out.println("JS調(diào)用了Android的hello方法");

          }

          }

          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10

          步驟2:將需要調(diào)用的JS代碼以.html格式放到src/main/assets文件夾里

          需要加載JS代碼:javascript.html

          <!DOCTYPE html>

          <html>

          <head>

          <meta charset="utf-8">

          <title>Carson</title>

          <script>

          function callAndroid(){

          // 由于對(duì)象映射,所以調(diào)用test對(duì)象等于調(diào)用Android映射的對(duì)象

          test.hello("js調(diào)用了android中的hello方法");

          }

          </script>

          </head>

          <body>

          //點(diǎn)擊按鈕則調(diào)用callAndroid函數(shù)

          <button type="button" id="button1" onclick="callAndroid()"></button>

          </body>

          </html>

          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19

          步驟3:在Android里通過WebView設(shè)置Android類與JS代碼的映射

          詳細(xì)請(qǐng)看注釋

          public class MainActivity extends AppCompatActivity {

          WebView mWebView;

          @Override

          protected void onCreate(Bundle savedInstanceState) {

          super.onCreate(savedInstanceState);

          setContentView(R.layout.activity_main);

          mWebView = (WebView) findViewById(R.id.webview);

          WebSettings webSettings = mWebView.getSettings();

          // 設(shè)置與Js交互的權(quán)限

          webSettings.setJavaScriptEnabled(true);

          // 通過addJavascriptInterface()將Java對(duì)象映射到JS對(duì)象

          //參數(shù)1:Javascript對(duì)象名

          //參數(shù)2:Java對(duì)象名

          mWebView.addJavascriptInterface(new AndroidtoJs(), "test");//AndroidtoJS類對(duì)象映射到j(luò)s的test對(duì)象

          // 加載JS代碼

          // 格式規(guī)定為:file:///android_asset/文件名.html

          mWebView.loadUrl("file:///android_asset/javascript.html");

          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24

          特點(diǎn)

          • 優(yōu)點(diǎn):使用簡單

          僅將Android對(duì)象和JS對(duì)象映射即可

          • 缺點(diǎn):存在嚴(yán)重的漏洞問題,具體請(qǐng)看文章:你不知道的 Android WebView 使用漏洞

          方式2:通過 WebViewClient 的方法shouldOverrideUrlLoading ()回調(diào)攔截 url

          • 具體原理:
          1. Android通過 WebViewClient 的回調(diào)方法shouldOverrideUrlLoading ()攔截 url
          2. 解析該 url 的協(xié)議
          3. 如果檢測(cè)到是預(yù)先約定好的協(xié)議,就調(diào)用相應(yīng)方法

          即JS需要調(diào)用Android的方法

          • 具體使用:
          • 步驟1:在JS約定所需要的Url協(xié)議
          • JS代碼:javascript.html

          以.html格式放到src/main/assets文件夾里

          <!DOCTYPE html>

          <html>

          <head>

          <meta charset="utf-8">

          <title>Carson_Ho</title>

          <script>

          function callAndroid(){

          /*約定的url協(xié)議為:js://webview?arg1=111&arg2=222*/

          document.location = "js://webview?arg1=111&arg2=222";

          }

          </script>

          </head>

          <!-- 點(diǎn)擊按鈕則調(diào)用callAndroid()方法 -->

          <body>

          <button type="button" id="button1" onclick="callAndroid()">點(diǎn)擊調(diào)用Android代碼</button>

          </body>

          </html>

          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20

          當(dāng)該JS通過Android的mWebView.loadUrl("file:///android_asset/javascript.html")加載后,就會(huì)回調(diào)shouldOverrideUrlLoading (),接下來繼續(xù)看步驟2:

          步驟2:在Android通過WebViewClient復(fù)寫shouldOverrideUrlLoading ()

          MainActivity.java

          public class MainActivity extends AppCompatActivity {

          WebView mWebView;

          // Button button;

          @Override

          protected void onCreate(Bundle savedInstanceState) {

          super.onCreate(savedInstanceState);

          setContentView(R.layout.activity_main);

          mWebView = (WebView) findViewById(R.id.webview);

          WebSettings webSettings = mWebView.getSettings();

          // 設(shè)置與Js交互的權(quán)限

          webSettings.setJavaScriptEnabled(true);

          // 設(shè)置允許JS彈窗

          webSettings.setJavaScriptCanOpenWindowsAutomatically(true);

          // 步驟1:加載JS代碼

          // 格式規(guī)定為:file:///android_asset/文件名.html

          mWebView.loadUrl("file:///android_asset/javascript.html");

          // 復(fù)寫WebViewClient類的shouldOverrideUrlLoading方法

          mWebView.setWebViewClient(new WebViewClient() {

          @Override

          public boolean shouldOverrideUrlLoading(WebView view, String url) {

          // 步驟2:根據(jù)協(xié)議的參數(shù),判斷是否是所需要的url

          // 一般根據(jù)scheme(協(xié)議格式) & authority(協(xié)議名)判斷(前兩個(gè)參數(shù))

          //假定傳入進(jìn)來的 url = "js://webview?arg1=111&arg2=222"(同時(shí)也是約定好的需要攔截的)

          Uri uri = Uri.parse(url);

          // 如果url的協(xié)議 = 預(yù)先約定的 js 協(xié)議

          // 就解析往下解析參數(shù)

          if ( uri.getScheme().equals("js")) {

          // 如果 authority = 預(yù)先約定協(xié)議里的 webview,即代表都符合約定的協(xié)議

          // 所以攔截url,下面JS開始調(diào)用Android需要的方法

          if (uri.getAuthority().equals("webview")) {

          // 步驟3:

          // 執(zhí)行JS所需要調(diào)用的邏輯

          System.out.println("js調(diào)用了Android的方法");

          // 可以在協(xié)議上帶有參數(shù)并傳遞到Android上

          HashMap<String, String> params = new HashMap<>();

          Set<String> collection = uri.getQueryParameterNames();

          }

          return true;

          }

          return super.shouldOverrideUrlLoading(view, url);

          }

          }

          );

          }

          }

          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37
          • 38
          • 39
          • 40
          • 41
          • 42
          • 43
          • 44
          • 45
          • 46
          • 47
          • 48
          • 49
          • 50
          • 51
          • 52
          • 53
          • 54
          • 55
          • 56
          • 57
          • 58
          • 59
          • 60

          特點(diǎn)

          • 優(yōu)點(diǎn):不存在方式1的漏洞;
          • 缺點(diǎn):JS獲取Android方法的返回值復(fù)雜。

          如果JS想要得到Android方法的返回值,只能通過 WebView 的 loadUrl ()去執(zhí)行 JS 方法把返回值傳遞回去,相關(guān)的代碼如下:

          // Android:MainActivity.java

          mWebView.loadUrl("javascript:returnResult(" + result + ")");

          // JS:javascript.html

          function returnResult(result){

          alert("result is" + result);

          }

          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7

          方式3:通過 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回調(diào)攔截JS對(duì)話框alert()、confirm()、prompt() 消息

          在JS中,有三個(gè)常用的對(duì)話框方法:

          方式3的原理:Android通過 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回調(diào)分別攔截JS對(duì)話框

          (即上述三個(gè)方法),得到他們的消息內(nèi)容,然后解析即可。

          下面的例子將用攔截 JS的輸入框(即prompt()方法)說明 :

          • 常用的攔截是:攔截 JS的輸入框(即prompt()方法)
          • 因?yàn)橹挥衟rompt()可以返回任意類型的值,操作最全面方便、更加靈活;而alert()對(duì)話框沒有返回值;confirm()對(duì)話框只能返回兩種狀態(tài)(確定 / 取消)兩個(gè)值

          步驟1:加載JS代碼,如下:

          javascript.html

          以.html格式放到src/main/assets文件夾里

          <!DOCTYPE html>

          <html>

          <head>

          <meta charset="utf-8">

          <title>Carson_Ho</title>

          <script>

          function clickprompt(){

          // 調(diào)用prompt()

          var result=prompt("js://demo?arg1=111&arg2=222");

          alert("demo " + result);

          }

          </script>

          </head>

          <!-- 點(diǎn)擊按鈕則調(diào)用clickprompt() -->

          <body>

          <button type="button" id="button1" onclick="clickprompt()">點(diǎn)擊調(diào)用Android代碼</button>

          </body>

          </html>

          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22

          當(dāng)使用mWebView.loadUrl("file:///android_asset/javascript.html")加載了上述JS代碼后,就會(huì)觸發(fā)回調(diào)onJsPrompt(),具體如下:

          • 如果是攔截警告框(即alert()),則觸發(fā)回調(diào)onJsAlert();
          • 如果是攔截確認(rèn)框(即confirm()),則觸發(fā)回調(diào)onJsConfirm();

          步驟2:在Android通過WebChromeClient復(fù)寫onJsPrompt()

          public class MainActivity extends AppCompatActivity {

          WebView mWebView;

          // Button button;

          @Override

          protected void onCreate(Bundle savedInstanceState) {

          super.onCreate(savedInstanceState);

          setContentView(R.layout.activity_main);

          mWebView = (WebView) findViewById(R.id.webview);

          WebSettings webSettings = mWebView.getSettings();

          // 設(shè)置與Js交互的權(quán)限

          webSettings.setJavaScriptEnabled(true);

          // 設(shè)置允許JS彈窗

          webSettings.setJavaScriptCanOpenWindowsAutomatically(true);

          // 先加載JS代碼

          // 格式規(guī)定為:file:///android_asset/文件名.html

          mWebView.loadUrl("file:///android_asset/javascript.html");

          mWebView.setWebChromeClient(new WebChromeClient() {

          // 攔截輸入框(原理同方式2)

          // 參數(shù)message:代表promt()的內(nèi)容(不是url)

          // 參數(shù)result:代表輸入框的返回值

          @Override

          public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {

          // 根據(jù)協(xié)議的參數(shù),判斷是否是所需要的url(原理同方式2)

          // 一般根據(jù)scheme(協(xié)議格式) & authority(協(xié)議名)判斷(前兩個(gè)參數(shù))

          //假定傳入進(jìn)來的 url = "js://webview?arg1=111&arg2=222"(同時(shí)也是約定好的需要攔截的)

          Uri uri = Uri.parse(message);

          // 如果url的協(xié)議 = 預(yù)先約定的 js 協(xié)議

          // 就解析往下解析參數(shù)

          if ( uri.getScheme().equals("js")) {

          // 如果 authority = 預(yù)先約定協(xié)議里的 webview,即代表都符合約定的協(xié)議

          // 所以攔截url,下面JS開始調(diào)用Android需要的方法

          if (uri.getAuthority().equals("webview")) {

          //

          // 執(zhí)行JS所需要調(diào)用的邏輯

          System.out.println("js調(diào)用了Android的方法");

          // 可以在協(xié)議上帶有參數(shù)并傳遞到Android上

          HashMap<String, String> params = new HashMap<>();

          Set<String> collection = uri.getQueryParameterNames();

          //參數(shù)result:代表消息框的返回值(輸入值)

          result.confirm("js調(diào)用了Android的方法成功啦");

          }

          return true;

          }

          return super.onJsPrompt(view, url, message, defaultValue, result);

          }

          // 通過alert()和confirm()攔截的原理相同,此處不作過多講述

          // 攔截JS的警告框

          @Override

          public boolean onJsAlert(WebView view, String url, String message, JsResult result) {

          return super.onJsAlert(view, url, message, result);

          }

          // 攔截JS的確認(rèn)框

          @Override

          public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {

          return super.onJsConfirm(view, url, message, result);

          }

          }

          );

          }

          }

          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37
          • 38
          • 39
          • 40
          • 41
          • 42
          • 43
          • 44
          • 45
          • 46
          • 47
          • 48
          • 49
          • 50
          • 51
          • 52
          • 53
          • 54
          • 55
          • 56
          • 57
          • 58
          • 59
          • 60
          • 61
          • 62
          • 63
          • 64
          • 65
          • 66
          • 67
          • 68
          • 69
          • 70
          • 71
          • 72
          • 73
          • 74
          • 75
          • 76
          • 77
          • 78

          • Demo地址
          • 上述所有代碼均存放在:Carson_Ho的Github地址 : WebView Demo

          2.2.2 三種方式的對(duì)比 & 使用場(chǎng)景


          3. 總結(jié)

          • 本文主要對(duì)Android通過WebView與JS的交互方式進(jìn)行了全面介紹

          • 關(guān)于WebView的系列文章對(duì)你有所幫助
          • Android開發(fā):最全面、最易懂的Webview詳解
          • Android:你不知道的 WebView 使用漏洞
          • 手把手教你構(gòu)建 Android WebView 的緩存機(jī)制 & 資源預(yù)加載方案
          • 接下來我會(huì)繼續(xù)講解其他安卓開發(fā)的知識(shí),有興趣可以繼續(xù)關(guān)注Carson_Ho的安卓開發(fā)筆記!!!!

          請(qǐng)?jiān)u論點(diǎn)贊!因?yàn)槟銈兊馁澩?鼓勵(lì)是我寫作的最大動(dòng)力!

          .前言

          目前很多公司的 App 就只使用一個(gè) WebView 作為整體框架, App 中的所有內(nèi)容全部使用 HTML5 進(jìn)行展示,這樣只需要寫一次 HTML5 代碼,就可以在 Android 和 iOS 平臺(tái)上運(yùn)行,這就是所謂的「 跨平臺(tái) 」。隨著 HTML5 的普及,很多 App 都會(huì)內(nèi)嵌 WebView 來加載 HTML5 頁面,即 Native 和 HTML5 共存,這就是當(dāng)下最流行的「 混合開發(fā) 」。HTML5 除了開發(fā)簡單,還有一個(gè)優(yōu)勢(shì)就是迭代方便, 只需要修改服務(wù)端的 HTML5 頁面,App 會(huì)同步更新,無論是做活動(dòng)推廣 App 還是及時(shí)修復(fù) Bug 都帶來的極大的便利。不過 HTML5 劣勢(shì)也很明顯,受制于國內(nèi)的網(wǎng)速限制。 雖然國內(nèi)已經(jīng)普及了 4g 網(wǎng)絡(luò),但是網(wǎng)速還是不盡如人意。HTML5 加載受限于網(wǎng)絡(luò),沒有原生控件流暢,用戶體驗(yàn)相對(duì)較差, 所以目前完全使用 HTML5 開發(fā) App 并沒有成為主流。我所在的項(xiàng)目組也使用HTML5開發(fā)比較頻繁,這個(gè)時(shí)候了解WebView使用就變得尤為重要了,而WebView的坑也是非常的多,我在開發(fā)中就遇到了許多莫名其妙的問題。 所以準(zhǔn)備寫幾篇文章總結(jié)一下,文章按照類來進(jìn)行分類。WebView開發(fā)常用的類是 WebView , WebSettings , WebViewClient , WebChromeClient。
          這里是WebView開發(fā)第一篇: WebView 的使用介紹;

          1. Android WebView 簡介
            ==
            我們先來看一下官方對(duì)Android WebView的介紹

          A View that displays web pages. This class is the basis upon which you can roll your own web browser or simply display some online content within your Activity. It uses the WebKit rendering engine to display web pages and includes methods to navigate forward and backward through a history, zoom in and out, perform text searches and more.

          總結(jié)起來就是:WebView是一個(gè)基于WebKit引擎的,并且可以在activity展現(xiàn)Web頁面的控件。

          1. 簡單使用
            ==
            3.1、添加網(wǎng)絡(luò)權(quán)限
          <uses-permission android:name="android.permission.INTERNET" />
          

          3.2 添加布局頁面
          這里介紹另外一種方式,通過addView添加進(jìn)去
          1.在布局頁面添加布局

            <FrameLayout
                  android:id="@+id/webViewWrap"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  android:visibility="visible" />
          

          2.實(shí)體化webview并添加到布局中

          		webViewWrap = findViewById(R.id.webViewWrap); //上面的FrameLayout
                  webView = new WebView(MyApplication.getAppContext()); //使用應(yīng)用上下文,可以防止內(nèi)存泄露,如果傳入activity的上下文,需要將webview remove掉。下面有講解。
                  webViewWrap.addView(webView);
          

          3.加載頁面

          //方式1. 加載一個(gè)網(wǎng)頁:
            webView.loadUrl("http://www.google.com/");
          
            //方式2:加載apk包中的html頁面
            webView.loadUrl("file:///android_asset/test.html");
          
            //方式3:加載手機(jī)本地的html頁面
             webView.loadUrl("content://com.android.htmlfileprovider/sdcard/test.html");
          
             // 方式4: 加載 HTML 頁面的一小段內(nèi)容
            WebView.loadData(String data, String mimeType, String encoding)
          // 參數(shù)說明:
          // 參數(shù)1:一段HTML代碼
          // 參數(shù)2:展示內(nèi)容的類型
          // 參數(shù)3:字節(jié)碼
          

          到這一步我們就能夠展示一個(gè)WebView頁面了,不過是通過外部瀏覽器打開的。但是還有許多優(yōu)化的地方。

          4.WebView的狀態(tài)

          //激活WebView為活躍狀態(tài),能正常執(zhí)行網(wǎng)頁的響應(yīng),可以在activity 的回調(diào)方法中調(diào)用
          webView.onResume() ;
          
          //當(dāng)頁面被失去焦點(diǎn)被切換到后臺(tái)不可見狀態(tài),需要執(zhí)行onPause,可以在activity 的回調(diào)方法中調(diào)用
          //通過onPause動(dòng)作通知內(nèi)核暫停所有的動(dòng)作,比如DOM的解析、plugin的執(zhí)行、JavaScript執(zhí)行。
          webView.onPause();
          
          //當(dāng)應(yīng)用程序(存在webview)被切換到后臺(tái)時(shí),這個(gè)方法不僅僅針對(duì)當(dāng)前的webview而是全局的全應(yīng)用程序的webview
          //它會(huì)暫停所有webview的layout,parsing,javascripttimer。降低CPU功耗。
          webView.pauseTimers()
          
          //恢復(fù)pauseTimers狀態(tài)
          webView.resumeTimers();
          
          //銷毀Webview
          //在關(guān)閉了Activity時(shí),如果Webview的音樂或視頻,還在播放。就必須銷毀Webview
          //但是注意:webview調(diào)用destory時(shí),webview仍綁定在Activity上
          //這是由于自定義webview構(gòu)建時(shí)傳入了該Activity的context對(duì)象
          //因此需要先從父容器中移除webview,然后再銷毀webview:
          ViewParent parent = mWebView.getParent();
                  if (parent != null) {
                      ((ViewGroup) parent).removeView(mWebView);// 防止內(nèi)存泄露
                  } 
          webView.destroy();
          
          1. 關(guān)于前進(jìn) / 后退網(wǎng)頁
            ==
          //是否可以后退
          Webview.canGoBack() 
          //后退網(wǎng)頁
          Webview.goBack()
          
          //是否可以前進(jìn)                     
          Webview.canGoForward()
          //前進(jìn)網(wǎng)頁
          Webview.goForward()
          
          //以當(dāng)前的index為起始點(diǎn)前進(jìn)或者后退到歷史記錄中指定的steps
          //如果steps為負(fù)數(shù)則為后退,正數(shù)則為前進(jìn)
          Webview.goBackOrForward(intsteps)
          

          常見用法:Back鍵控制網(wǎng)頁后退

          問題:在不做任何處理前提下 ,瀏覽網(wǎng)頁時(shí)點(diǎn)擊系統(tǒng)的“Back”鍵,整個(gè) Browser 會(huì)調(diào)用 finish()而結(jié)束自身
          目標(biāo):點(diǎn)擊返回后,是網(wǎng)頁回退而不是
          推出瀏覽器
          解決方案:在當(dāng)前Activity中處理并消費(fèi)掉該 Back 事件

          1. 清除緩存數(shù)據(jù)
            ==
          //清除網(wǎng)頁訪問留下的緩存
          //由于內(nèi)核緩存是全局的因此這個(gè)方法不僅僅針對(duì)webview而是針對(duì)整個(gè)應(yīng)用程序.
          Webview.clearCache(true);
          
          //清除當(dāng)前webview訪問的歷史記錄
          //只會(huì)webview訪問歷史記錄里的所有記錄除了當(dāng)前訪問記錄
          Webview.clearHistory();
          
          //這個(gè)api僅僅清除自動(dòng)完成填充的表單數(shù)據(jù),并不會(huì)清除WebView存儲(chǔ)到本地的數(shù)據(jù)
          Webview.clearFormData();
          

          WebView 的使用介紹就先到這里了,下一篇將會(huì)講解WebSettings的使用。

          結(jié):

          Android 調(diào)用 js:

          在 Android 中創(chuàng)建通往 javascript 的接口;

          在 html 中定義要執(zhí)行的方法;

          在 Android 中的具體事件中進(jìn)行調(diào)用。

          <pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word;">contentWebView.loadUrl("javascript:javacalljs()");

          </pre>


          <pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word;">

          js中調(diào)用Android 方法 :

          html中調(diào)用 Android 方法則反來,在 Andorid 中定義要調(diào)用的方法, html 中綁定事件進(jìn)行調(diào)用。 </pre>

          <pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word;"><button onclick="window.wjj.startFunction()">點(diǎn)擊調(diào)用java 代碼</button></pre>


          Android 展示 html 頁面

          (1)project 視圖下,在 Android 工程中新建目錄 assets;

          image

          (2)在 assets 目錄下新建 html 頁面 如 show.html;

          (3)Android 界面中在 WebView 中展示 show.html;

          (4)Android 原生按鈕點(diǎn)擊執(zhí)行 html 中的 js 方法;

          image

          界面設(shè)計(jì):

          image

          html 中的 js:

          image

          效果:

          image


          js 調(diào)用 android 方法

          還是需要一個(gè)接口:

          image

          Andorid中定義相應(yīng)的執(zhí)行方法(注意帶上相應(yīng)的注解):

          image

          html 中進(jìn)行調(diào)用:

          image

          效果(彈的吐司沒截下來):


          主站蜘蛛池模板: 久久精品动漫一区二区三区| 杨幂AV污网站在线一区二区| 蜜桃传媒一区二区亚洲AV| 国产精品一级香蕉一区| 精品成人一区二区三区免费视频| 国产人妖视频一区二区| 免费无码一区二区三区蜜桃大| 日韩爆乳一区二区无码| 日韩精品电影一区亚洲| 午夜视频一区二区| 亚洲av色香蕉一区二区三区蜜桃 | 精品亚洲A∨无码一区二区三区| 成人国产精品一区二区网站| 午夜一区二区在线观看| 精品人妻无码一区二区三区蜜桃一| 国产精品无圣光一区二区 | 国产精品视频无圣光一区| 久久精品无码一区二区WWW| 无码国产精成人午夜视频一区二区| 国产一区二区三区高清视频| 精品国产日韩亚洲一区| 一区二区三区AV高清免费波多| 国产丝袜无码一区二区视频| 无码人妻精品一区二区三区不卡| 亚洲一区二区三区亚瑟| 亚洲美女视频一区二区三区| 久久国产精品无码一区二区三区| 无码国产精品一区二区免费式芒果| 久久久无码精品国产一区| 亚洲一区二区三区高清| 亚洲福利一区二区精品秒拍| 精品亚洲AV无码一区二区三区| 国产精品亚洲午夜一区二区三区| 综合无码一区二区三区四区五区 | 国产色综合一区二区三区| 国产精品无码AV一区二区三区| 寂寞一区在线观看| 人妻无码久久一区二区三区免费 | 丝袜美腿一区二区三区| 国产乱码精品一区三上| 国产精品一区二区三区免费|