반응형

이번에 어플을 만들면서 아주 쉽게 할 수 있었는데도 불구하고 찾아보지도 않고 끙끙댔던 인코딩 문제가 있었습니다.
쉽다고 생각했기 때문에 더 길을 찾지 못 했는지도 모르겠어요^^;
안 그래도 초보인데 워낙 프로그래밍을 안하다보니 ㅠㅠ

네이버 검색 API에 들어가는 키워드는 UTF-8 인코딩이라고해서
예전에 DB에 값을 넣고 받아오거나 할때의 기억을 살려서 UTF-8로 인코딩을 해봤지만 소용이 없더군요.

절망에 빠졌는데.. 이런.. 그랬습니다.
이전까지 제 경험과 다른 점이 있군요.

바로 API에 요청을 URL로 보낸다는 것입니다.
그리고 자바의 환경과 안드로이드의 환경 차이도 있겠지요?? (물음표인 이유는 저도 궁금해서..ㅎㅎ)
그래서 인코딩시 URLEncoder를 사용해야합니다.

제가 범했던 실수는 바로 이것입니다.
이러니 에러가 날 수 밖에 없었군요. URL에 표시되는 것과는 다르니까요.
처음에 정말 당당하게 이런 코드를 작성했습니다. 그러나 낭패 ^^;;

    String keyword = "편의점"; //이부부은 검색어를 UTF-8로 넣어줄거임.
    System.out.println("변환전:"+keyword);
    String query = null;
    try {
        query = new String(keyword.getBytes("8859_1"), "UTF-8");
    } catch (UnsupportedEncodingException e1) {
        e1.printStackTrace();
    }
      System.out.println("변환후 :"+query);
  
     try{
            URL url = new URL("http://openapi.naver.com/search?"
           +"key="+key
           +"&query="+query
           +"&target=local&start=1&display=4");

LogCat에 이렇게 엉뚱하게 변환 된 것이 기록 되었네요^^; 이건 뭔지;;


애뮬에도 아무것도 파싱되지 않았습니다;; 요청 URL이 에러니 뭔가 나올 거리가 없죠. 에러 태그에 대한 처리를 하지 않은 이상.


같이 어플 만드는 동생이 URLEncoder를 사용하니 바로 해결 되더군요. 짜잔~^^ 원래 알고 계셨던 분들은 피식 웃으실지도 모르지만 저에겐 대단한 발견이었습니다. 
  String keyword = "편의점"; //이부부은 검색어를 UTF-8로 넣어줄거임.  
  System.out.println("변환전:"+keyword);    
  String query = null;
  try {
   query = URLEncoder.encode(keyword,"UTF-8");
  } catch (UnsupportedEncodingException e1) {
   e1.printStackTrace();
  }  
  System.out.println("변환후 :"+query);    
        try{
            URL url = new URL("http://openapi.naver.com/search?"
           +"key="+key
           +"&query="+query
           +"&target=local&start=1&display=4");

LogCat에 깔끔하게 UTF-8로 변환된 것을 확인 했습니다.


애뮬에도 편의점에 대한 검색요청의 결과가 파싱되었습니다^^

반응형
반응형


만들고 있는 안드로이드 어플이 네이버 검색 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 클래스를 사용해서 자료에 대한 정보를 가져와 보도록 하겠습니다!!
반응형
반응형

리스트 뷰(ListView)는  어댑터 뷰(AdapterView)의 대표 위젯으로서 항목들을수직으로 펼쳐서 보여줍니다.
다른 위젯들 역시 동작 방식이 유사하기 때문에 리스트 뷰만 잘 공부해도 나머지는 쉽게 익힐 수 있습니다.

문자열을 리스트 뷰에 출력해 보겠습니다.


layout/listtest.xml
<?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">
 
  <ListView
   android:id="@+id/list"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   />
      
</LinearLayout>
리니어레이아웃 안에 리스트 뷰 위젯 하나만 배치하고 코드에서 어댑터와 연결하기 위해 리스트 뷰를 참조할 것이므로 list라는 이름으로 id를 줬습니다.


src/TestAdapterViewActivity.java
package net.test.TestAdapterView;
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class TestAdapterViewActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.listtest);
       
        //배열 데이터
        ArrayList<String> BMENTmember = new ArrayList<String>();
        BMENTmember.add("창환");
        BMENTmember.add("상종");
        BMENTmember.add("슬기");
        BMENTmember.add("예지");
        BMENTmember.add("소정");
       
        //어댑터 준비
        ArrayAdapter<String> Adapter;
        Adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, BMENTmember);
       
        //어댑터 연결
        ListView list = (ListView)findViewById(R.id.list);
        list.setAdapter(Adapter);       
    }
}
리스트 뷰에 표시한 데이터 원본은 ArrayList 객체에 생성하고  그 다음 데이터와 리스트 뷰를 연결해 중 어댑터를 생성했습니다. 항목들이 모두 문자열이니 ArrayAdapter가 가장 적합 하겠죠?

성공!! 다음과 같은 결과가 출력됩니다.!!

배열을 원본으로 사용할 때는 다음 생성자로 어댑터를 초기화 합니다.
ArrayAdapter(Context context, int textViewResourceId, List<T> objects)
ArrayAdapter(Context context, int textViewResourceId, T[] objects)
첫 번째 Context 인수에는 액티비티를 넘겨주면되고, 두 번째 인수는 항목을 표시할 레이아웃의 리소스ID입니다. 세 번째는 원본 데이터겠지요? List 인터페이스를 지원하는 컬렉션 객체(ArrayList, LinkedList, Stack 등)와 단순 배열 두 가지 타입에 대해 오버라이딩되어 있습니다.

두 번째 인수에 들어갈 레이아웃의 리소스 ID는 시스템이 목록용으로 미리 정의해 놓은 것이므로 android.R 뒤에 ID만 다음과 같은 지정하면 됩니다.

 리소스 ID  설명
 simple_list_item_1  하나의 텍스트 뷰로 구성된 레이아웃
 simple_list_item_2   두개의 텍스트 뷰로 구성된 레이아웃
 simple_list_item_checked  오른쪽에 체크 표시가 나타남
 simple_list_item_single_choice  오른쪽에 라이오 버튼이 나타남
 simple_list_item_multiple_choice  오른쪽에 체크 박스가 나타남

기본으로 제공되는 것 외에 더 복잡한 모양으로 레이아웃을 정의하고 싶으면 커스텀 뷰를 만들어야 합니다.


 

반응형

'컴퓨터&IT > 안드로이드 Android' 카테고리의 다른 글

Android - HttpURLConnection 클래스  (0) 2011.08.24
Android - HTTP로 웹에 접근하기!!  (0) 2011.08.24
Android - 어댑터 뷰(AdapterView)  (0) 2011.08.24
Android - 어댑터(Adapter)  (1) 2011.08.24
Android - Activity  (0) 2011.08.24
반응형

어댑터 뷰(AdapterView)는 같은 종류의 뷰들을 특정한 방식으로 반복해서 보여주는데 적합하며, ListView, GridView, Gallery, Spinner가 그런 뷰 컨테이너 위젯에 속합니다.

ListView
뷰 객체들을 수직 방향의 목록 형태로 보여줍니다. 수직 스크롤을 지원하며 일반적으로 목록의 각 항목은 자료를 담은 뷰이고, 사용자는 목록의 한 항목을 선택해서 일정한 작업을 수행합니다.

GridView
뷰 객체들을 고정된 개수의 열들로 이루어진 격자(Grid) 형태(2차원의 표 형태)로 배치합니다. 격자의 각 칸에 이미지 아이콘이 배치되는 경우가 많으며 사용자는 한 항목을 선택해서 일정한 작업을 수행합니다.

Gallery
뷰 객체들을 수평 방향의 목록 형태로 표시합니다. 수평 스크롤을 지원하며 이미지를 표시하는데 흔히 쓰입니다. 사용자는 한 항목을 선택해서 일정한 작업을 수행합니다.

Spinner
목록을 표시한다는 면에서 리스트뷰와 용도가 동일하나 ListView는 항상 펼쳐져 있는데 비해 Spinner는 클릭할 때만 팝업으로 펼쳐집니다. 흔히 콤보박스라고 부르는 컨트롤이 바로 Spinner 위젯이며 화면지 좁은 모바일 환경에서 면적을 적게 차지하는 장점이 있지만 목록을 보려면 팝업을 열어야 하는 단점이 있습니다.


위의 컨테이너 위젯들은 모두 AdapterView 클래스에서 파생된 것이며 AdapterView는 Adapter객체를 통해 특정 데이터 소스로부터 가져온 자료들로 자식 뷰들을 만들어서 부모 컨테이너에 채워 넣을 수 있도록 합니다.

반응형

'컴퓨터&IT > 안드로이드 Android' 카테고리의 다른 글

Android - HTTP로 웹에 접근하기!!  (0) 2011.08.24
Android - 리스트 뷰(ListView)  (0) 2011.08.24
Android - 어댑터(Adapter)  (1) 2011.08.24
Android - Activity  (0) 2011.08.24
Android 인터페이스  (0) 2011.08.24
반응형

어댑터 (Adapter)

어댑터는 데이터를 사용자 인터페이스 뷰와 바인드하는 브리징 클래스 입니다. 어댑터는 각 항목을 표현하는데 사용되는 자식 뷰 생성과 하부에 놓은 데이터에 대한 접근 제공을 담당합니다.

어댑터 바인딩을 지원하는 사용자 인터페이스 컨트롤은 반드시 어댑터 뷰(AdapterView) 추상 클래스를 확장해야 합니다. 그리고 자신만의 어댑터 뷰(AdapterView) 파생 컨트롤을 만들고, 이들을 바인드하기 위한 새로운 어댑터 클래스를 만드는 것이 가능합니다.




어댑터는 데이터를 공급하는 것과 각 항목을 나타내는 뷰를 선택하는 것 모두를 담당하기 때문에 반인드된 컨트롤의 겉모습과 기능을 획기적으로 바꿀 수 있습니다.


어댑터는 원본 데이터를 항목 뷰를 만들어 어댑터 뷰의 항목으로 보여줍니다.


안드로이드가 제공하는 몇가지 어댑터
 ArrayAdapter
ArrayAdapter는 어댑터 뷰 객체를 배열에 바인드하는 일반적인 클래스입니다. 기본 적으로 각 객체의 toString 값을 레이아웃 내에 정의된 TextView 컨트롤에 바인드 합니다.

SimpleCursorAdapter
SimpleCursorAdapter는 뷰를 컨텐트 공급자 질의를 통해 리턴된 커서에 바인드 합니다. XML 레이아웃 정의를 지정한 뒤, 결과 셋의 각 열에 있는 값을 이 레이아웃에 있는 값에 바인드 합니다.
반응형

'컴퓨터&IT > 안드로이드 Android' 카테고리의 다른 글

Android - 리스트 뷰(ListView)  (0) 2011.08.24
Android - 어댑터 뷰(AdapterView)  (0) 2011.08.24
Android - Activity  (0) 2011.08.24
Android 인터페이스  (0) 2011.08.24
Android application의 구조와 Life cycle  (0) 2011.08.24
반응형
Activity
액티비티는 하나의 사용자 인터페이스(UI)를 나타내는 단위 입니다.

하나의 앱에 여러개의 액티비티가 존재할 수 있습니다. 이 액티비티들은 각각 다른 액티비티와 독립되어 있지만 하나의 결합도니 인터페이스를 형성하기 위해 함께 동작합니다.

각각의 액티비티는 Activity 클래스를 상속하는 하위 클래스로 구현되며 하나의 윈도우가 기본적으로 제공됩니다. 윈도우 내의 컨텐츠는 VIew 클래스의 계층 구로에 의해 만들어 지고 각각의 View는 윈도우 내의 특정 영역을 제어하며 액티비티와 사용자간의 상호작용을 가능하게 합니다. parent view는 children view의 레이아웃을 포함하고 구조화하게 됩니다.  View는 Activity.setContentView() 메소드로 액티비티 윈도우 내에 위치하게 됩니다.

그리고 하나의 액티비티는  다른 앱의 액티비티를 포함한 다른 액티비티를 시작할 수 있습니다. 이 때 인텐트 객체에 필요한 정보를 추가한 후에 startActivity()의 파라미터로 전달하게 되면 다른 액티비티가 시작되게 됩니다.

이렇게 서로 다른 앱의 액티비티를 같은 Task 내에 유지함으로써 하나의 앱 처럼 사용자들은 사용할 수 있게 됩니다.


Task
태스크는 한의 스택 내에 정렬된 액티비티의 그룹으로 그 태스크를 시작했던 액티비티가스택의 root액티비티가 됩니다.

하나의 액티비티가 다른 액티비티를 시작할때 새로운 액티비티는 Push되어(스택에 올려짐) 실행상태가 됩니다. 이전의 액티비티는 스택에 남아서 사용자가 back키를 누러면 현재 액티비티가 Pop(스택에서 제거)되고, 이전의 액티비티는 resume(재개)되게 됩니다.

스택은 객체들은 포함하므로 태스크가 동일한 액티비티 하위 클래스의 인스턴스를 하나 이상 사지고 있다면 스택은 각각의 인스턴스에 대한 별도의 시작점을 가지게 됩니다.






반응형
반응형

안드로이드의 UI(사용자 인터페이스)는 View와 ViewGroup 객체를 사용하여 만들어집니다.

모든 View와 ViewGroup은 View 클래스의 하위 클래스가 되며 View 객체는 UI를 구성하는 기본 단위가 됩니다.

View 클래스는 버튼 같은 사용자 인터페이스 객체들을 제공하는 Widget에 대한 기반을 제공하고 ViewGroup 클래스는 Linear, Relative 같은 Layout에 대한 기반을 제공합니다.

View 객체는 하나의 데이터 구조로 구조의 속성에는 스크린의 특정 직사각 영역에 대한 제어를 하며, 사용자와 상호작용 지점이 되어 해당 상호작용 이벤트의 Receiver가 됩니다.

사용자 인터페이스는 선언적 방식절차적 방식으로 디자인 될 수 있습니다.

절차적 방식
절차적이란 코드에서 비롯한다는 뜻으로 예를 들면 자바로 코딩하여 JFrame, JButton 등의 모든 사용자 인터페이스 개체를 만들고 조정하는 방식을 말합니다.

선언적 방식
선언적 디자인은 XML이나 HTML같은 markup 언어로 페이지가 어떻게 작동하는지가 아니라 무엇을 나타내는지를 선언하는 방식입니다.

안드로이드는 두 가지 방식으로 만들어진 여러 프로그램 간의 차이를 좁히기 위해 절차적 방식과 선언적 방식 모두를 지원하기 때문에 자바 코드만으로 또는 XML descriptor 만으로 프로그램을 작성할 수 있습니다.
하지만 XML 코드가 자바 코드에 비해 짧고 이해가 쉽기 때문에 선언적 방식을 추천하고 있습니다.
반응형
반응형

안드로이드 앱은 task의 집합으로 안드로이드에서는 이 task를 activity라 부릅니다.
다시 말하면 하나의 activity는 앱이 수행하는 고유한 하나의 task라는 말이죠.

intent를 통해 현재 activity에서 다른 activity로 전환할 수 있습니다.
그리고 처음 화면에 띄워질 main activity는 AndroidManifest.xml 파일에서 결정합니다.


Activity의 Life cycle

  안드로이드 앱에서는 한 시점에 단 하나의 응용 프로그램 activity만이 foreground에서 실행됩니다. 우리가 자주 쓰는 윈도우와는 조금 다르죠.
  Activity callback 메서드를 이용해서 앱의 상태 및 자원을 관리합니다. 즉 한 activity의 Life cycle 동안 여러 상태를 거치게 되는데 그 때마다 적절한 callback 메서드가 호출되는 것입니다.



Activity callback 메서드
   
 onCreate(Bundle)
하나의 activity가 처음 시작되면 호출되며, setContentView() 메서드 호출과 같은 데이바인딩과 초기 설정 작업에 관여합니다.

 onStart()
activity가 사용자에게 곧 보여질 것을 나타냅니다.

 onResume()
한 activity가 스택의 제일 상위에 놓이고 foreground process가 되면 호출되는 메서드로 애니매이션이나 음악 같은 activity의 실행에 필요한 자원들을 준비하기에 적합한 메서드 입니다.

 onPause()
다른 activity가 스택의 최상위를 차지하면 현재 activity는 background로 밀려나고 이때 현재 activity의 onPause() 메서드가 호출됩니다. activity가 background에 있는 동안 필요하지 않은 자원을 해제할 마지막 기회로 onPause()메서드에서 자원을 많이 해제할 수록 activity가 background에서 죽을(kill) 가능성이 줄어듭니다.

 onStop()
activity가 사용자에서 더 이상 보여지지 않을 때 호출 되며 메모리가 얼마 남지 않았다면 호출되지 않고 시스템이 프로세스를 종료할 수 있습니다.

 onRestart()
activity가 정지 상태에서 다시 디스플레이될 때 호출됩니다.

 onSaveInstanceState(Bundle)
Activity가 죽어도 스택에서 제거되지는 않고 activity 객체의 상태가 하나의 Bundle객체에 저장됩니다. 예를 들면 텍스트 필드 내의 커서 위치에 대한 정보 처럼 activity의 필수 적이지 않은 상태를 Bundle객체에 저장합니다. 이 메서드는 디폴트 구현 값이 모든 사용자 인터페이스 제어 상태를 자동으로 저장하므로 구지 재정의할 필요는 없습니다.

 onDestroy()
activity의 lifecycle이 끝나거나 자원 부족으로 안드로이드가 activity를 죽일 때 호출 됩니다. 메모리가 얼마 남지 않았다면 호출되지 않고 시스템이 프로세스를 종료할 수 있습니다.

 onRestoreInstanceState(Bundle)
onSaveInstanceState() 메서드가 미리 저장해 둔 상태로부터 activity가 다시 초기화될 때 호출 됩니다.


반응형

'컴퓨터&IT > 안드로이드 Android' 카테고리의 다른 글

Android - Activity  (0) 2011.08.24
Android 인터페이스  (0) 2011.08.24
Android Application 구성요소(Component)  (2) 2011.08.24
Dalvik VM (Dalvik Virtual Machine)  (0) 2011.08.24
안드로이드 ? (Android)  (1) 2011.08.24
반응형

   안드로이드 앱에는 적절한 권한만 있으면 누구나 인스턴스화할 수 있는 4개의 컴포넌트가 있고 main()같은 유일한 진입점이 따로 없이 처음으로 생성되는 인스턴스의 생성자가 실질적 진입점이 됩니다.


4가지 구성요소

  Activity
 사용자 인터페이스의 기본 단위로 눈에 보이는 화면 하나를 뜻합니다. 여러 개의 View로 구성되며 App은  필요한 만큼 Activity를 가질 수 있고 그 중에 어떤 것을 화면에 띄울지 결정합니다.

  Service
UI 없이 백그라운드에서 실행되는 요소로 예를 들면 음악을 재생하는 코드를 들 수 있습니다. UI가 없기 때문에 사용자의 명령을 받아들일 수 있는 Activity와 연결해서 사용합니다.

  Broadcast Receiver(BR)
BR도 UI가 없는 것으로 시스템으로부터 전달되는 Broadcast를 대기하고 있다가 신호가 전달되면 수신하여 적절한 activity를 띄웁니다. 배터리가 떨어졌다는 신호나 데이터 전송이 완료 되었다는 등의 신호를 수신하는 역할로 이해하시면 되겠습니다.

  Content Provider(CP)
서로 다른 Application 사이에 데이터를 함부로 액세스 하지 못하도록 되어 있어 CP를 통해 프로그램간의 데이터를 공유할 수 있게 합니다. 예를 들자면 카카오톡 같은 프로그램에서 주소록의 데이터를 이용하는 것을 들 수 있겠지요.


Application은 4가지 요소 중 일부를 가질 수도 있고 여러 개를 가질 수도 있습니다.
이런 구성요소들의 구성은 manifest파일에 저장 관리 되며 최초 실행 시에 어떤 Activity를 화면에 띄울지도 같은 파일에 저장됩니다.

  구성요소간의 통신 수단 Intent
intent는 각 구성요소간의 통신을 위한 장치로 메시지에 대한 상세한 정보를 가지고 구체적인 행동을 설명하는 메카니즘입니다. 만약 '주소록 편집' activity를 호출하면 '누구의 주소를 어떻게 편집할지'가 intent에 실려 전달 됩니다. 
반응형

'컴퓨터&IT > 안드로이드 Android' 카테고리의 다른 글

Android - Activity  (0) 2011.08.24
Android 인터페이스  (0) 2011.08.24
Android application의 구조와 Life cycle  (0) 2011.08.24
Dalvik VM (Dalvik Virtual Machine)  (0) 2011.08.24
안드로이드 ? (Android)  (1) 2011.08.24
반응형
안드로이드 런타임의 Dalvik VM은 무엇일까요??

그림 출처 : http://android-developers.blogspot.com/2010/05/dalvik-jit.html

Dalvik은 Google의 Dan Bornstein이 만든 Virtual Machine 입니다.
우리가 작성한 코드는 Bytecode라는 기계에 독립적인 명령으로 컴파일되고 모바일 장치 안에 있는 Dalvik VM에 의해 실행됩니다.
 
Bytecode의 형식이 조금 다른긴 하기만 Dalvik은 결국 낮은 메모리용으로 최적화된 Java VM 이라 생각 하셔도 될 것 같습니다.

전형적인 Java에 대한 차이는 Dalvik VM은 .dex 파일을 실행 시키는데 이 파일은 표준 .class 와  .jar 파일이 컴파일 시점에서 변환된 것으로 이 .dex 파일은 클래스 파일보다 컴팩트하고 효율성이 높아 적은 메모리와 베터리를 사용하는 환경에 적합하다고 합니다.

그리고 Dalvik 이란 이름은 Bornstein이 그 의 조상이 살던 아이슬란드의 한 물고기 잡는 마을의 이름을 딴 것이라고 합니다.
 
↓↓↓이런 동네레요 ㅋㅋ아 억수로 멋있네


반응형

'컴퓨터&IT > 안드로이드 Android' 카테고리의 다른 글

Android - Activity  (0) 2011.08.24
Android 인터페이스  (0) 2011.08.24
Android application의 구조와 Life cycle  (0) 2011.08.24
Android Application 구성요소(Component)  (2) 2011.08.24
안드로이드 ? (Android)  (1) 2011.08.24
반응형

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