[데이터 조회하기]
※ 데이터 조회하기 예시
☞ 데이터를 조회하기 위해 사용되는 표준 SQL은 “select.." 구문을 사용하게 되는데 이 구문을 통해 반환되는 Cursor 객체를 받기 위해 rawQuery() 메서드를 실행합니다. 즉, executeSQL()은 결과 값이 없는 SQL 실행 방법이며, rawQuery()는 결과 값을 Cursor 객체로 받을 수 있는 SQL 실행방법 입니다.
☞ Cursor 객체는 처음에는 아무런 레코드를 가리키지 않으며, moveToNext() 메서드를 이용해 그 다음 레코드를 가리키도록 해야 레코드 값을 가져올 수 있습니다. 따라서 while 구문을 이용해 moveToNext() 가 false 값을 반환할 때 까지 레코드 값을 가져오는 방법을 일반적으로 사용합니다.
☞ 칼럼에 대한 정보를 알아보는 방법으로 getColumnCount() 메서드를 이용해 칼럼의 전체 개수를 알아낸 후 각각의 칼럼 인덱스를 칼럼 이름으로 알아낼 수 있습니다. 그리고 getColumnNames() 메서드를 이용해 모든 칼럼의 이름을 확인한 후 각각의 칼럼이 어떤 인덱스 값으로 확인할 수 있는지를 getColumnIndex() 메서드를 이용해 알아낼 수도 있습니다.
☞ 커서는 데이터베이스와 마찬가지로 사용한 후에 close() 메서드를 이용해 닫아야 합니다.
[내용 제공자(Content Provider) 이해하기]
1. 내용 제공자는 콘텐트 프로바이더(Content Provider)라고도 부르며 한 앱에서 관리하는 데이터를 다른 앱에서도 접근할 수 있도록 해줍니다.
2. 내용 제공자도 앱 구성요소이기 때문에 시스템에서 관리하며 매니페스트 파일에 등록해야 사용할 수 있습니다.
3. 내용 제공자가 필요한 이유는 앱의 보안 때문입니다. 다른 사람이 만든 앱이 나의 앱의 데이터를 마음대로 바꾸면 안되겠죠. 그래서 각 앱은 자신의 프로세스와 권한 안에서만 데이터에 접근할 수 있도록 되어있습니다.
4. 하지만, 서로 다른 앱의 데이터에 접근해야 하는 경우도 있습니다. 바로 그때 내용 제공자를 사용하면 됩니다. 내용 제공자를 사용하면 다른 앱에게 데이터 접근 통로를 열어줄 수 있습니다. 주의할 점은 반드시 허용된 통로로만 접근해야 한다는 것입니다.
★ 내용 제공자에서 공유할 수 있는 데이터
- 데이터 베이스
- 파일
- SharedPreferences
5. 이 중에서 데이터베이스에 접근하는 것이 가장 일반적입니다. 왜냐하면 내용 제공자는 CRUD 에 대응되는 insert(), query(), update(), delete() 메서드를 지원합니다.
6. 내용 제공자에서 허용한 통로로 접근하려면 콘텐트 리졸버(ContentResolver) 객체가 필요합니다.
※ 내용 제공자(Content Provider) 예시
☞ 내용 제공자를 만들기 위해서는 고유한 값을 가진 content URI를 만들어야 합니다. 여기에서는 앱의 패키지 이름과 person 테이블의 이름을 합쳐 content URI를 정의했습니다.
★ content URI 정의형식
content://org.techtown.provider/person/1
content:// > 내용 제공자에 의해 제어되는 데이터라는 의미로 항상 content:// 로 시작함
Authority > org.techtown.provider 부분을 가리키며 특정 내용 제공자를 구분하는 고유값
Base Path > person 부분을 가리키며 요청할 데이터의 자료형을 결정함 (여기에서는 테이블 이름)
ID > 맨 뒤의 1과 같은 숫자를 가리키며 요청할 데이터 레코드를 지정함
☞ UriMatcher 객체는 URI를 매칭하는 데 사용됩니다. match() 메서드를 호출하면 UriMatcher에 addURI() 메서드를 이용해 추가된 URI 중에서 실행 가능한 것이 있는지 확인해줍니다.
☞ 내용 제공자에 접근하기 위하여 ContentResolver 객체도 사용됩니다. 액티비티에서 getContentResolver() 메서드를 호출하면 ContentResolver 객체를 반환합니다. 이 객체에는 query(), insert(), update(), delete() 등의 메서드가 정의되어 있어 내용 제공자의 URI를 파라미터로 전달하면서 데이터를 조회, 추가, 수정, 삭제하는 일이 가능합니다.
☞ notifyChange() 메서드는 레코드가 추가, 수정, 삭제되었을 때 변경이 일어났음을 알려주는 역할을 합니다.
☞ 내용 제공자를 이용해 값을 조회하고 싶다면 다음과 같은 query() 메서드를 사용합니다.
★ Cursor query (
Uri uri,
String[] projection, // 조회칼럼 지정
String selection, // where 절에 들어갈 조건 지정, null = where 절이 없음
Stirng[] selectionArgs, // 세번째 파라미터에 값이 있을 경우 그 안에 들어갈 조건 값을 대체하기 위해 사용
String sortOrder // 정렬 칼럼을 지정, null = 정렬 적용 x
)
☞ 내용 제공자를 이용해 값을 추가하고 싶다면 다음과 같은 insert() 메서드를 사용합니다.
★ uri insert (
Uri uri,
ContentValues values // 저장할 칼럼명과 값들이 들어간 ContentValues 객체
)
결과 값으로는 새로 추가된 값의 Uri 정보가 반환됩니다.
☞ 내용 제공자를 이용해 값을 수정하고 싶다면 다음과 같은 update() 메서드를 사용합니다.
★ int update (
Uri, uri
ContentValues values, // 저장할 칼럼명과 값들이 들어간 ContentValues 객체, null이 되면안됨!!
String selection, // where절에 들어갈 조건 지정, null = where 절 없음
String[] selectionArgs // 세 번째 파라미터에 값이 있을 경우 그 안에 들어갈 조건 값을 대체하기 위해 사용
)
결과 값으로는 영향을 받은 레코드의 개수가 반환됩니다.
☞ 내용 제공자를 이용해 값을 삭제하고 싶다면 다음과 같은 delete() 메서드를 사용합니다.
★ int delete (
Uri uri,
String selection, // where 절에 들어갈 조건 지정, null = where 절 없음
String[] selectionArgs // 두 번째 파라미터에 값이 있을 경우 그 안에 들어갈 조건 값을 대체하기 위해 사용
)
결과 값으로는 영향을 받은 레코드의 개수가 반환됩니다.
☞ getType() 메서드는 MIME 타입이 무엇인지를 알고 싶을 때 사용합니다.
★ String getType (
Uri uri
)
Uri 객체가 파라미터로 전달되며 결과 값으로 MIME 타입이 반환됩니다.
☞ 첫 번째 버튼을 누르면 insertPerson() 메서드가 호출됩니다.
insertPerson() 메서드 안에서는 먼저 Uri 객체를 만들고
ContentResolvier 객체의 query()메서드를 호출하면서 Uri 객체를 파라미터로 전달합니다.
ContentResolver 객체는 getContentResolver() 메서드를 호출하면 참조할 수 있으며 query() 메서드를 호출하면 그 결과 값으로 Cursor 객체가 반환됩니다.
Cursor 객체를 이용해 결과 값을 조회할 수 있는데 결과 레코드에 들어가 있는 칼럼의 이름을 조회하고 싶다면 getColumnNames() 메서드를 사용할 수 있습니다.
레코드를 추가할 때는 ContentValues 객체가 사용되는데 getColumnNames() 메서드를 이용해 알아낸 칼럼 이름을 사용할 수도 있고 직접 칼럼 이름을 지정할 수도 있습니다.
☞ 두 번째 버튼을 눌렀을 때 queryPerson 메서드를 호출하도록 코드를 입력합니다.
먼저 Uri 객체를 만들고 ContentResolver 객체의 query() 메서드를 호출하면서 Uri 객체를 전달하면 Cursor 객체가 반환됩니다. query() 메서드를 호출할 때 Uri 객체 외에 columns 도 전달하고 있는데 여기에는 조회할 칼럼의 이름이 문자열의 배열 형태로 들어가 있습니다. 이렇게 하면 지정한 칼럼만 조회됩니다.
Cursor 객체가 반환되면 각 칼럼 이름에 해당하는 칼럼 인덱스 값을 확인한 후 칼럼 값을 조회합니다.
Cursor 객체는 moveToNext() 메서드를 호출하면서 결과 레코드를 넘길 수 있으므로 while 문 안에서 moveToNext를 호출하면서 각 레코드의 값을 출력하도록 합니다.
☞ 세 번째 버튼을 눌렀을 때, updatePerson() 메서드를 호출합니다.
where 조건의 문자열에 ‘mobile = ?’를 넣었으므로 그 안에 ? 기호가 하나 들어있습니다. 이 기호는 selectionArgs 배열 변수의 첫 번째 원소로 대체됩니다. 따라서 where 조건은 ‘mobile = 010-1000-1000’ 이 됩니다.
[앨범과 연락처 조회하기]
1. 실제 앱을 만들 때는 내용 제공자를 사용하지 않는 경우도 많습니다. 그리고 내용 제공자를 직접 만들어야 할 때보다 내용 제공자를 사용해야 하는 경우가 더 많을 것입니다.
※ 앨범 조회하기 예시
※ 연락처 조회하기 예시
☞ 인텐트 객체를 만들 때는 첫 번째 파라미터로 Intent.ACTION_PICK 이라는 액션 정보를 전달하고 두 번째 파라미터로는 ContactsContract.Contacts.CONTENT_URI 를 전달합니다. 이 값은 연락처 정보를 조회하는 데 사용되는 URI 값입니다.
☞ startActivityForResult() 메서드가 호출되면 연락처를 선택할 수 있는 화면이 표시됩니다. 사용자가 연락처를 하나 선택하면 onActivityForResul() 메서드가 자동으로 호출됩니다.
☞ 이 메서드로 전달되는 인텐트 객체의 getData() 메서드를 호출하면 선택된 연락처 정보를 가리키는 Uri 객체가 반환됩니다. 이 Uri 객체의 getLastPathSegment() 메서드를 호출하여 id 값을 확인합니다. 이렇게 id 값을 확인하는 이유는 선택한 연락처의 상세 정보가 다른 곳에 저장되어 있기 때문입니다.
[뷰에 그래픽 그리기]
구분 |
설명 |
1단계 |
새로운 클래스를 만들고 뷰를 상속받습니다. |
2단계 |
페인트 객체를 초기화하고 필요한 속성을 설정합니다. |
3단계 |
onDraw() 메서드 내에 사각형을 그리는 메서드를 호출합니다. |
4단계 |
onTouchEvent() 메서드 내에 터치 이벤트를 처리하는 코드를 넣습니다. |
5단계 |
새로 만든 뷰를 메인 액티비티에 추가합니다. |
※ 뷰에 그래픽 그리기 예시