[Android] WebView 傳值給 HTML

摘要:[Android] WebView 傳值給 HTML

目的

透過 WebView 將參數傳送給 HTML。

方法

  • WebView 載入 HTML l時,呼叫在 HTML 上 JavaScript 函數。
  • WebView 設定 JavaScript 介面,並 HTML 上呼叫 Java 函數。=====> 本文的方法,原因是此方法比較符合資訊安全。

實作

輸入經緯度跳出 Goole Map 地圖。

畫面如下

程式結構

XML(activity_main.xml)

主頁面包含二個 TextView、二個 EditView 與一個 Button。


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/textViewLat"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="31dp"
        android:layout_marginTop="90dp"
        android:text="緯度"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <TextView
        android:id="@+id/textViewLon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="31dp"
        android:layout_marginTop="140dp"
        android:text="經度"
        android:textAppearance="?android:attr/textAppearanceLarge" />
    
    <EditText
        android:id="@+id/editTextLat"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" 
        android:layout_marginLeft="90dp"
        android:layout_marginTop="90dp" >
    </EditText>

    <EditText
        android:id="@+id/editTextLon"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" 
        android:layout_marginLeft="90dp"
        android:layout_marginTop="140dp" >
    </EditText>

    <Button
        android:id="@+id/buttonmap"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignRight="@+id/editTextLon"
        android:layout_centerVertical="true"
        android:text="Google Map" />
    
</RelativeLayout>

XML(map.xml)

跳出頁面的套版包含一個 WebView (用來載入網頁)與一個 ImageView (用來結束畫面的X)。


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="300dp"
    android:orientation="vertical" >

    <WebView
        android:id="@+id/webviewmap"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:layout_margin="@dimen/activity_horizontal_margin" />
    
    <ImageView
        android:id="@+id/imageviemap"
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:src="@drawable/cancel" />

</RelativeLayout>

HTML(map.html)

給WebView載入的 HTML 檔。

  • 第6行 為 Google Map API載入。
  • 第9~30行 為載入 Google Map的函數。
  • 第11~12行 先賣個關子,後頭會解釋。
  • 第17行 zoom 是 Google Map 的縮放等級,值愈大地圖會愈細。
  • 第18行 mapTypeId 是 Google Map 的地圖類型。
    • ROADMAP  顯示 Google 地圖的正常、預設 2D 地圖方塊。
    • SATELLITE 可顯示攝影地圖方塊。
    • HYBRID 可顯示混合攝影地圖方塊與重要地圖項 (道路、城市名稱) 的地圖方塊圖層。
    • TERRAIN 可顯示實際起伏的地圖方塊,以呈現海拔高度和水域圖徵 (山嶽、河流等)。
  • 第19行 center 是地圖中心位置。
  • 第28行 地圖上註記的文字說明。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Google Maps</title>
    <script src="https://maps.googleapis.com/maps/api/js?sensor=false&v=3.9"></script>

    <script>
      function initialize() 
      { 
    	  var lat = AndroidFunction.GetLat();
    	  var lon = AndroidFunction.GetLon();
    	  
    	  var latlon = new google.maps.LatLng(lat,lon);
    	  var mapOptions = 
    	  {
    			  zoom: 16,
    			  mapTypeId: google.maps.MapTypeId.ROADMAP,
    			  center: latlon
    	  };
    	  map = new google.maps.Map(document.getElementById('map'),mapOptions);   
    	  var marker = new google.maps.Marker(
    			  {     
    				  position: latlon,
    				  map: map,   
        		});
    	  var infowindow = new google.maps.InfoWindow();
    	  infowindow.setContent("<p>No 1105 到此一遊</p>");
          infowindow.open(map, marker);
      }
    </script>
  </head>

  <body onload="initialize()">
    <div id="map" style="width: device-width; height: 300px;"></div>
  </body>
</html>

MainActivity.java

  • 第29~30行 為設定按下 Google Map 按鈕的事件。
  • 第61~65行 為擷取輸入的經緯度。
  • 第69~72行 為彈出視窗套上 map.xml 的格式。
  • 第74~75行 為設定按下X按鈕的事件。
  • 第77行 為 map.html 的位置。
  • 第80行 為可以使用 Javascript。
  • 第81行 為本文的重點,從字面上的翻譯是說建立一個 Javascript 的介面,意思是說在 HTML 裡面的 Javascript 可以呼叫 Java 本身的函數, 還記的 map.html 的第11~12行,那奇怪的東西嗎,那部份就是呼叫40~44行與46~50行的 GetLat 與 GetLon 來取得經緯度,我這邊是直接設定成原 Class 且給定期名字(本文設定:AndroidFunction),當然也可以其他的 Class,只是有一點要注意,那就是 GetLat 與 GetLon 上面都有一行標記@JavascriptInterface,這部份有 聽說是 Android4.2.2 以後才要加,但這點我不是很肯定,但因為我是用 Android4.2.2,所以沒加真的不會出來,其他版本就請大大自己試試看嚕,呼叫時前面要加你設定介面的名字+函數的名稱。
  • 第82行 為 WebView 載入 map.html。
  • 第83行 為彈出視窗。
  • 第83行 為關閉視窗。

package com.example.webviewdamo;


import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.webkit.JavascriptInterface;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;

public class MainActivity extends Activity 
{
	private String Lat;
	private String Lon;
	private AlertDialog alerdialog;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) 
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		Button MapButton = (Button) findViewById(R.id.buttonmap);
		MapButton.setOnClickListener(Click);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) 
	{
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@JavascriptInterface
	public String GetLat()
	{
		return Lat;
	}
	
	@JavascriptInterface
	public String GetLon()
	{
		return Lon;
	}
	

	private View.OnClickListener Click= new View.OnClickListener () 
	{
		@Override
		public void onClick(View view) 
		{
			switch(view.getId())
			{
			case R.id.buttonmap:
				EditText latedittext = (EditText) findViewById(R.id.editTextLat);
				EditText lonedittext = (EditText) findViewById(R.id.editTextLon);
				
				Lat = latedittext.getText().toString();
				Lon = lonedittext.getText().toString();
				
				if (Lat != null && Lon != null)
				{
				    Builder builder = new AlertDialog.Builder(MainActivity.this);
				    LayoutInflater inflater = LayoutInflater.from(MainActivity.this);
				    View mapview = inflater.inflate(R.layout.map,null);
				    builder.setView(mapview);
						
				    ImageView imageview = (ImageView)mapview.findViewById(R.id.imageviemap);
				    imageview.setOnClickListener(Click);
					   
				    String mapurl = "file:///android_asset/map.html"; 
					   
				    WebView webview = (WebView) mapview.findViewById(R.id.webviewmap);
				    webview.getSettings().setJavaScriptEnabled(true); 
				    webview.addJavascriptInterface(MainActivity.this , "AndroidFunction");     
				    webview.loadUrl(mapurl);
				    alerdialog = builder.show();
				}
				break;
			case R.id.imageviemap:
				alerdialog.cancel();
				break;
			}
		}
	};
}

AndroidManifest.xml(需要增加==>才可以上網)


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

結果

我輸入了我大學的母校東吳大學,經度:121.5457,緯度:25.0944。

以上有任何問題與錯誤,歡迎各位指教,謝謝。