LearnHouse

[Java]Google Geocoding API

在寫這一篇之前應該會有三篇關於Facebook在Android與iOS上的應用

但我只寫到一半,因為Facebook的SDK使用上有幾個很重要的經驗

需要花一點時間截圖說明,但我最近一直都沒有時間去完成他

所以看官們對Facebook在Android與iOS應用有興趣的需要再等會,我先寫這一篇比較簡單的。

本文開始前,先了解一下什麼是Geocoding,其實說穿的就是google提供把住址轉換成經緯度的API

至於能做什麼應用就見仁見智。

其中要注意的我歸納有以下幾點

1. 2500筆的限制:google為了避免有人濫用 Geocoding API 和 (或) 將其用在其他目的,限制非Google Maps API Premier 使用者,每天只能要求 2,500 個地理位置,經實測結果的確在2600多筆之後回傳的經緯度就都是(0, 0)了,但這只是防君子不防小人的鳥策略。

2.請求速度不能太快:如果你程式一執行就讓他一直向Google要求住址轉換成經緯度,你會發現每隔幾筆請求會回傳經緯度是(0, 0)

3.使用http GET的方式請求:台灣是中文語系的國家,所以請求前最好指定一下為UTF-8編碼格式

4.回傳的結果可以是XML或JSON的呈現方式:我只測試JSON的部分,因此使用的第三方的套件來解析json-simple

以下是原始碼:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;

import java.net.InetAddress;
import java.net.URL;
import java.net.URLEncoder;

import org.json.JSONArray;
import org.json.JSONObject;

public class GeoCoding {

 /**
 * @param args
 */
 public static void main(String[] args) {
 // TODO Auto-generated method stub

 try {
 //設定要讀取轉換地址的文字檔與寫入轉換後經緯度的文字檔
 BufferedReader addressIn = new BufferedReader(new FileReader("address_in.txt"));
 BufferedWriter addressOut = new BufferedWriter(new FileWriter("address_out.txt"));
 String strIn;
 String strOut;
 double AddrXY[] = { 0, 0 };
 int queryCount = 0;

 while ((strIn = addressIn.readLine()) != null) {
 Thread.sleep(500);    //這裡就是我說的如果不休息個幾毫秒,一直傳送請求會有些無法取到經緯度
 queryCount++;
 AddrXY = getAdressXY(strIn);    //取得經緯度
 if (queryCount == 2500){    //用來防君子不防小人的方式,2500筆的時候重新連線取得新IP
 Runtime.getRuntime().exec("cmd /k start PPPoE.bat"); //執行我寫的重新連線bat檔
 Thread.sleep(7000); //怕還沒撥接完,所以停7秒再繼續(其實不需要這麼久)
 InetAddress myIP = InetAddress.getLocalHost() ;
 System.out.println(myIP.getHostAddress());
 queryCount = 0;
 }

 strOut = strIn + ";" + AddrXY[1] + ";" + AddrXY[0];
 System.out.println(strOut);
 addressOut.write(strOut);
 addressOut.newLine();
 }
 addressIn.close();
 addressOut.close();

 } catch (Exception e) {
 // TODO Auto-generated catch block
 //e.printStackTrace();
 System.out.println("Main Exception" + e.toString());
 }
 }

 public static double[] getAdressXY(String Address) {
 URL url;
 double retXY[] = { 0, 0 };

 try {
 Address = URLEncoder.encode(Address, "utf-8");
 String actionUrl = "http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address="
 + Address;

 url = new URL(actionUrl);
 HttpURLConnection con = (HttpURLConnection) url.openConnection();

 con.setDoOutput(true);
 con.setDoInput(true);
 con.setRequestMethod("GET");
 con.setUseCaches(false);
 con.setReadTimeout(3000);
 con.setConnectTimeout(3000);

 con.setRequestProperty("Connection", "Keep-Alive");
 con.setRequestProperty("Charset", "utf-8");
 con.setRequestProperty("Content-Type",
 "application/x-www-form-urlencoded");

 DataOutputStream ds = new DataOutputStream(con.getOutputStream());

 /* 取得Response內容 */
 int retCode = con.getResponseCode();
 // System.out.println("JsonUtil retCode" + retCode);
 String inputLine = null;
 if (retCode == 200) {
 BufferedReader reader = new BufferedReader(new InputStreamReader(
 con.getInputStream(), "utf-8"));

 String strResult = "";
 while (((inputLine = reader.readLine()) != null)) {
 strResult = strResult + inputLine;
 }
 //System.out.println("strResult="+strResult);
 reader.close();

 //解析JSON回傳結果
 JSONObject obj = new JSONObject(strResult);

 JSONArray jsonArray = obj.getJSONArray("results");
 for (int i = 0; i < jsonArray.length(); i++) {
 JSONObject obj2 = jsonArray.getJSONObject(i);
 JSONObject obj3 = obj2.getJSONObject("geometry");
 JSONObject obj4 = obj3.getJSONObject("location");
 //retString[0] = obj4.getString("lat");
 //retString[1] = obj4.getString("lng");
 retXY[0] = obj4.getDouble("lat");
 retXY[1] = obj4.getDouble("lng");

 //System.out.println("lat(經度):"+retXY[0]);
 //System.out.println("lng(緯度):"+retXY[1]);
 }
 }
 con.disconnect();
 } catch (Exception e) {
 // TODO Auto-generated catch block
 //e.printStackTrace();
 System.out.println("getAdressXY Exception" + e.toString());
 }

 return retXY;
 }

}

讀入的address_in.txt文字檔內容如下
台東縣台東市永安街97號
台東縣台東市漢中街128號
台東縣鹿野鄉高台路42巷2號
台東縣台東市新生路772號
台東縣台東市傳廣路257號

寫入的address_out.txt文字黨內容如下
台東縣台東市永安街97號;121.1220152;22.7829546
台東縣台東市漢中街128號;121.1374301;22.7582271
台東縣鹿野鄉高台路42巷2號;121.1197793;22.9141254
台東縣台東市新生路772號;121.1341475;22.7654438
台東縣台東市傳廣路257號;121.1439304;22.7629646

另外其中有一段用來防君子不防小人的做法
就是在請求2500筆後,重新撥接ADSL取得新IP

if (queryCount == 2500){    //用來防君子不防小人的方式,2500筆的時候重新連線取得新IP
 Runtime.getRuntime().exec("cmd /k start PPPoE.bat"); //執行我寫的重新連線bat檔
 Thread.sleep(7000); //怕還沒撥接完,所以停7秒再繼續(其實不需要這麼久)
 InetAddress myIP = InetAddress.getLocalHost() ;
 System.out.println(myIP.getHostAddress());
 queryCount = 0;
 }


PPPoE.bat的內容如下:

rasdial /disconnect
rasdial 連線名稱 12345678@hinet.net password

posted by admin in 程式&軟體 and have No Comments

Place your comment

Please fill your data and comment below.
Name
Email
Website
Your comment