最近公司再添加功能的時候,有一部分功能是用的html,在一個瀏覽器或webview中展示出html即可。當然在這里我們當然用webview控件嘍 WebApp的好處: 在應用里嵌套web的好處有這么幾點,1,跨平台,不僅可以在Android上運行,也可以在iOS上運行,而且樣式什么的絕對統一,因為都是加載的html,用的都是同一套html 2,修改靈活,容易更新版本。例如大家常看到的app里面的廣告頁,大多是嵌套的html,這樣只要后台替換一下頁面的內容,手機端就會改變展現內容,跟新版本也是如此,因為界面什么得成了在服務器端,所以要是想跟新界面什么得,只需要在后台修改在發布即可,不需要用戶再重新下載app。這個好處我覺得對ios是有很大幫助的,哈哈,繞開蘋果審核嘛,由於html我們可以隨意替換,審核時可以把違規的部分隱藏,上線之后就可以隨意改了,哈哈,你們懂得。 當然,開發webapp當然也有局限,就是網速什么的,這個咱無法改變,這里也不廢話。不過在開發中呢,如果只是頁面之間的交互的話,我們只需提供一個webview控件即可, 可是要是涉及到和手機設備或軟件交互的話(如打開相冊,攝像頭等等),這就需要我們和頁面經行js交互,js交互可以說是雙向的,一種是,我們調用頁面的,就是調用服務端的js方法,另一個呢則是服務端調用我們Android里面的代碼,調用其實很簡單,下面說一下怎樣調用。 當然我們先等有一個WebView,先創建一個Activity,然后設置布局,穿件WebView,布局和Activity如下: activity_webview.xml [html] view plain copy print?在CODE上查看代碼片派生到我的代碼片 01.<?xml version="1.0" encoding="utf-8"?> 02.<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 03. android:layout_width="match_parent" 04. android:layout_height="match_parent" 05. android:orientation="vertical" > 06. <WebView 07. android:id="@+id/webview" 08. android:layout_width="match_parent" 09. android:layout_height="match_parent" 10. /> 11. 12.</LinearLayout> 然后是activity, WebViewActivity.activity [java] view plain copy print?在CODE上查看代碼片派生到我的代碼片 01.import android.app.Activity; 02.import android.os.Bundle; 03.import android.webkit.WebSettings; 04.import android.webkit.WebView; 05. 06.public class WebViewActivity extends Activity { 07. private static final String url = "http://192.168.30.199:8080/song/test.html"; 08. private WebView mWebView; 09. @Override 10. protected void onCreate(Bundle savedInstanceState) { 11. super.onCreate(savedInstanceState); 12. setContentView(R.layout.activity_webviw); 13. initView(); 14. } 15. 16. private void initView() { 17. mWebView = (WebView) findViewById(R.id.webview); 18. //或的WebView的Setting 19. WebSettings settings = mWebView.getSettings(); 20. //設置支持js,看方法名字就知道啥意思 21. settings.setJavaScriptEnabled(true); 22. //加載網頁路徑 23. mWebView.loadUrl(url); 24. } 25.} 上面就是一個簡單的webview,然后很常規的設置屬性,然后再加載要加載的頁面路徑,這樣一般就可在網頁里面自由點擊跳轉了,但是要和手機交互的話需要我們寫js交互的代碼了。 首先說怎樣調用服務器端的js方法,很簡單,和加載網頁路徑基本上一樣如下: [java] view plain copy print?在CODE上查看代碼片派生到我的代碼片 01.mWebView.loadUrl("javascript:forSmallPhoto()"); 就這么簡單的一句話你就可以調用服務器端的js方法了,其中JavaScript:是固定寫法forSmallPhoto()則是服務端的js方法名字,這是一個無參數的方法,當然也可以傳參,這需要我們拼湊字符串,mWebView.loadUrl("javascript:forSmallPhoto('" + data + "')");其中data就是一個變量,也就是你要傳的參數值,當然也可以支持多參數傳送,這得看你服務器端的js方法有幾個參數了,其實就是我們調用一個方法一樣,只不過這個方法是在服務器端的。我們調用服務器js,是為了,當Android完成某些功能后,需要告訴服務器,則我們可以調用js來告訴他我們完成了。 在一種就是,服務端調用我們的Android代碼了,這里Android中也是封裝好了接口 我們可以通過void android.webkit.WebView.addJavascriptInterface(Object object, String name)的方法來實現服務器端調用我們的代碼,其中這個方法有兩個參數,一個是object,另一個是String類型的; 只要webview調用了這個方法就可以調用我們的代碼了。而要調用的代碼我們寫在Object里面,首先我們就先實現這個Object,我們創建一個類,JavaScriptInterface。Android中APi Guides中提供的Demo中取得累的名字是JavaScriptInterface,那我們也用這個名字把。然后實現它,然后隨便在里面寫一個方法,如下面 JavaScriptInterface.Java類 [java] view plain copy print?在CODE上查看代碼片派生到我的代碼片 01.import java.util.HashMap; 02.import java.util.Map; 03. 04.import android.content.Context; 05.import android.os.Handler; 06.import android.os.Message; 07.import android.text.TextUtils; 08.import android.util.Log; 09.import android.webkit.JavascriptInterface; 10.import android.widget.Toast; 11. 12./** 13. * 14. * Title: JavaScriptInterface.java Description: 15. * 16. * @author Liusong 17. * @version V1.0 18. */ 19.public class JavaScriptInterface { 20. 21. /** Instantiate the interface and set the context */ 22. public JavaScriptInterface() { 23. } 24. 25. /** Show a toast from the web page */ 26. @JavascriptInterface 27. public void showToast() { 28. Log.i("TAG", "調用成功==================》》》》》"); 29. 30. } 31. 32.} 這樣就完成了一個簡單的JavaScriptInterface類,這個類的方法是自己隨便寫的,其中,先說一下這里要注意的幾點,首先重要的@JavascriptInterface這個注解,你會發現去掉也不會報錯,但是這個是很早重要的,如果你想讓服務器端調用你的方法,你就要加上這個注解@JavascriptInterface。在4.4api中說道,一定要加這個注解,負責調用不會成功,其實我在開發中,用紅米1s,4.3的系統,就沒法調用成功了,當時還納悶,因為當時手里的文檔是4.2的,很是郁悶。所以在這里強掉,一定要在自己寫的方法前面加上@JavascriptInterface。 還有一個注意的是方法的參數,這里是一個無參方法,當然這里你也可以寫一個有參方法,這里先提一下,待會會配合html里面的js說道,我們先說void android.webkit.WebView.addJavascriptInterface(Object object, String name)這個方法里面的第二個參數,第二個參數你可以理解為是標識符,就是服務器端調用你方法時,需要找到你,怎么找到?就是通過這個標識符,標識符是自己隨便定的,但是,你要告訴后台開發人員你的標識符是什么,我們這里把這第二個參數設置為“Android”。下面我給出我測試的html代碼結合着看你就明白了。 test.html [html] view plain copy print?在CODE上查看代碼片派生到我的代碼片 01.<!doctype html> 02.<html> 03.<head> 04. <meta name="viewport" content="width=device-width, initial-scale=1" charset="GBK"> 05. <title>測試</title> 06.</head> 07. 08.<body> 09. 10.<div data-role="page" > 11. 12.<script type="text/javascript"> 13. function callAndroidAction(action) { 14. Android.showToast(); alert("我敢保證,你現在用的是演示一"); 15. } 16. function forSmallPhoto(action) { 17. alert("我敢保證,你現在用的是演示一"+action); 18. } 19.</script> 20. 21. <div data-role="header"> 22. <h1>調用圖庫</h1> 23. <!-- <a href="#" class="ui-btn">返回</a>--> 24. </div> 25. 26. <div data-role="main" class="ui-content"> 27. 28. <div style="width: 98%;margin: 0 auto; text-align: center"> 29. <a href="#" class=" ui-btn ui-btn-inline" onclick="callAndroidAction(0)">調用圖庫 </a> 30. 31. <a href="#" class=" ui-btn ui-btn-inline" onclick="callAndroidAction('2')"> 充值 </a> 32. 33. </div> 34. 35. 36. </div> 37. 38. 39.</div> 40. 41.</body> 42. 43. 44.</html> 這個代碼有點亂,就將就這看吧,我是把這個頁面放在自己的tomcat上的,其中這個html中大家發現 [html] view plain copy print?在CODE上查看代碼片派生到我的代碼片 01.<script type="text/javascript"> 02. function callAndroidAction(action) { 03. Android.showToast(); 04. alert("我敢保證,你現在用的是演示一"); 05. } 06. function forSmallPhoto(action) { 07. alert("我敢保證,你現在用的是演示一"+action); 08. } 09.</script> 這個js方法沒,看見里面的Android標識符沒,沒錯,后台就是這么調用我們代碼的,Android.showToast();就是這么調用的,就是這么簡單,不要想的太難,我們就需按我上面說的那樣,把Object實現,把標識符寫好就ok了。飯后,后台就會通過標識符和你Object的方法名字調用你的方法。這里要說一下,你Object(即JavaScriptInterface,我們上面已經實現)里的方法的參數要和后台調用你的方法的參數個數和類型一直,就像我們平時調用方法是一樣的。這一點知道了就好了。 這樣就可以了。 所以WebViewActivity里面加上這一句就可以了。 [java] view plain copy print?在CODE上查看代碼片派生到我的代碼片 01.view.addJavascriptInterface(new JavaScriptInterface(),"Android"); 這樣js就說完了。 模版 當后台要調用我們的代碼,我們就寫一個方法,如果調用多次我們就寫多個,這樣太麻煩,所以我們來寫一個通用的方法,就是無論后台調用你代碼干不同的事,都調用你這個方法,那怎么區分不同的執行動作呢?用傳的參數,我們在JavaScriptInterface里面寫一個方法,這里就叫callAndroidAction,我設計的是給這個方法三個參數, public void callAndroidAction(String action, String url,String json),第一個參數action,即用來表示要執行的動作,第二個則是url,不管是服務其給的下載路徑還是,訪問其他頁面的路徑,在一個json就是其他一些參數,由於傳的參數不固定,我們就用一個參數,一個參數時就傳過來,多個參數時可以通過json字符串傳過來,就沒必要麻煩一個一個的寫參數了。 然后我們在設計一個回調,讓操作的代碼拿出去,怎大體就是這樣了 [java] view plain copy print?在CODE上查看代碼片派生到我的代碼片 01.import java.util.HashMap; 02.import java.util.Map; 03. 04.import android.content.Context; 05.import android.os.Handler; 06.import android.os.Message; 07.import android.text.TextUtils; 08.import android.util.Log; 09.import android.webkit.JavascriptInterface; 10.import android.widget.Toast; 11. 12./** 13. * 14. * Title: JavaScriptInterface.java Description: 15. * 16. * @author Liusong 17. * @version V1.0 18. */ 19.public class JavaScriptInterface { 20. 21. private Handler mHandler; 22. 23. /** Instantiate the interface and set the context */ 24. public JavaScriptInterface(Handler handler) { 25. mHandler = handler; 26. } 27. 28. /** Show a toast from the web page */ 29. @JavascriptInterface 30. public void showToast(final String toast) { 31. Log.i("TAG", "調用成功==================》》》》》"); 32. } 33. 34. @JavascriptInterface 35. public void callAndroidAction(String action, String url,String json) { 36. Map<String, String> params = new HashMap<String, String>(); 37. if(!TextUtils.isEmpty(url)){ 38. params.put("url", url); 39. } 40. if(!TextUtils.isEmpty(json)){ 41. params.put("json", json); 42. } 43. Message msg = Message.obtain(); 44. msg.what = Integer.valueOf(action); 45. msg.obj = params; 46. mHandler.sendMessage(msg); 47. } 48.} 這樣我們就從服務其拿到的參數都給Handler了,則WebViewActivity里面就要這樣寫了 [java] view plain copy print?在CODE上查看代碼片派生到我的代碼片 01.import java.util.HashMap; 02.import java.util.Map; 03. 04.import android.app.Activity; 05.import android.os.Bundle; 06.import android.os.Handler; 07.import android.os.Message; 08.import android.webkit.WebSettings; 09.import android.webkit.WebView; 10. 11.public class WebViewActivity extends Activity { 12. private static final String url = "http://192.168.30.199:8080/song/test.html"; 13. 14. //執行動作 15. public static final int SELECT_IMAGE = 0;// 打開圖庫 16. public static final int OPEN_PAGE = 1;// 跳轉其他特定頁面 17. public static final int CLOSE_OR_BACK = 2;// 關閉或 18. 19. private WebView mWebView; 20. @Override 21. protected void onCreate(Bundle savedInstanceState) { 22. super.onCreate(savedInstanceState); 23. setContentView(R.layout.activity_webviw); 24. initView(); 25. } 26. <p> 27. private void getIntentDatas() { 28. // TODO Auto-generated method stub 29. url = getIntent().getStringExtra("url"); 30. }</p><p> </p> private void initView() { 31. mWebView = (WebView) findViewById(R.id.webview); 32. //或的WebView的Setting 33. WebSettings settings = mWebView.getSettings(); 34. //設置支持js,看方法名字就知道啥意思 35. settings.setJavaScriptEnabled(true); 36. mWebView.addJavascriptInterface(new JavaScriptInterface(handler), "Android"); 37. //加載網頁路徑 38. mWebView.loadUrl(url); 39. } 40. 41. private Handler handler = new Handler(){ 42. public void handleMessage(Message msg) { 43. switch (msg.what) { 44. case SELECT_IMAGE://執行打開圖庫, 45. 46. //如果有參數,取服務端傳過來的參數(url,json) 47. Map<String, String> params = (HashMap<String, String>)msg.obj; 48. break; 49. 50. //其他功能,可隨着自己功能的增加,在這里增加,只需和后台商量好動作的action值即可 51. default: 52. break; 53. } 54. }; 55. }; 56.} 最后再讓WebViewActivity通用,就是通過傳url參數 [java] view plain copy print?在CODE上查看代碼片派生到我的代碼片 01.private void getIntentDatas() { 02. // TODO Auto-generated method stub 03. url = getIntent().getStringExtra("url"); 04.}
