출처 : http://blog.naver.com/hyuki0920?Redirect=Log&logNo=140111581692

이번 안드로이드 프로젝트를 진행하면서 필요한 기능 중 하나가 사용자 주변검색을 하는 기능이다.

이 기능을 구현하기 위해 목표로 한 것이 구글에서 제공하는 지역검색을 사용하여 지역정보를 얻어 오는 것이 였다.

그래서 발견한 사이트가 http://stackoverflow.com/questions/2499324/google-search-api-for-android-systems 여기다

사실 구글에서 android google search api 라고 치면 가장 위에 나오는 사이트다. ㅎ

사이트를 URL을 이용하여 google 서비스에 접근해서 원하는 결과(주변검색결과)를 받아 오는 예제를 얻을 수 있다.

이 예제를 수정하여 완벽하진 않지만 원하는 결과물을 얻을 수 있었다.

 

우선 Google Search API에 접근할 URL을 생성해야 한다.

로컬검색을 위해서는

"http://ajax.googleapis.com/ajax/services/search/local?v=1.0&q="+ URLEncoder.encode(검색어, "UTF-8")+"&sll="+위도+경도

위와 같이 URL을 만들어야 한다. 여기서 sll뒤의 위도 경도는 현재위치, 주변검색의 중심이 되는 위치를 말한다.

만약 에뮬레이터가 아닌 디바이스를 사용한다면 디바이스의 GPS를 이용하여 현재 위치를 얻어 값을 넣어주면 된다.

google search API에 대한 자세한 내용은 http://code.google.com/intl/ko/apis/ajaxsearch/ 이곳에서 확인 할 수 있다.

 

다음은 URL을 생성하고 그 URL을 이용하여 검색결과를 받아오는 코드이다.

  StringBuilder responseBuilder = new StringBuilder();
     // URL을 이용하여 검색신청을 하고, 결과를 받아 responseBuilder에 저장한다.
     try {
      // 검색을 위한 URL 생성
      URL url = new 
      URL("http://ajax.googleapis.com/ajax/services/search/local?v=1.0&q="+ URLEncoder.encode(search, "UTF-8")
       + "&sll="+currentLocation[0]+","+currentLocation[1]
       + "&hl=kr");
      BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
      String inputLine;
      while ((inputLine = in.readLine()) != null) {
       responseBuilder.append(inputLine);
      }
      in.close();
     } catch (MalformedURLException me) {
      me.printStackTrace();
     } catch (UnsupportedEncodingException ue) {
      ue.printStackTrace();
     } catch (IOException ie) {
      ie.printStackTrace();
     }

URL을 생성하고, stream을 열면 결과를 받아온다. (사실 자세한건 모른다... 하하;;)

 

위의 코드의 결과값, 즉 responseBuilder 에 저장되는 문자열이

{"responseData": {"results":[{"GsearchResultClass":"GlocalSearch","viewportmode":"computed","listingType" ..........

이런 식으로 나오게 된다.(JavaScript 라는데.......)

그리고 이 것을 가지고 원하는 결과값을 얻기 위해서는 JSON(JavaScript Object Notationo)를 이용해 parsing을 해야한다.

JSON이.. 무엇인지는 http://www.json.org/ (영어)  http://www.json.org/json-ko.html (한국어) 이 곳을 들어가면 알 수 있다.

 

음... 안드로이드에서는 JSONObject 를 기본적으로 제공하여 이것을 사용하면 된다...

 

JSONObject를 생성하는 것은 간단하다.

JSONObject json = new JSONObject(responseBuilder.toString());

이렇게 URL을 통해 얻은 결과를 String으로 건내주어 생성하면 된다.

JSONObject를 생성한 다음에는 Key를 이용하여 원하는 결과를 Parsing을 해주면된다.

Parsing을 어떻게하는지는.. http://www.cyworld.com/fourhand/4096293 이곳에서 배웠다.

JSONObject json = new JSONObject(responseBuilder.toString());
      
json = json.getJSONObject("responseData");
JSONArray jarray = json.getJSONArray("results");
    
String result = new String();
      
Log.d(LOG,Integer.toString(jarray.length()));
      
for(int i = 0; i < jarray.length(); i++) {
// 결과별로 결과 object 얻기
JSONObject jtmp = jarray.getJSONObject(i);
       
String streetAddr = jtmp.getString("streetAddress"); // street 주소
String title = jtmp.getString("titleNoFormatting"); // html 이 포함되지 않은 장소명
       
// 번호 얻기
JSONArray jarray_tmp = jtmp.getJSONArray("phoneNumbers");
JSONObject jtmp2 = jarray_tmp.getJSONObject(0); // 처음 번호만 파싱함
String number = jtmp2.getString("number");
       
// 전체 주소 얻기
String addr_tmp = jtmp.getString("addressLines"); // addressLines(ket) 값을 얻어온다.
String[] addr_tmp2 = addr_tmp.split("\""); // ["...."] 이 구조이기 때문에 중간 문자열만 가지고온다
String addr = addr_tmp2[1]; // { "[" , ".....", "]" } 이렇게 되어있는 것에서 중간 문자열을 선택

JSONObject를 생성하고 원하는 결과 - 장소명, 주소, 전화번호-를 얻은 코드이다.

 

그런데... 여기서  한가지 의문이 가는 점이 있다. 결과값이 항상 4개만 나온다는 것이다. 어떤걸 검색하든....

어필 생각하기론 URL의 결과가 페이지 단위로 오는데 한 페이지에 4개의 검색 결과만 저장되고,

작성한 코드는 첫번째 페이지만 가지고 오는 것 같다....

자세한건... 모른다.. ;;;;;;

누가 왜 그런지 알려줬으면 하는 심정이다... (5개 이상의 결과를 얻고싶은 1人)

 

지금까지의 지식으로 만든 결과물이다. 검색의 기준을 숭실대입구역으로 하였기 때문에 숭실대입구 근처의

주변검색 결과가 나온다.

 

 

 

그리고 이 결과물을 바탕으로 GeoCoder로 위도 경도를 얻어,

아래와 같이 Map에 검색 결과를 마킹해주는 것도 할 수 있었다.

 

private void searchOnMap(String search) {
     StringBuilder responseBuilder = new StringBuilder();
     // URL을 이용하여 검색신청을 하고, 결과를 받아 responseBuilder에 저장한다.
     try {
      // 검색을 위한 URL 생성
      URL url = new 
      URL("http://ajax.googleapis.com/ajax/services/search/local?v=1.0&q="+ URLEncoder.encode(search, "UTF-8")
       + "&sll="+currentLocation[0]+","+currentLocation[1]
       + "&hl=ko");  // 8.13 수정
      BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8")); // 8.13 수정
      String inputLine;
      while ((inputLine = in.readLine()) != null) {
       responseBuilder.append(inputLine);
      }
      in.close();
     } catch (MalformedURLException me) {
      me.printStackTrace();
     } catch (UnsupportedEncodingException ue) {
      ue.printStackTrace();
     } catch (IOException ie) {
      ie.printStackTrace();
     }

     // 위의 결과를 JSONObject를 이용해 원하는 정보를 parsing 한다
     try {
      JSONObject json = new JSONObject(responseBuilder.toString());
      
      json = json.getJSONObject("responseData");
      JSONArray jarray = json.getJSONArray("results");
      
      String result = new String();
      
      Log.d(LOG,Integer.toString(jarray.length()));
      
      for(int i = 0; i < jarray.length(); i++) {
       // 결과별로 결과 object 얻기
       JSONObject jtmp = jarray.getJSONObject(i);
       
       String streetAddr = jtmp.getString("streetAddress"); // street 주소 파싱
       String title = jtmp.getString("titleNoFormatting"); // html 이 포함되지 않은 주소
       
       // 번호 파싱
       JSONArray jarray_tmp = jtmp.getJSONArray("phoneNumbers");
       JSONObject jtmp2 = jarray_tmp.getJSONObject(0); // 처음 번호만 파싱함
       String number = jtmp2.getString("number");
       
       // full address 파싱
       String addr_tmp = jtmp.getString("addressLines"); // addressLines(ket) 값을 얻어온다.
       String[] addr_tmp2 = addr_tmp.split("\""); // ["...."] 이 구조이기 때문에 중간 문자열만 가지고온다
       String addr = addr_tmp2[1]; // { "[" , ".....", "]" } 이렇게 되어있는 것에서 중간 문자열을 선택
      

       // 주소를 이용하여 위도경도 얻어오기
       // Geocoder를 이용하면 위도경도로 주소를 얻어오거나
       // 주소를 이용해 위도 경도의 정보를 얻어 올 수 있다
       Geocoder geocoder = new Geocoder(this);
       List<Address> addrList = geocoder.getFromLocationName(addr, 1); // 한개의 주소정보만 얻어온다
       Address adr_tmp = addrList.get(0); // list에서 사용할 Address Object를 가지고 온다
       String[] location = new String[2];
       location[0] = Double.toString(adr_tmp.getLatitude()); // 위도 
       location[1] = Double.toString(adr_tmp.getLongitude()); // 경도 
       
       // 화면에 출력할 String 작성
       result += "Title : " + title + "\n";
       result += "Address : " + addr + "\n";
       result += "StreetAddr : " + streetAddr + "\n";
       result += "Phone : " + number +"\n";
       result += "Latitude : " + location[0] + "\n";
       result += "Longitude : " + location[1] + "\n\n";
      }
      
      text.setText(result);
      
      Log.d(LOG,jarray.getString(0));
     } catch (JSONException e) {
      e.printStackTrace();
     } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
    }

 

 

------------------------- 수정 ----------------- 8.13 -------------

 

url 쿼리를 통해 검색을 받아오는 것은 밑에 뎃글을 달아주신 것처럼 1~8만 되도록 되어있다.

rsz 이 파라미터값을 주는 것을 이용하여 그 개수를 조절 할 수 있는데. 기본값이 4여서 위와 같이하면 항상 4개의 결과를 받아오는 것이였다.

 

음.. 그리고 다른 한가지... 더 이상의 결과를 얻기 위해서는 url 쿼리를 다시 날려 그 뒤에 결과값을 받아 올 수 있다.

url 파라미터중에 start 라는 것이 있는데, 이것은 검색결과를 어디서 부터 줄것인지 결정하는 것이다.

(검색 시작 페이지를 위한 파라미터라고 설명하는 곳도 있다.)

 URL("http://ajax.googleapis.com/ajax/services/search/local?v=1.0&q="+ URLEncoder.encode(search, "UTF-8")
       + "&sll="+currentLocation[0]+","+currentLocation[1]
       + "&hl=kr");

즉 위의 url 을

 URL("http://ajax.googleapis.com/ajax/services/search/local?v=1.0&q="+ URLEncoder.encode(search, "UTF-8")
       + "&sll="+currentLocation[0]+","+currentLocation[1]
       + "&hl=kr"

       + "&start=4" );

위와 같이 start 파라미터값을 주면 4부터 결과값을 받아온다. (start의 기본값은 0이라고한다.)

이를 이용해 or문같은 반복문으로

int rsz = 4;

for(int i = 0; i < 30; i += rsz) {

URL url =   

new URL("http://ajax.googleapis.com/ajax/services/search/local?v=1.0&q="+ URLEncoder.encode(search, "UTF-8")
       + "&sll="+currentLocation[0]+","+currentLocation[1]
       + "&hl=ko"

       + "&rsz=" + String.valueOf(rsz)

       + "&start=" + String.valueOf(i) };

........

}

이렇게 해서 각 결과물을 파싱하면 최대 30개까지의 결과물을 얻을 수 있다.

(start 값이 30개가 넘어가면 out of range 라는 것을 리턴해준다)

아참, 그리고 hl은 언어를 나타내는데.. 우리나라 언어코드고 kr인줄알고 kr을 썼었지만.... 알아보니 kr 이 아니고 ko 가 맞는 것이였다.;;

 

 

 

아무리 생각해도.. 무지하면 몸이 고생하는 것같다... 저런걸 미리 알고있었더라면....

많은 시간 검색에 투자하지 않아도 되었을터인데...

+ Recent posts