一處疑難雜症的術後總結:WebView和JavaScript之間的互動

來源:互聯網
上載者:User

標籤:navigator   jsp   property   電話   協助   內容   函數   use   get   

近期在公司裡參與了M3項目的開發,這個項目是使用HTML5開發的前端頁面,在開發完成後,把項目地址寫入Android、iOS的殼原始碼裡面,這樣當應用被開啟時候自己主動附加元件目首頁的URL。這樣的做法對於使用者來說,能夠不用更新client,對於開發人員來說,發現問題能夠及時修複並更新,當然這也是B/S軟體的長處。

在這個APP裡面是有個撥號功能的,即點擊介面上的電話小表徵圖。能夠直接通過手機撥出號碼。

昨天同事丁丁告知我們這個APP有個BUG:在iOS裡面撥號是沒有問題的,可是在Android裡面撥號時。會跳轉到一個報錯頁面,類似於我們常見的404頁面。無法實現撥號操作。我們的代碼寫的就是常見的tel:19212345678這樣的。

我先講一下我們的處理過程。

話說知之為知之。不知百度知。

所以在接到問題反饋後,我和同事明明先到百度上面搜尋了一下,得到下面的結果:

在開源中國社區裡面,有人建議在tel:後面加上雙斜杠,類似tel://19212345678。我看到後立刻試了一下。不行。

在還有一個網站裡面,有人建議在號碼背後加上的官網地址。

類似tel:19212345678#weixin.qq.com。

我試了一下。還是老樣子。

同事們聚在一起看了下,這段撥號的代碼,在iOS上面是沒有不論什麼問題的,在的內建的瀏覽器裡面是沒有不論什麼問題的。在Android手機內建的瀏覽器裡面也是沒有不論什麼問題的。只有在打包成APP後訪問時出了問題!

後來同事華華給我發來一段代碼。這個是在設定屬性的時候重寫shouldOverrideUrlLoading(WebView view, String url)這種方法。代碼大意是,先推斷傳入的URL是不是以“tel:”開頭的,假設是的,那就運行撥號操作;假設不是的。那就運行載入URL的操作。

我加進去試了一下,這下能夠撥號了,可是不能高興得太早。

還發現有個小問題,在撥號介面彈出的同一時候。那個類似404的錯誤介面還是會彈出來的,僅僅只是是被撥號的介面給遮擋住了。在通話完成掛機之後,那個錯誤介面又會出來。


今天丁丁又在催問這個撥號的問題了,我說我僅僅完畢了50%。還有個小問題還沒解決。我還不愜意。

丁丁狡猾地說道:假設你今天不能解決,我也不愜意。

下午我把手頭上的任務完畢了之後,就又開始研究這個奇葩的問題了。同事濤濤和華華也過來協助把脈。

同事濤濤在QQ上給我發的幾個網址。我都點開一一試了下。

第一個是重寫shouldOverrideUrlLoading(WebView view, String url)這種方法的。我回複說昨天已經試過了,能生效可是錯誤的介面還是會跟著彈出,體驗不是非常好;

第二個是使用wati協議撥打到電話。類似<a href="wtai://wp//mc;10086">撥打10086 </a>  。我回複說這個也試了,也是不起作用。

在同事華華的建議下,我把模擬器開啟了,研究了下載整個撥號操作中的過程,花費了一些時間。

除了證明shouldOverrideUrlLoading這段代碼的推斷是對的。並沒有什麼其它的收穫。

正當一籌莫展的時候,華華忽然想起了一年前和還有一位同事做的戶型圖展示功能。當時也是因為技術的局限性不得不使用js調用了Android的瀏覽器API,想看看能不能仿照那個問題的解決思路來解決這個撥號的問題。

這個WebView與js的互動是在jsp頁面上定義個函數。

在Android殼原始碼裡面通過addJavascriptInterface(new JavascriptInterface(this),"jsInterface")來加入定義在jsp頁面上定義的js介面。當然前提是要在殼原始碼裡面加入javascript互動支援。這個我已經加了。

在jsp裡面,原來的<a href=”tel:XXX”>已經被改造成了個點擊事件,詳細的運行內容寫在了js函數裡面,從而避免了會被識別為個超連結而跳到一個404頁面。

假設你覺得在這裡就成功了,那也太easy了。

試了一下,點擊圖片後頁面是一明一暗地閃爍,並沒有運行撥號操作。

在Logcat看到,它事實上是沒取到值的。是在取值的時候的時候出了問題?我把取值的${clientInfoVO.clientMobile}換成了<s:property value=‘clientMobile‘ />。居然就取到值了!

剩下的就是針對Android和iOS兩種作業系統進行推斷了。


感謝你有足夠的耐心看完了上面這長長的流水賬,假設你也遇到了和我類似的問題,那麼你是幸運的。

以下我總結下WebView與js互動這類的問題的解決的方法:

1、在Android殼原始碼裡面加入許可權聲明:

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

須要聲明打電話的許可權並擷取使用者授權,不然不能通過Android殼去運行撥號操作。

假設你要是要發簡訊,那就是簡訊相關的許可權啦,靈活處理;

2、在Android殼原始碼裡面啟用JavaScript支援:

contentWebView.getSettings().setJavaScriptEnabled(true);

這樣才幹在殼原始碼裡面調用web頁面的js函數

3、重寫shouldOverrideUrlLoading(WebView view, String url)方法。對符合和不符合的兩種URL進行推斷,並運行不同的操作。示範範例代碼例如以下:

public boolean shouldOverrideUrlLoading(WebView view, String url) {        if (url.startsWith("tel:")) {                 Intent intent = new Intent(Intent.ACTION_VIEW,                        Uri.parse(url));                 startActivity(intent);                             return false;        } else {        view.loadUrl(url);        return true;}    }

4、在web頁面的連結改造成調用js函數,在函數裡面運行類似window.js互動介面名.js函數名()

示範範例代碼例如以下:

function exitSys(tel){window.jsInterface.exitSys(tel);}

5、在Android殼原始碼裡面相應加上js介面聲明,比方我的名稱是jsInterface,就是在第四步裡面寫的js互動介面名:

contentWebView.addJavascriptInterface(new JavascriptInterface(this),"jsInterface");

6、在JavascriptInterface類裡面聲明與js 相應的方法。這裡我就寫在Android裡面運行撥打到電話的代碼。

比如:

public void exitSys(String number) {   Intent intent = new Intent(Intent.ACTION_CALL,Uri.parse("tel:"+number));                 startActivity(intent);  }

7、須要被調用的這個js裡面假設須要動態傳參,給這個js函數相關的參數值賦值最好用<s:property >。而不要用${}

否則可能會莫名其妙地取不到值(假設你在模擬器上測試,出現invalid MMI code的時候。也能夠說明成功了。

由於模擬器是沒有與通訊電訊廠商聯通的,所以會報這個小錯誤,這時候建議你能夠換用真機去測試);

8、在web頁面加上瀏覽器推斷:預設運行tel:,假設是iOS瀏覽器。就繼續沿用之前萬能的<a href=”tel:XXX”>,假設是Android瀏覽器,就運行自己定義的這個js函數,改變點擊操作調用的URL。

<a href="tel:<s:property value=‘clientMobile‘ />" ><img src="<%=basePath %>crm/html5_new/myCustomer/images/phone.png"></a>

$(document).ready(function(){$("a").each(function(){var u = navigator.userAgent;if(u.indexOf(‘iPhone‘) > -1){}else {if($(this).attr("href").length>4&&$(this).attr("href").indexOf("tel:")==0){$(this).attr("href","javascript:exitSys(‘"+$(this).attr("href").replace("tel:","")+"‘)");}}});});


一處疑難雜症的術後總結:WebView和JavaScript之間的互動

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.