Android應用開發-------------WebView(一)之WebView與服務器端的Js交互

博客爲 有時個哥 原創,如需轉載請標明出處:http://blog.csdn.net/ls703/article/details/45504021


最近公司再添加功能的時候,有一部分功能是用的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

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

</LinearLayout>

然後是activity,

WebViewActivity.activity

import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebSettings;
import android.webkit.WebView;

public class WebViewActivity extends Activity {
	private static final String url = "http://192.168.30.199:8080/song/test.html";
	private WebView mWebView;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_webviw);
		initView();
	}

	private void initView() {
		mWebView = (WebView) findViewById(R.id.webview);
		//或的WebView的Setting
		WebSettings settings = mWebView.getSettings();
		//設置支持js,看方法名字就知道啥意思
		settings.setJavaScriptEnabled(true);
		//加載網頁路徑
		mWebView.loadUrl(url);
	}
}

上面就是一個簡單的webview,然後很常規的設置屬性,然後再加載要加載的頁面路徑,這樣一般就可在網頁裏面自由點擊跳轉了,但是要和手機交互的話需要我們寫js交互的代碼了。

首先說怎樣調用服務器端的js方法,很簡單,和加載網頁路徑基本上一樣如下:

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類

import java.util.HashMap;
import java.util.Map;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.JavascriptInterface;
import android.widget.Toast;

/**
 * 
 * Title: JavaScriptInterface.java Description:
 * 
 * @author Liusong
 * @version V1.0
 */
public class JavaScriptInterface {	
		
	/** Instantiate the interface and set the context */
	public JavaScriptInterface() {
	}

	/** Show a toast from the web page */
	@JavascriptInterface
	public void showToast() {
		Log.i("TAG", "調用成功==================》》》》》");

	}

}


這樣就完成了一個簡單的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

<!doctype html>
<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1" charset="GBK">
    <title>測試</title>
</head>

<body>

<div data-role="page" >
    
<script type="text/javascript">
	 function callAndroidAction(action) {
		Android.showToast();		alert("我敢保證,你現在用的是演示一");
    }
	 function forSmallPhoto(action) {
		alert("我敢保證,你現在用的是演示一"+action);
    }
</script>

    <div data-role="header">
        <h1>調用圖庫</h1>
        <!--   <a href="#" class="ui-btn">返回</a>-->
    </div>

    <div data-role="main" class="ui-content">

        <div style="width: 98%;margin: 0 auto; text-align: center">
            <a href="#" class=" ui-btn ui-btn-inline" onclick="callAndroidAction(0)">調用圖庫  </a>
            
			<a href="#" class=" ui-btn ui-btn-inline" onclick="callAndroidAction('2')"> 充值  </a>
        
        </div>


    </div>

   
</div>

</body>


</html>


這個代碼有點亂,就將就這看吧,我是把這個頁面放在自己的tomcat上的,其中這個html中大家發現
 

<script type="text/javascript">
    function callAndroidAction(action) {
		Android.showToast();
		alert("我敢保證,你現在用的是演示一");
    }
   function forSmallPhoto(action) {
		alert("我敢保證,你現在用的是演示一"+action);
    }
</script>


 

這個js方法沒,看見裏面的Android標識符沒,沒錯,後臺就是這麼調用我們代碼的,Android.showToast();就是這麼調用的,就是這麼簡單,不要想的太難,我們就需按我上面說的那樣,把Object實現,把標識符寫好就ok了。飯後,後臺就會通過標識符和你Object的方法名字調用你的方法。這裏要說一下,你Object(即JavaScriptInterface,我們上面已經實現)裏的方法的參數要和後臺調用你的方法的參數個數和類型一直,就像我們平時調用方法是一樣的。這一點知道了就好了。

這樣就可以了。

所以WebViewActivity裏面加上這一句就可以了。

view.addJavascriptInterface(new JavaScriptInterface(),"Android");

 

這樣js就說完了。

模版

當後臺要調用我們的代碼,我們就寫一個方法,如果調用多次我們就寫多個,這樣太麻煩,所以我們來寫一個通用的方法,就是無論後臺調用你代碼幹不同的事,都調用你這個方法,那怎麼區分不同的執行動作呢?用傳的參數,我們在JavaScriptInterface裏面寫一個方法,這裏就叫callAndroidAction,我設計的是給這個方法三個參數,

public void callAndroidAction(String action, String url,String json),第一個參數action,即用來表示要執行的動作,第二個則是url,不管是服務其給的下載路徑還是,訪問其他頁面的路徑,在一個json就是其他一些參數,由於傳的參數不固定,我們就用一個參數,一個參數時就傳過來,多個參數時可以通過json字符串傳過來,就沒必要麻煩一個一個的寫參數了。

然後我們在設計一個回調,讓操作的代碼拿出去,怎大體就是這樣了

import java.util.HashMap;
import java.util.Map;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.JavascriptInterface;
import android.widget.Toast;

/**
 * 
 * Title: JavaScriptInterface.java Description:
 * 
 * @author Liusong
 * @version V1.0
 */
public class JavaScriptInterface {
	
	private Handler mHandler;
	
	/** Instantiate the interface and set the context */
	public JavaScriptInterface(Handler handler) {
		mHandler = handler;
	}

	/** Show a toast from the web page */
	@JavascriptInterface
	public void showToast(final String toast) {
		Log.i("TAG", "調用成功==================》》》》》");
	}

	@JavascriptInterface
	public void callAndroidAction(String action, String url,String json) {
		Map<String, String> params = new HashMap<String, String>();
		if(!TextUtils.isEmpty(url)){
			params.put("url", url);
		}
		if(!TextUtils.isEmpty(json)){
			params.put("json", json);
		}
		Message msg = Message.obtain();
		msg.what = Integer.valueOf(action);
		msg.obj = params;
		mHandler.sendMessage(msg);
	}
}


這樣我們就從服務其拿到的參數都給Handler了,則WebViewActivity裏面就要這樣寫了

import java.util.HashMap;
import java.util.Map;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.webkit.WebSettings;
import android.webkit.WebView;

public class WebViewActivity extends Activity {
	private static final String url = "http://192.168.30.199:8080/song/test.html";
	
	//執行動作
	public static final int SELECT_IMAGE = 0;// 打開圖庫
	public static final int OPEN_PAGE = 1;// 跳轉其他特定頁面
	public static final int CLOSE_OR_BACK = 2;// 關閉或
	
	private WebView mWebView;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_webviw);
		initView();
	}
 	<p>
	 private void getIntentDatas() {
  		// TODO Auto-generated method stub
 		 url = getIntent().getStringExtra("url");
 	}</p><p> </p>	private void initView() {
		mWebView = (WebView) findViewById(R.id.webview);
		//或的WebView的Setting
		WebSettings settings = mWebView.getSettings();
		//設置支持js,看方法名字就知道啥意思
		settings.setJavaScriptEnabled(true);
		mWebView.addJavascriptInterface(new JavaScriptInterface(handler), "Android");
		//加載網頁路徑
		mWebView.loadUrl(url);
	}
	
	private Handler handler = new Handler(){
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case SELECT_IMAGE://執行打開圖庫,
				
				//如果有參數,取服務端傳過來的參數(url,json)
				Map<String, String> params = (HashMap<String, String>)msg.obj;
				break;
				
			//其他功能,可隨着自己功能的增加,在這裏增加,只需和後臺商量好動作的action值即可
			default:
				break;
			}
		};
	};
}

最後再讓WebViewActivity通用,就是通過傳url參數

 private void getIntentDatas() {
  // TODO Auto-generated method stub
  url = getIntent().getStringExtra("url");
 }


這樣就可以了。

如果要demo可以留言

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章