반응형


만들고 있는 안드로이드 어플이 네이버 검색 API를 통해 검색 결과로 나온 곳의 좌표를 받아오는데 카텍좌표계라는 것으로 값을 받아오더군요. 그런데 저는 WGS84 좌표계가 필요한 상황이었습니다 ㅠㅠ

이를 어떻게 해야할지..
처음에 열심히 검색을 했습니다. 수학 공식으라도 찾으면 그걸 프로그래밍하면되니깐요.
그러다 변환 공식이 아닌 API를 찾았습니다. 가까운 다음 지도 API좌표계 변환 API가 있더군요^^

좀 더 조사한 결과 네이버는 KTM 좌표계라는 걸 알아냈습니다.
결론 적으로 저는 다음 좌표계 변환 API를 써서 WGS84 좌표계로 변환하면 된다는 말씀!!

다음 API의 요청 주소 예는는 아래와 같습니다.

http://apis.daum.net/maps/transcoord?apikey=key&x=경도&y=위도&fromCoord=KTM&toCoord=WGS84&output=xml

파라미터로 x = 경도, y = 위도, fromCoord = 입력좌표계, toCoord = 출력좌표계, output = 출력형식 이 있네요.

모든 파라미터의 값은 string 형이고,

입,출력 좌표계의 값은 TM, KTM, UTM, CONGNAMUL, WGS84, BESSEL, WTM, WKTM, WUTM, WCONGNAMUL 이 있습니다.
위에 열거된 좌표끼리의 변환이 가능합니다.

출력 형태는 xml json 이 있고 기본은 xml입니다. 기본이 xml이니 받아와서 파싱만 하면 끝이겠군요^^

우선 KTM인 좌표 x=311277, y=552098을 KTM에서 WGS84로 변환하여 xml로 받아오도록 URL을 익스플로러에 보내보면


이렇게 xml로 값을 받아 오는군요 .

그럼 간단히 필요에 따라 아래와 비슷하게 메소드 하나만 만들면 될 것 같네요.^^
제가 만든 코드가 너무 허접하여 고수님들께서 댓글 좀 남겨주시면 감사하겠습니다.
다른 코드들을 보니깐 좌표를 x와 y로 표현한게 많던데 그렇게 하면 경도와 위도가 헷갈려서 힘들더라구요 ㅎㅎ
그래서 저는 longitude와 latitude라고 변수명을 줬습니다.

HashMap과  XmlPullParser를 사용하기 위해 사전에 import시켜줍니다.
import java.util.HashMap;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;

그리고 메소드를 만들어 봐요~ ㅋㅋㅋㅋㅋ

 private HashMap<String, String> transCoord(String longitude, String latitude) { 

       private HashMap<String, String> map = new HashMap<String,String>();  //경위도를 넣을 해시에용

       final String key = "key"; //이부분의 발급받은 Key를 넣습니당.
         
       try {
        //다음 API를 사용하여 ㅁㅁㅁ 형식의 좌표를 ㅇㅇㅇ형태로 바꾼다 XML로 받아 와서 파싱한다.
        URL text = new URL("http://apis.daum.net/maps/transcoord?"
              +"apikey=" + key        //apikey
              +"&x=" + longitude                 //원래 좌표계 경도
              +"&y=" + latitude                 //원래 좌표계 위도
              +"&fromCoord=KTM"  //원래 좌표계
              +"&toCoord=WGS84"   //변환한 후 좌표계
              +"&output=xml");        //출력형식
      
     //파서를 생성하고 파싱을 시작해요. 
     XmlPullParserFactory parserCreator = XmlPullParserFactory.newInstance();
     XmlPullParser parser = parserCreator.newPullParser();
     parser.setInput(text.openStream(), null);
     int parserEvent = parser.getEventType();
    while (parserEvent != XmlPullParser.END_DOCUMENT) {
           switch(parserEvent) {
             case XmlPullParser.START_TAG:
                String tag = parser.getName();
                if (tag.compareTo("result") == 0) { //파서가 result 태그를 만나면 x의 y의 속성 값을 각각 longitude,latitude에 넣음.
                      map.put("longitude", parser.getAttributeValue(null, "x"));             
                      map.put("latitude", parser.getAttributeValue(null, "y"));
              }
              break;
            }
        parserEvent = parser.next();
     }
    } catch (Exception e) {
     Log.e("Net", "Error in network call", e);
       }
       return map;
   }

제가 만든 메소드를 사용해서 HashMap 으로 결과를 받아오면 매우 편리할거에요^^ 아마도 ㅎㅎ
더 편리한 방법 제보를 기다립니당~^^
반응형
반응형


요즘 만들고 있는 어플에 네이버 검색 API를 쓸 일이 있어 포스팅합니다.

네이버 오픈 API는 네이버 개발자 센터
http://dev.naver.com/openapI 로 가시면 상세한 설명을 보실 수 있습니다.

네이버 검색 API 중 지역 검색을 사용하는데요.
요청 URL(request url)요청변수(request parameter) target 값에 따라 검색 분야가 달라지네요.
지역 검색은 target값이 local입니다.
display는 받아올 결과의 수 입니다.

샘플 URL은 다음과 같습니다.
http://openapi.naver.com/search?key=test&query=%EA%B0%88%EB%B9%84%EC%A7%91&target=local&start=1&display=10

key에 자신이 받은 key값을 넣고 query에 검색할 키워드를 넣으시면됩니다.
검색어의 문자셋은 UTF-8을 써야한다고 하네요.
저는 일단 파싱만 하고 테스트만 할 목적이므로 샘플 URL에 key값만 넣어서 실행 했습니다.
샘플 URL의 검색어는 '갈비집'이네요.

출력결과로 다양한 값들이 있는데 저는 제게 필요한 것들만 받아옵니다.
우선 결과를 먼저 보여 드리면 이렇습니다.^^;; 허접하죠


결과로 주어지는 항목들은 네이버 개발자 센터에 테이블로 잘 정리가 되있습니다 ㅎㅎ
PullParser를 사용할건데요 뭐 속도가 느릴거라는 말도 있던데 어차피 전 테스트이므로 4개만 받아올거라서 크게 못 느낄 것 같아요.(그렇겠죠??????아닌가??)

package ksk06.naverapi;
import java.net.URL;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class NaverTest extends Activity {
     
 /** Called when the activity is first created. */
 @Override   
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        TextView status = (TextView)findViewById(R.id.status);
        TextView status1 = (TextView)findViewById(R.id.status1); //파싱된 결과를 보자
        TextView status2 = (TextView)findViewById(R.id.status2);
          
        boolean inItem = false, inTitle = false, inAddress = false, inMapx = false, inMapy = false;
       
  String title = null, address = null, mapx = null, mapy = null;
  String query = "%EA%B0%88%EB%B9%84%EC%A7%91"; //이부부은 검색어를 UTF-8로 넣어줄거임.
  System.out.println(query);
  
        try{
            URL url = new URL("http://openapi.naver.com/search?"
           +"key=여기에 발급받은 키값을 넣으세요"
           +"&query="+query //여기는 쿼리를 넣으세요(검색어)
           +"&target=local&start=1&display=4");
            
      
         XmlPullParserFactory parserCreator = XmlPullParserFactory.newInstance();
         XmlPullParser parser = parserCreator.newPullParser();
           
         parser.setInput(url.openStream(), null);
                  
         status.setText("파싱 중이에요..");
         
         int parserEvent = parser.getEventType();
         
         while (parserEvent != XmlPullParser.END_DOCUMENT){
          switch(parserEvent){                     
           case XmlPullParser.START_TAG:  //parser가 시작 태그를 만나면 실행
            if(parser.getName().equals("item")){
             inItem = true;
            }
            if(parser.getName().equals("title")){ //title 만나면 내용을 받을수 있게 하자 
             inTitle = true;              
            }
            if(parser.getName().equals("address")){ //address 만나면 내용을 받을수 있게 하자
            inAddress = true;              
            }
            if(parser.getName().equals("mapx")){ //mapx 만나면 내용을 받을수 있게 하자  
             inMapx = true;              
            }
            if(parser.getName().equals("mapy")){ //mapy 만나면 내용을 받을수 있게 하자  
             inMapy = true;              
            }            
            if(parser.getName().equals("message")){ //message 태그를 만나면 에러 출력
             status1.setText(status1.getText()+"에러");
              //여기에 에러코드에 따라 다른 메세지를 출력하도록 할 수 있다.
            }            
            break;
            
           case XmlPullParser.TEXT://parser가 내용에 접근했을때
            if(inTitle){ //isTitle이 true일 때 태그의 내용을 저장.
             title = parser.getText();             
                inTitle = false;
            }
            if(inAddress){ //isAddress이 true일 때 태그의 내용을 저장.
             address = parser.getText();             
                inAddress = false;
            }
            if(inMapx){ //isMapx이 true일 때 태그의 내용을 저장.
             mapx = parser.getText();             
                inMapx = false;
            }
            if(inMapy){ //isMapy이 true일 때 태그의 내용을 저장.
             mapy = parser.getText();             
                inMapy = false;
            }
            break;            
           case XmlPullParser.END_TAG:
            if(parser.getName().equals("item")){
             status1.setText(status1.getText()+"상호 : "+ title +"\n주소 : "+ address +"\n좌표 : " + mapx + ", " + mapy+"\n\n");
             inItem = false;
            }
            break;                   
          }          
           parserEvent = parser.next();
         }
         status2.setText("파싱 끝!");
        } catch(Exception e){
         status1.setText("에러가..났습니다...");
        }       
    }
}

레이아웃은 간단히 파싱되는걸 확인만 할거라서 텍스트뷰로 만들었습니다.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView
 android:id="@+id/status" 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    />
    <TextView
 android:id="@+id/status1" 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    />
    <TextView
 android:id="@+id/status2" 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    />
</LinearLayout>

절대로 빠뜨리시면 안될 한가지가 있습니다.
AndroidManifest.xml 파일에 인터넷에 접근하기 위한 권한을 설정해 주셔야합니다^^
<uses-permission android:name="android.permission.INTERNET"/>

저는 이렇게 간단히 검색어에 대한 건색 결과 중 상호와, 주소, map의 좌표를 받아 온 것을 String에 넣어서 출려해 봤습니다. 실제로 편리하게 쓰시려면 List 같은 걸 사용하시면 더 좋을 거 같아요.

네이버의 다른 오픈 검색 API 도 똑같은 URL을 사용하기 때문에 target값만 바꿔 주시고 받아올 결과들에 대한 코드만 수정해 주시면 다른 검색도 쉽게 사용하실 수 있을겁니다. 
반응형
반응형
HTTP를 통해서 주고 받는 자료의 많은 부분은 XML형식으로 조직화 되어 있다고 합니다.
안드로이드에서는 XML Pull Parser를 제공하여 XML 파일을 파싱합니다.

그럼 네트워크에 있는 XML 파일의 파싱을 한번 해 볼까요?
URL객체를 생성하는 것은 웹에서 자료를 읽어올 때와 다를 것이 없습니다.
XMLPullParserFactory를 이용해 XMLPullParser 객체를 생성하고 URL 객체를 이용해 입력 스트림을 파서에 연결해서 적절한 메서드를 루프에서 반복 호출 하면서 XML 문서를 읽어서 파싱하게 됩니다.

아래 코드에서는 파서가 시작 태그를 만났을 때 (START_TAG)만 동작합니다.
시작 태그를 만났을 때 요소의 특성을 조회하고 비교해서 정보를 로그에 기록합니다.
즉 코드에서는 flickr feeds에서 이미지 URL만 뽑아 로그에 기록합니다.

XMLPullParser 의 next()와 getEventType()이 반확하는 속성들은 다음과 같습니다.
START_TAG : 요소의 시작 태그를 만났을 때 반환 (<tag>)
TEXT : 요소의 텍스트를 만났을 때 반환 (<tag>TEXT</tag>에서 TEXT)
END_TAG : 요소의 종료 태그를 만났을 때 반환 (</tag>)
END_DOCUMENT : XML 파일의 끝에 도달했을 때 반환

package net.bment.net;
import java.net.URL;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
public class XmlparseActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        TextView status = (TextView)findViewById(R.id.status);
        TextView status1 = (TextView)findViewById(R.id.status1);
        TextView status2 = (TextView)findViewById(R.id.status2);
       
        try {
   URL url = new URL("http://api.flickr.com/services/feeds/photos_public.gne"
     + "?id=26648248@N04&amp;lang=en-us&amp;format=atom");
   
  XmlPullParserFactory parserCreator = XmlPullParserFactory.newInstance();
  XmlPullParser parser = parserCreator.newPullParser();
   
   parser.setInput(url.openStream(), null);
   
   status.setText("파싱 중이에요..");
   int parserEvent = parser.getEventType();
   while (parserEvent != XmlPullParser.END_DOCUMENT){
    switch(parserEvent){
    case XmlPullParser.START_TAG:  //parser가 시작 태그를 만나면 실행
     String tag = parser.getName();
     
     if(tag.compareTo("link") == 0){   
      String relType = parser.getAttributeValue(null, "rel");
      
      if(relType.compareTo("enclosure") == 0){
       String encType = parser.getAttributeValue(null, "type");
       
       if(encType.startsWith("image/")){
        String imageSrc = parser.getAttributeValue(null, "href");
        Log.i("Net", "image source = " + imageSrc); //parser에서 받아 온 값을 Log에 기록
        status1.setText(status1.getText()+ ".");

       }       
      }
     }
     break;
    }
    
    parserEvent = parser.next();
   }
   status2.setText("파싱 끝!");
  } catch(Exception e){
         Log.e("Net", "네트워크 에러가..났습니다...", e);
  }
 }
}


로그에 이미지 파일의 URL이 기록됬습니다.

에뮬레이터에도 제가 코딩한데로 메시지가 뜨는군요^^ 히히

반응형
반응형

HttpURLConnection 클래스는 URL 객체가 가리키는 자원의 HTTP 상태와 헤더 등의 정보를 제공합니다.

다음은 HttpURLConnection을 사용해 URL에 대한 정보를 얻어오는 예제입니다.
결과는 LogCat이 친절히 보여주는군요 ^^
해당 URL의 자원 내용을 가져오려면 getInputStream() 을 호출하면 됩니다.

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

//...중략

try {
        URL url = new URL("http://kkoseul.tistory.com/entry/2011080101");
        
        HttpURLConnection http = (HttpURLConnection)url.openConnection();
        Log.i("Net", "length = " + http.getContentLength());
        Log.i("Net", "respCode = " + http.getResponseCode());
        Log.i("Net", "contentType = " + http.getContentType());
        Log.i("Net", "content = " + http.getContent());

 


 
        InputStream isText = http.getInputStream();
         byte[] bText = new byte[2048];
         int readSize = isText.read(bText);
         Log.i("Net", "readSize = " + readSize);
         Log.i("Net", "bText = " + new String(bText));
         isText.close();
         http.disconnect();
 
     }catch(Exception e){
         Log.e("Net", "네트워크 에러가..났습니다...", e);
     }

//...생략


처음에 length 값이 '-1'이라 좀 의아해 했는데 찾아보니 getContentLength()는 명확하지 않으면 -1을 반환하는군요^^ 
반응형
반응형

안드로이드 네트워킹 API를 사용해서 네트워킹을 지원해 보도록할까요?
Java를 해보신 분이라면 한 번쯤 보셨을 java.net 패키지가 사용됩니다.

가장 흔히 쓰이는 HTTP를 위주로 진행해 보겠습니다.
참고로 HTTP로는 대부분의 자료를 캡슐화 할 수 있고 SSL을 적용함으로써 보안 통신을 수행할 수도 있습니다.


■ 웹(Web)에서 자료 읽기!

  웹에서 자료를 읽어 오는 것은 비교적 간단합니다.
  읽고자하는 웹 페이지의 URL을 알기만 하면 java.net 패키지의 URL 클래스를 사용해서 원하는 자료를 읽어 올 수 있습니다.

import java.io.InputStream;
import java.net.URL;

//...

try {
URL url = new URL("http://kkoseul.tistory.com/entry/2011080101");

InputStream isText = url.openStream();
byte[] bText = new byte[250];
int readSize = isText.read(bText);
Log.i("Net", "readSize = " + readSize);
Log.i("Net", "bText = " + new String(bText));
isText.close();
}catch(Exception e){
Log.e("Net", "네트워크 에러가..났습니다...", e);
}

 
읽어올 자료의 URL을 URL객체로 생성합니다. 그다음 URL에 대한  입력 스트림을 열고 자료를 읽으면 됩니다.
  위 코드의 경우는 250byte 만큼만 자료를 읽은 후 스트림을 닫습니다.

  네트워크 상의 자원을 이용할 때에는 통신망의 상태나, 자원이 있는 서버의 상태에 따라 오류가 날 수 있으므로 이 점을 알고 있어야하며 또 URL이 잘 못 되는 경우도 있으니 주의가 필요합니다. (try-catch문을 쓰는 이유가 이것?^^)
  
  그리고 중요한 한 가지! 
  안드로이드 응용프로그램이 네트워크 기능을 사용하려면 적절한 권한이 필요합니다.
  AndroidManifest.xml 파일의 <manifest>요소 하위에 <uses-permission>요소를 추가합니다.

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

 
  추가하지 않으면..여러분도 저와 같은 메시지를 보게 되실겁니다 ㅠ_ㅠ

 
  위의 한 줄을 추가하니 기분 좋은 로그가 보이는 군요^ㅁ^ 여기까지가 웹에서 자료를 읽어오기 였습니다!  


다음 포스트에서는 HttpURLConnection 클래스를 사용해서 자료에 대한 정보를 가져와 보도록 하겠습니다!!
반응형
반응형

Google Android 에 대한 첫 번째 글입니다.
저도 이제 막 공부를 시작하려니 설레이네요 ^^

Android리눅스를 모바일 환경에 맞게 개조해서 만든 공개 운영체제입니다.
안드로이드 개발에는 다른 언어도 사용 가능하지만 공식적으로는 Java 언어를 사용하고 있다네요.
다양한 라이브러리를 제공하고, 써드파티 라이브러리까지 내장하고 있어서 어떤 책에서는 '오픈소소 집대성'이라는 표현도 사용하고 있습니다.
               


그리고 내장된 빌트인 프로그램과 사용자가 만든 프로그램이 동일한 API를 사용하기 때문에 모든 프로그램이 평등하다고 합니다.

안드로이드의 아키텍쳐는 아래와 같습니다.

Android System Architecture
그림 출처: http://developer.android.com/guide/basics/what-is-android.html

  먼저 제일 하위에 리눅스 커널(LINUX Kernel)이 있어서 백그라운드 스레드와 메모리를 관리하고, 보안, 디바이스 드라이버 등 저 수준의 관리를 담당합니다.

  다음 커널 위 계층에는 시스템 라이브러리(Libraries)가 있는데 이 라이브러리들의 동작이 장비의 전반적인 속도를 결정하기 때문에  Java가 아닌 C 또는 C++ 로 작성되어 있다고 합니다. 그리고 이 계층에 Android Runtime도 있는데요 Runtime은 자바 코어 라이브러리와 Dalvik 가상 머신(Dalvik VM)으로 구성됩니다. Dalvik 가상 머신은 모바일 디바이스용으로 최적화해 구현된 구글의 Java 격으로 이해 하시면 될것 같습니다. 

  세번째로 프레임워크(Application Framework) 계층에는 안드로이드의 API가 있습니다. Application은 직접 시스템 라이브러리나 하위 커널을 호출할 수 없기 때문에 API를 통해서 이들을 호출합니다.

  마지막 Applications 계층은 우리가 사용하고 보는 '앱'들이 되겠지요^^

여기까지 간단하게 안드로이드가 무엇인지에 대해 알아봤습니다.
혹시나 틀린 정보가 있다면 딴지 걸어주시길..^^
반응형

+ Recent posts