[안드로이드] 컨텐트 프로바이더의 데이터 읽기/수정/추가/삭제
- 프로그래밍 정보
- 2010. 10. 22.
반응형
< 쿼리를 이용하여 컨텐트 프로바이더의 데이터를 조작해 봅시다 >
읽기전에 손가락 한번 클릭~ >_<
고마워요 ~ Chu ~ ♥
컨텐트 프로바이더 데이터 읽기
쿼리에 의해 리턴되는 커서 객체는 결과의 SET 에 대한 접근을 제공해 줍니다. 만약 ID로 특정 레코드를 쿼리하면 이 SET 은 하나의 값만 가질 것입니다. 그렇지 않으면 다수의 값을 가지겠죠. ( 일치하는 데이터가 없다면 empty 가 될 수도 있습니다 )
또 레코드에 있는 특정 필드 데이터를 읽을 수도 있습니다. 하지만 그 필드의 데이터 타입을 알아야만 합니다. 왜냐하면 커서 객체는 각 데이터 타입을 읽기 위한 별도의 메소드를 가지고 있으니까.
예를들면 getString(), getInt(), getFloat() 등이 있겠죠.
이전에 나온 쿼리에서 이름과 전화번호를 읽어 오는 소스코드 입니다.
만약 쿼리가 이미지나 사운드 같은 바이너리 데이터를 리턴할 수 있을 때, 그 데이터가 테이블에 직접 입력되어 있을수도 있고, 또는 그 데이터에 대한 테이블 엔트리가 content: URI 를 지정하는 문자열이 될 수도 있습니다.
일반적으로 약 50K 이하가 되는 데이터는 흔히 테이블이 직접 입력 되곤 합니다. 이것은 바이트 배열을 리턴하는 Cursor.getBlob() 메소드를 호출하여 읽어 올 수 있습니다.
만일 테이블 엔트리가 content: URI 라면, 이때 직접 파일을 오픈하거나 읽는것을 시도하지 맙시다. 대신에 데이터를 읽기 위한 InputStream 객체를 얻어야 하므로 ContentResolver.openInputStream() 메소드를 호출합니다.
컨텐트 프로바이더 데이터 수정하기
컨텐트 프로바이더에 의해 유지되는 데이터는 아래와 같은 작업들에 의해 수정 될 수 있습니다.
1. 새로운 레코드를 추가할 때
2. 기존 레코드에 새로운 값을 추가할 때
3. 기존 레코드를 재배치 할 때
4. 레코드를 삭제 할 때
2. 기존 레코드에 새로운 값을 추가할 때
3. 기존 레코드를 재배치 할 때
4. 레코드를 삭제 할 때
모든 데이터의 수정은 컨텐트 리졸버의 메소드를 통해서 이루어 집니다.
몇개의 컨텐트 프로바이더는 데이터를 읽을 때보다, 데이터를 쓰는 작업을 할 때 퍼미션을 요구하기도 합니다.
이때 만약 컨텐트 프로바이더에 쓰기 위한 퍼미션이 없다면, 당연히 컨텐트 리졸버 메소드를 실패하겠죠.
그럼 하나씩 살펴볼까요?
1. 새로운 레코드를 추가하기
새로운 레코드를 컨텐트 프로바이더에 추가하기 위해서는, 먼저 ContentValues 객체에 키와 값 쌍으로 된 맵(map) 을 만들어야 합니다. 이 객체의 각각의 키는 컨텐트 프로바이더에 있는 컬럼의 이름과 매칭되며, 그 값은 그 컬럼 내의 새로운 레코드에서 요구되어지는 값입니다.
그런 뒤 ContentValuesResolver.insert() 메소드를 호출하세요.
이 메소드에게 프로바이더의 URI 와 ContentValues 맵을 전달하면 됩니다.
이 메소드는 새로운 레코드에 대한 전체 URI 를 리턴해 줍니다.
즉, 새로운 레코드를 위해 추가된 ID 를 가지는 프로바이더의 URI 라는 뜻입니다.
이것을 이용하면 나중에 쿼리를 통해 URI를 사용할 수도 있고, 새로운 레코드에 대한 커서를 얻을 수도 있습니다. 또 레코드 수정을 할 때도 사용할 수 있죠.
그런 뒤 ContentValuesResolver.insert() 메소드를 호출하세요.
이 메소드에게 프로바이더의 URI 와 ContentValues 맵을 전달하면 됩니다.
이 메소드는 새로운 레코드에 대한 전체 URI 를 리턴해 줍니다.
즉, 새로운 레코드를 위해 추가된 ID 를 가지는 프로바이더의 URI 라는 뜻입니다.
이것을 이용하면 나중에 쿼리를 통해 URI를 사용할 수도 있고, 새로운 레코드에 대한 커서를 얻을 수도 있습니다. 또 레코드 수정을 할 때도 사용할 수 있죠.
2. 새로운 값을 추가하기
어떤 레코드가 현재 존재하고 있다면, 그것에 새로운 정보를 추가하거나 기존의 정보를 수정할 수 있습니다. 예를들어 이전 예제소스에서면 전화번호 등을 추가하는것이 될 수 있겠네요.
컨택 DB 에 있는 하나의 레코드에 값을 추가하는 최선책은 그 레코드에 대한 URI 에 새로운 데이터가 들어갈 테이블의 이름을 붙여주는 것입니다. 그런 다음 데이터 값 추가를 위해 수정된 URI를 사용하는 방식입니다. 이런 이유 때문에 각각의 컨택 테이블은 CONTENT_DIRECTORY 상수로써 이름을 제공하는 것이죠.
아래 소스는 이전 소스에서 생성된 레코드에 전화번호와 이메일 주소를 추가해 봅시다
바이트 배열을 가지는 ContentValues.put() 메소드를 호출함으로써, 테이블에 작은 양의 바이너리 데이터를 넣을 수도 있습니다. ( 작은 아이콘이나 짧은 사운드 파일 등 )
만약 큰 양의 바이너리 데이터를 가지고 있다면, 그 데이터에 대한 content: URI 를 데이터에 넣고, 그 파일의 URI를 가지고 ContentResolver.openOutputStream() 메소드를 호출해야 합니다. 이것은 컨텐트 프로바이더가 파일로 데이터를 저장하고 레코드 필드에 그 파일 경로를 기록하는 작업을 포함합니다.
이런 점 때문에 이미지, 사운드, 비디오 데이터를 관리하는 메인 프로바이더인 미디어스토어(MediaStore) 컨텐트 프로바이더는 특별한 규칙이 있습니다.
우선, 바이너리 데이터에 관한 메타정보를 얻기 위해 query() 또는 managedQuery() 메소드의 결과 URI가 데이터 자체를 얻기 위한 openInputStream() 에서 사용됩니다.
비슷하게 메타정보를 미디어스토어에 넣기 위해 insert() 메소드의 결과 URI가 바이너리 데이터를 넣기 위한 openOutputStream() 에서 사용됩니다.
컨택 DB 에 있는 하나의 레코드에 값을 추가하는 최선책은 그 레코드에 대한 URI 에 새로운 데이터가 들어갈 테이블의 이름을 붙여주는 것입니다. 그런 다음 데이터 값 추가를 위해 수정된 URI를 사용하는 방식입니다. 이런 이유 때문에 각각의 컨택 테이블은 CONTENT_DIRECTORY 상수로써 이름을 제공하는 것이죠.
아래 소스는 이전 소스에서 생성된 레코드에 전화번호와 이메일 주소를 추가해 봅시다
바이트 배열을 가지는 ContentValues.put() 메소드를 호출함으로써, 테이블에 작은 양의 바이너리 데이터를 넣을 수도 있습니다. ( 작은 아이콘이나 짧은 사운드 파일 등 )
만약 큰 양의 바이너리 데이터를 가지고 있다면, 그 데이터에 대한 content: URI 를 데이터에 넣고, 그 파일의 URI를 가지고 ContentResolver.openOutputStream() 메소드를 호출해야 합니다. 이것은 컨텐트 프로바이더가 파일로 데이터를 저장하고 레코드 필드에 그 파일 경로를 기록하는 작업을 포함합니다.
이런 점 때문에 이미지, 사운드, 비디오 데이터를 관리하는 메인 프로바이더인 미디어스토어(MediaStore) 컨텐트 프로바이더는 특별한 규칙이 있습니다.
우선, 바이너리 데이터에 관한 메타정보를 얻기 위해 query() 또는 managedQuery() 메소드의 결과 URI가 데이터 자체를 얻기 위한 openInputStream() 에서 사용됩니다.
비슷하게 메타정보를 미디어스토어에 넣기 위해 insert() 메소드의 결과 URI가 바이너리 데이터를 넣기 위한 openOutputStream() 에서 사용됩니다.
3. 레코드 재배치로 업데이트 하기
레코드들의 그룹을 업데이트 하려면 ( ex: 모든 'aa' 를 'AA' 로 변경하는 등 ) 변경을 원하는 컬럼과 값을 가지는 ContentResolver.update() 메소드를 호출합니다.
4. 레코드 삭제하기
하나의 레코드를 삭제하려면, 삭제를 원하는 행에 대한 URI를 가지는 ContentResolver.delete() 메소드를 호출합니다.
여러개의 행을 삭제하려면 , 삭제를 원하는 레코드 타입의 URI
(ex: android.provider.Contacts.People.CONTENT_URI)
와 삭제할 행을 정의하는 SQL WHERE 구문을 가지고 ContentResolver.delete() 메소드를 호출합니다.
하지만 삭제 전에는 항상 WHERE 절 등을 꼼꼼히 점검하시는거 잊지마세요 ^^
여러개의 행을 삭제하려면 , 삭제를 원하는 레코드 타입의 URI
(ex: android.provider.Contacts.People.CONTENT_URI)
와 삭제할 행을 정의하는 SQL WHERE 구문을 가지고 ContentResolver.delete() 메소드를 호출합니다.
하지만 삭제 전에는 항상 WHERE 절 등을 꼼꼼히 점검하시는거 잊지마세요 ^^
끝~~
관련글
[안드로이드] 컨텐트 프로바이더 쿼리하기
[안드로이드] 컨텐트 프로바이더와 URI
[안드로이드] 컴포넌트 #4 - 컨텐츠 프로바이더
반응형