아이폰을 보다보면 On Off 버튼 쪼기 조것을 많이 사용 하는데, 왠지 멋있어 보여서. Android 용으로 아이폰과 비슷(?) 하게 동작 하는 custom widget을 만들어 보고 싶었음. 그냥 그렇다구.

Custom widget 이라고 해봐야 별거 없고 그냥 만들어 보면 됨 (안될라나?)

시작하게 된다면 나름 생각 있는 프로그래머? 라면 대충 View 혹은 ViewGroup을 상속 받아서 만들려고 시도 할꺼임? 내말과 다르면 별수 없고...

나는 View 상속 받아서 만들꺼임. 나도 잘 모르고 혹 잘 따라오신다면 나 보다 더많은걸 건져 갈 수 있을지도... 움헤헤헤


난 이미 얼추 다만들어 놨기때문에 대충 내 플젝 상태는 이러함.

프로젝트 네임 OnOffButton, 패키지명 com.android.customwidget 뭐 이정도면 될듯.

참고로 그림 한장이 필요한데 아이폰에 있는 on off button 그림 이게 필요함.

우앙 댑따 크다~ ㅋㅋ 준비물 끝... 담편으로 고고씽~

'Android' 카테고리의 다른 글

Android Custom Widget 만들기 3편  (0) 2012.04.12
Android Custom Widget 만들기 2편  (0) 2012.04.12
Android Study ListView Indexer 6편  (3) 2012.03.07
Android Study ListView Indexer 5편  (0) 2012.03.07
Android Study ListView Indexer 4편  (0) 2012.03.07
뭐 고작 ListView에 index 넣는 걸로 엄청 오래 끌었는데... 무튼 이제 거의 다왔음요.

전편 필요한 분.
2012/03/07 - [Android Study] - Android Study ListView Indexer 5편 

Layout 파일 내용.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/header"
        android:layout_width="match_parent"
        android:layout_height="25dip"
        android:clickable="false"
        android:background="@*android:drawable/dark_header"
        android:gravity="center_vertical"
        android:focusable="false"
        android:visibility="gone">

        <TextView
            android:id="@+id/head"
            android:layout_width="56dip"
            android:layout_height="wrap_content"
            android:textStyle="bold"
            android:textColor="@*android:color/dim_foreground_dark"
            android:textSize="14sp"
            android:gravity="center"/>
    </LinearLayout>

    <TextView
        android:id="@+id/text1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:minHeight="?android:attr/listPreferredItemHeight"
        android:gravity="left|center_vertical"
        android:layout_weight="1"
        android:textAppearance="?android:attr/textAppearanceMedium"/>
</LinearLayout>
붉은 색 부분이 index 표현을 위해서 추가된 code임. Layout 설명은 생략 하도록 하겠음.
IconAdapter에 추가된 함수

private void bindSectionHeader(View itemView, int position) {
    final int section = getSectionForPosition(position);
    LinearLayout header = (LinearLayout) itemView.findViewById(R.id.header);
    TextView head = (TextView) itemView.findViewById(R.id.head);
    if (getPositionForSection(section) == position) {
        String title = (String)mIndexer.getSections()[section];
        head.setText(title);
        header.setVisibility(View.VISIBLE);
    } else {
        header.setVisibility(View.GONE);
    }
}

Index 표시하는 부분 임 그럼 이 함수를 어디서 호출 해주는 것이냐 하면.

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    mCursor.moveToPosition(position);
    if (convertView == null) {
        convertView = newView(mContext, mCursor, parent);
    }
    bindView(convertView, mContext, mCursor);
    bindSectionHeader(convertView, position);
    return convertView;
}

이렇게 CursorAdapter 에 기본 함수 getView에서 호출 하도록 만들면 땡!
그러면 Adapter는 어떻게 초기화 하냐 하면.

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.list_content);

    mAdapter = new IconAdapter(this, null);
    mList = (ListView) findViewById(android.R.id.list);
    mList.setAdapter(mAdapter);
    mList.setOnItemClickListener(this);

    Cursor cursor = getContentResolver().query(PracticeColumns.CONTENT_URI, 
    new String[] {PracticeColumns.ID, PracticeColumns.DATA}, null,
    null, PracticeColumns.DATA + " ASC");
    mAdapter.changeCursor(cursor);
}

Adapter 에서 changeCursor를 호출하면 땡!

이런 DB를 출력하면

이렇게 출력됨.


보통 Code를 통째로 공개하지는 않지만... 흠흠 이번엔 특별히 내가 귀찮으므로... 첨부~

AndroidList.zip


'Android' 카테고리의 다른 글

Android Custom Widget 만들기 2편  (0) 2012.04.12
Android Custom Widget 만들기 1편  (1) 2012.04.12
Android Study ListView Indexer 5편  (0) 2012.03.07
Android Study ListView Indexer 4편  (0) 2012.03.07
Android Study ListView Indexer 3편  (0) 2012.03.07
전편 필요한분
2012/03/07 - [Android Study] - Android Study ListView Indexer 4편

여기 까지 해놓으면 대충 기본은 완성 해둔 상태 임.
이제 mIndexer 초기화와 사용 법을 알려 주겠음요.

여기서 부터는 아래 글 안보고 온 분들은 멘탈 붕괴될테니 꼭 보시길...
2012/02/08 - [Android Study] - Android List에 index를 표시해보자 1편 

PracticeIndexer 초기화

        // CursorAdapter 에서 제공하는 기본 함수 Cursor 변경 하고 싶을때 호출하면됨
        @Override
        public void changeCursor(Cursor cursor) {
            super.changeCursor(cursor);
            updateIndexer(cursor);
            mCursor = cursor;
        }
 
        // Indexer 초기화 함수
        private void updateIndexer(Cursor cursor) {
            // cursor가 null 이면 초기화 종료 
            if (cursor == null) {
                mIndexer = null;
                return;
            }
            // Provider 에서 만들어 준 Indexer 얻어 오기. 
            Bundle bundle = cursor.getExtras();
            // 붉은색 긁씨는 꼴릿한 데로 작성해도 됨 단 Provider와 동일하게 설정해야 함. 
            // bundle에 내용이 있으면 PracticeIndexer 초기화 
            if (bundle.containsKey(PracticeColumns.EXTRA_DATA_INDEX_TITLES)) {
                String sections[] =
                    bundle.getStringArray(PracticeColumns.EXTRA_DATA_INDEX_TITLES);
                int counts[] = bundle.getIntArray(PracticeColumns.EXTRA_DATA_INDEX_COUNTS);
                // PracticeIndexer 초기화
                mIndexer = new PracticeIndexer(sections, counts);
            } else {
                mIndexer = null;
            }
        }


예전에 index 관련 내용을 잘 따라 오셨다면 요기 까지는 무난 하게 완성 할 꺼임 담은 사용 법.

ListView에 사용할 layout 파일을 수정 해야 함.
Index를 listView에 일일이 add 해도 되긴 하지만 그랬다간 position이 미친듯이 꼬일 꺼임.
추천 하는 방법으로는 layout에 해더부분을 만들고 Visibility를 gone 상태로 항시 유지 하는 것임.

To be continue...

'Android' 카테고리의 다른 글

Android Custom Widget 만들기 1편  (1) 2012.04.12
Android Study ListView Indexer 6편  (3) 2012.03.07
Android Study ListView Indexer 4편  (0) 2012.03.07
Android Study ListView Indexer 3편  (0) 2012.03.07
Android Study ListView Indexer 2편  (1) 2012.03.07
전편 필요한 분.
2012/03/07 - [Android Study] - Android Study ListView Indexer 3편

PracticeIndexer class 내용 입니당.
public class PracticeIndexer implements SectionIndexer {
    // Index 내용
    private final String[] mSections;
    // Index 위치 
    private final int[] mPositions;
    // 최종 index 위치 
    private final int mCount;

    public HistortSectionIndexer(String[] sections, int[] counts) {
        // 생성자에서 Index 내용, 위치 배열 설정 null 이면 그냥 종료
        if (sections == null || counts == null) {
            throw new NullPointerException();
        }
        // Index 내용, 위치 배열 크기가 다르면 그냥 종료
        if (sections.length != counts.length) {
            throw new IllegalArgumentException(
                    "The sections and counts arrays must have the same length");
        }

        // Index 내용 초기화
        this.mSections = sections;
        // 위치는 같은 index를 사용 하는 것이 몇개 인지 counting 해서 전달 함.
        // 그래서 count를 일일이 더해야 실제 위치가 나옴. 위치 배열 새로 생성
        mPositions = new int[counts.length];
        int position = 0;
        for (int i = 0; i < counts.length; i++) {
            // Index 내용이 null 이면 공백으로 초기화 
            if (mSections[i] == null) {
                mSections[i] = " ";
            } else {
                // Index 내용에 공백 있으면 제거
                mSections[i] = mSections[i].trim();
            }
            // Index 위치 초기화
            mPositions[i] = position;
            // counting 된 값 더하기. 
            position += counts[i];
        }
        // Index의 최종 위치 지정 
        mCount = position;
    }

    // Index 내용 반환
    @Override
    public Object[] getSections() {
        return mSections;
    }

    // Index 위치 반환
    @Override
    public int getPositionForSection(int section) {
        if (section < 0 || section >= mSections.length) {
            return -1;
        }

        return mPositions[section];
    }

    // Index 위치 내용을 binarySearch 해서 배열 index 반환
    @Override
    public int getSectionForPosition(int position) {
        if (position < 0 || position >= mCount) {
            return -1;
        }

        int index = Arrays.binarySearch(mPositions, position);
        /*
         * Consider this example: section positions are 0, 3, 5; the supplied
         * position is 4. The section corresponding to position 4 starts at
         * position 3, so the expected return value is 1. Binary search will not
         * find 4 in the array and thus will return -insertPosition-1, i.e. -3.
         * To get from that number to the expected value of 1 we need to negate
         * and subtract 2.
         */
         // 위 코멘트는 Google 꺼... 내용인 즉슨 예를 들어 인덱스 위치가 0,3,5 이면
         // 현재 위치가 4면 가까운 시작 위치가 3이니깐 1이 반환 되야함
         // 근데 Binary search에 의해서 4가 나옴
         // 그러니깐 -3이 반환되게 해서 4 + (-3) 하면 1이 나오게 됨.
        return index >= 0 ? index : -index - 2;
    } 


이 코드역시 google base code를 따온것 이구요.
힘드니께 담 이야기는 담편으로~
 

'Android' 카테고리의 다른 글

Android Study ListView Indexer 6편  (3) 2012.03.07
Android Study ListView Indexer 5편  (0) 2012.03.07
Android Study ListView Indexer 3편  (0) 2012.03.07
Android Study ListView Indexer 2편  (1) 2012.03.07
Android Study ListView Indexer 1편  (0) 2012.03.07

후~ 전편은 여기로!
2012/03/07 - [Android Study] - Android Study ListView Indexer 2편 

아흥 슬슬 어케 마무리 지어야 할지 매우 난감하네...
private class IconAdapter extends CursorAdapter implements SectionIndexer {
    private SectionIndexer mIndexer;
    
@Override
    public int getPositionForSection(int sectionIndex) {
        if (mIndexer == null) {
            return -1;
        }
        return mIndexer.getPositionForSection(sectionIndex);
    }
 
    @Override
    public int getSectionForPosition(int position) {
        if (mIndexer == null) {
            return -1;
        }
        return mIndexer.getSectionForPosition(position);
    }

    @Override
    public Object [] getSections() {
        if (mIndexer == null) {
            // 이거 null 리턴하면 200% 에러 발생함. 그냥 요롷게 주는게 속편함.
            return new String[] { " " };
        } else {
            return mIndexer.getSections();
        }
    } 
}
정말 별거 없는 내용임... 그냥 mIndexer 객체가 null 일 경우만 정해 주면 알아서 처리가 됨. 참 쉽죠잉~ 
다음 편은 PracticeIndexer class 내용 입니당~

'Android' 카테고리의 다른 글

Android Study ListView Indexer 5편  (0) 2012.03.07
Android Study ListView Indexer 4편  (0) 2012.03.07
Android Study ListView Indexer 2편  (1) 2012.03.07
Android Study ListView Indexer 1편  (0) 2012.03.07
LayoutInflater에 대하여...  (0) 2012.02.15
전편 필요 한분 ㄱㄱㅆ
2012/03/07 - [Android Study] - Android Study ListView Indexer 1편 

나는 늘 이게 문제인듯 ㅍㅍ 발행 해놓고 한동안 잠적질?? (마치 왕창 똥싸놓고 튀는 느낌ㅋ)
우리 이제 후후 실전 code를 짜보아요~ let's go!

Base 뼈대 Code.
private class IconAdapter extends CursorAdapter implements SectionIndexer {
    private PracticeIndexer mIndexer;
    @Override
    public int getPositionForSection(int section) {
        return 0;
    }

    @Override
    public int getSectionForPosition(int position) {
        return 0;
    }

    @Override
    public Object[] getSections() {
        return null;
    }

위 뼈대 code만 체우면 제대로 된거 나올꺼 같은 느낌이 마구마구 샘솓음 으캬~
Indexer 사용 하려면 기본 뼈대니까 그냥 외워버리...기는 너무 큰가?
별거 없음 그냥 위에 @Override 함수하고 PracticeIndexer 만 체워 넣으면 되는 거니깐 너무 겁먹지 마시고..

PracticeIndexer class는 SecticeIndexer를 상속 받은 class

getSectionForPosition 함수는 현재 ListView position을 넣으면 해당 배열 위치가 반환 됨
getPositionForSection 함수는 현재 section 배열 위치를 넣으면 해당 position이 반환 됨

요지는  getSectionForPosition 이걸로 현재 section 위치 얻어옴. 이 위치에 다음 section의 위치를 얻고 싶응 께 getPositionForSection 요걸로 얻어 오는 거임.
왜 이렇게 하냐면 현재 List의 위치에 sectionIndexer가 끝인지 시작인지, 다음 껀지 모르니까 담 section 위치와 List의 현재 위치를 비교해서 처리 하려고 하는 거임.
무튼 실전 코드는 담편에... (난 편수 늘리기 대마왕~)

- 네가 알고 있는 지식을 순순히 내놓는다면 유혈 사태는 벌어지지 않을 것이다..?


후~ 간만에 돌아와서 Android 강좌를 하게 되었네... (웃음...)
자 전편에 이어서 마무리~ ㄱㄱㅆ

2012/02/08 - [Android Study] - Android List에 index를 표시해보자 1편 


Android 에서 IPhone 처럼 list에 index 표시 하려면 indexer라는 걸 이용 하는 것이 속편한거 같다.
Indexer는 2개가 있는데 SectionIndexer와 AlphabetIndexer 요고...
자세히 다 아는건 아닌데 그냥 사용해 본 경험만 있는 (읭? 무슨 말인지?)

내가 사용 할 녀석은 SectionIndexer 이거 쓸꺼임. 사용 할 곳은 Adapter(ListView 내용물 처리 해주는 녀석). 에다가 사용 할 예정임.

이렇게 말로만 하면 이해도 안되고 감흥도 없고 지루하기 짝이 없겠지??
그래서 준비한 code...
private class IconAdapter extends CursorAdapter implements SectionIndexer {
    ...
}

뭐 대충 이렇다는거 사실 SectionIndexer에는 3개의 abstract 함수가 존재함
그거 다 구현 해야하는데 그건 담편으로 넘길꺼임,
마찬가지로 BaseAdapter 여기에도 abstarct 함수가 존재함.
이건 예전에 강좌로 남겼기 때문에 버릴예정. 모르겠으면 전편 찾아보시길...

담편에서 보아용~
 

'Android' 카테고리의 다른 글

Android Study ListView Indexer 3편  (0) 2012.03.07
Android Study ListView Indexer 2편  (1) 2012.03.07
LayoutInflater에 대하여...  (0) 2012.02.15
Cursor close 해야 하는 이유와 하는 방법.  (2) 2012.02.14
Android database 만들기 7편  (0) 2012.02.10

Android 사용 하다 보면 xml로 된 layout 파일을 어떤 식이든지 View 형태의 객체로 얻고 싶은 경우가 있을 것 이다. (없으면 말고...)

이 때 사용되는 녀석이 LayoutInflater 라는 녀석인데.
첨음 내가 이걸 접할때 대체 뭐하는 넘이지 하는 막연한 생각만 가지고 있어서 설명을 해볼까 함.

우선 layout.xml이 필요함.
그리고 LayoutInflater가 필요한데.
얻는 방법은 2가지가 있음.
- LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- LayoutInflater inflater2 = getLayoutInflater();

각각 차이점은 inflater는 system에서 얻어 오는 방법이고,
inflater2는 Activity에서 제공하는 메소드를 이용해 얻어 오는 방법임. (둘다 별반 차이없음)

inflater는 View객체를 반환 해주는 4가지 메소드가 존재함.
// 리소스(R.layout.xxx), root
inflater.inflate(resource, root);
// XMLparser, root  
inflater.inflate(parser, root);
// 리소스(R.layout.xxx), root, attach 조건(보통 false)
inflater.inflate(resource, root, attachToRoot);
//  XMLparser, root, attach 조건(보통 false)
inflater.inflate(parser, root, attachToRoot);
이렇게 4가지 이고 각각의 파라메터에 대한 부연 설명을 하자면,
리소스는 프로젝트/res/layout 폴더에 들어 있는 xml 파일을 지정 하면됨,
XMLparser는 잘 안쓰니 버리고(나도 써본적이 없음),
root는 내가 지정한 리소스(xml 파일)이 어디에 붙을 껀지 지정하는 것임(없으면 null 넣으면됨),
attach 조건 이게 좀 복잡한데 이해 하려면  LayoutParams 이란 걸 알아야함.
LayoutParams은 xml 상에서 (android:layout_width, android:layout_height) 을 code로 정의 해주는 녀석인데 이녀석에 대한 생성 기준을 어디로 설정 할 것이냐 묻는 것이다.

예를 들어 내가 show_item.xml 파일을 list라는 LinearLayout 에다가 add 하고 싶다고 한다면.
//  LinearLayout 객체 생성
LinearLayout list = (LinearLayout)findViewById(R.id.list);
//  LinearLayout 객체 초기화 
list.removeAllViews();
//  LayoutInflater 객체 생성
LayoutInflater inflater = getLayoutInflater();
//  View 객체 생성
View view =inflater.inflater(R.layout.show_item, list(View를 붙일 녀석), false(붙일 조건));
//  LinearLayout 객체에 View 객체 추가 
list.add(view);
이렇게 될 것이다. 이때 붙일 조건이 중요한데 이녀석이 false 이면, show_item.xml에서 사용된 (android:layout_width, android:layout_height) 값들을 list에다가 새로 추가를 해주는 작업을 하게 된다. (맞니?...)
Android Developer에 있는 붙일 조건에 대한 설명
(Whether the inflated hierarchy should be attached to the root parameter? If false, root is only used to create the correct subclass of LayoutParams for the root view in the XML)

이렇덴다.. 후후. 
 

간혹 어플을 만들고 나면 logcat 에서 다음과 같은 error 문구가 발생 하는 걸 볼 수 있다.

04-18 07:59:04.280: ERROR/Cursor(31526): Finalizing a Cursor that has not been deactivated or closed. 
 

(없으면 말고~) 위에 저 에러는 내가 발생 시킨건 아니고 어디서 퍼온거임.

여튼 이런 에러의 원인을 설명 해보자면 (나도 확실히 아는건 아님)
정확히 버전은 기억이 안나지만 아마 Froyo 부터 일듯 싶음.

Android 2.2 부터 Cursor 객체에 대한 GC를 보장 하지 않기 때문인 듯 사료됨.
무슨 뜻인고 하니 JAVA는 사용하다가 안쓰는 객체는 V 머신에서 free를 해주는 방법을 취하고 있는데.
정상 적이라면 android도 java니깐 dalvik 에서 우리가 안쓰는 객체를 free 하는 작업을 해주고 있는 거임.

근데 Cursor 객체는 지금 당장 사용 중이 아니라도 뭔가 목적을 위해 일부로 열어 둔것 일 수 도 있으니 dalvik 에서 인위 적으로 free 안해주겠다는 것임.
이렇게 되면 Activity는 끝났는데 cursor만 안끝나는 경우가 생김. 그러면 어케 되냐면 cursor 하나 때문에 activity 전체가 종료가 안되는 경우가 발생 할 수 있음 (순전히 내생각...)

그래서 따로 Cursor에 대해서 close 해달라고 난리 치는거임. 후훗~

일반적으로 cursor는 그냥 cursor.close() 이걸로 해결 되는데
문제는 ListView에 연결해 놓은 cursor 들임...
대부분 CursorAdapter 라던지 뭐 이런 것들로 처리를 했을 텐데.
close() 시키는 방법은 Activity라면 onDestroy() 가 적당 할 것임. (종료 하는 부분이 좋음)
무튼 onDestroy() 함수에다가 CursorAdapter 라던지 ListView라던지 객체를 얻어서 보통은
mList.getAdapter().getCursor().close(); 이러던가, mAdapter.getCursor().close();
이런식으로 종료를 처리함.

굉장히 허접하지만... 후훗~ 

'Android' 카테고리의 다른 글

Android Study ListView Indexer 1편  (0) 2012.03.07
LayoutInflater에 대하여...  (0) 2012.02.15
Android database 만들기 7편  (0) 2012.02.10
Android database 만들기 6편  (0) 2012.02.10
Android database 만들기 5편  (0) 2012.02.10
이전글 필요한분.

2012/02/10 - [Android Study] - Android database 만들기 6편 

변경 전
    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
        return null;
    }
변경 후 
    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
        switch(Matcher.match(uri)){
        case KIND_DATA :
          // 질의 요청 Cursor 형태로 return 됨 그리고 좀 찾아보면 좋은거 있음
          // GroupBy, 라던지 Having이라던지 이런것도 가능 하게 해줌 
 
            return mPracticeDB.query(PRACTICE_TABLE, projection, selection, selectionArgs, null, null, sortOrder);
        default :
            return null;
        }
    }
 
변경 전
    @Override
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs) {
        return 0;
    }
변경 후 
    @Override
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs) {
       // DB에 없뎃한 갯수 
        int count = 0;

        switch(Matcher.match(uri)){
        case KIND_DATA :
          // 질의 요청 DB에 업뎃요청
            count = mPracticeDB.update(PRACTICE_TABLE, values, selection, selectionArgs);
            break;
        default :
            count = 0;
        }
       // URI에 DB 갱신했다고 알려줌
        getContext().getContentResolver().notifyChange(uri, null);
        return count;
    } 

으캬~ 겨우 ContentProvider 다 완성 헀다.
이제 사용법이 궁금 하지 않음요?
 
DB 추가.
ContentValues values = new ContentValues();
        values.put(PracticeColumns.DATA, "Hello");
        Uri resutlUri = getContentResolver().insert(PracticeColumns.CONTENT_URI, values); 

DB 업데이트 (ID 값이 1번인 내용을 업데이트 할때)
ContentValues values = new ContentValues();
        values.put(PracticeColumns.DATA, "Android");
        int result = getContentResolver().update(PracticeColumns.CONTENT_URI, values,
                           PracticeColumns.ID + " = 1", null);
 
DB 삭제.  (ID 값이 1번인 내용을 삭제 할때) 
        int result = getContentResolver().delete(PracticeColumns.CONTENT_URI,
                          PracticeColumns.ID + " = 1", null);

DB 질문.
Cursor cursor = getContentResolver().query(PracticeColumns.CONTENT_URI,
               new String[] {PracticeColumns.ID, PracticeColumns.DATA}, null, null, null); 

요롷게 쓰면 된당께... 으흐흐. 

'Android' 카테고리의 다른 글

LayoutInflater에 대하여...  (0) 2012.02.15
Cursor close 해야 하는 이유와 하는 방법.  (2) 2012.02.14
Android database 만들기 6편  (0) 2012.02.10
Android database 만들기 5편  (0) 2012.02.10
Android database 만들기 4편  (0) 2012.02.10

+ Recent posts