標籤: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之間的互動