[안드로이드] 컨텐트 프로바이더 생성하기

반응형







< 컨텐트 프로바이더를 만들어 볼까요? >

읽기전에 손가락 한번 클릭~ >_<

고마워요 ~ Chu ~ ♥




컨텐트 프로바이더 생성하기


컨텐트 프로바이더를 생성하려면 아래와 같은 일을 우선적으로 해야 합니다.
1. 데이터 저장을 위해 시스템을 구성해야 합니다. 대부분의 컨텐트 프로바이더는 파일 저장 메소드 또는 SQLite DB 를 통해 자신의 데이터를 저장하게 되는데요, 안드로이드에는 DB를 생성할 때 유용한 SQLiteOpenHelper 클래스와 그것을 관리할 때 유용한 SQLiteDatabase 를 제공합니다.

2. DB에 대한 접근을 제공하기 위해 컨텐트 프로바이더 클래스를 상속합니다.

3. 매니페스트에 컨텐트 프로바이더를 선언합니다.



컨텐트 프로바이더 클래스 상속하기

컨텐트 리졸버와 커서 객체의 조건을 따르는 다른것들에게, 데이터를 보여주기 위해 컨텐트 프로바이더 클래스를 상속해야 합니다.

이것은 컨텐트 프로바이더 클래스에 있는 6개의 추상 메소드를 구현하기 위함입니다.
1. query() 메소드
2. insert() 메소드
3. update() 메소드
4. delete() 메소드
5. getType() 메소드
6. onCreate() 메소드

query() 메소드는 요청받은 데이터를 반복할 수 있는 커서 객체를 리턴해야 합니다.
커서 객체는 하나의 인터페이스 입니다.

안드로이드에서는 사용가능한 미리 만들어진 몇 개의 커서 객체를 제공해 줍니다.
대표적인 SQLiteCursor 는 SQLite DB에 저장된 데이터를 반복할 수 있습니다.
어떤 SQLiteDatabase 클래스의 query() 메소드를 호출함으로써 커서 객체를 얻습니다.

이러한 컨텐트 프로바이더 메소드들은 다른 프로세스와 스레드에 있는 다양한
컨텐트 리졸버 객체에서 호출될 수 있기 때문에, 스레드 안전(thread-safe) 방식으로 구현해야만 하겠습니다.

또한 데이터에 대한 수정이 있을 경우, 리스너에게 통지하려면 ContentResolver.notifyChange() 메소드를 호출하면 되겠네요~

컨텐트프로바이더 클래스를 상속(즉, 서브클래스를 생성하는 것이죠) 하는 것 뿐만 아니라, 작업을 단순화 하고 접근성을 높이는 여러가지 방법들이 권장되고 있습니다.
⊙ CONTENT_URI 라는 이름의 public static final Uri 를 정의합니다. 이것은 컨텐트 프로바이더가 취급하는 전체 content: URI를 나타내는 문자열이 됩니다. 이 값에 대한 고유한 문자열을 정의합니다. 최선책은 소문자로 컨텐트프로바이더의 전체 클래스 이름을 사용하는 것입니다.

예를들어 MyProvider 클래스를 위한 URI는
public static final Uri CONTENT_URI=Uri.parse("content://com.exam.myprovider");

만약 프로바이더가 서브클래스를 가진다면, 또한 각각의 서브테이블에 CONTENT_URI 상수를 정의해야합니다. 이러한 URI 들은 컨텐트 프로바이더 식별을 위해 동일한 authority 를 가져야하며 경로에 의해 구별이 되야합니다.





⊙ 컨텐트프로바이더가 클라이언트에게 리턴해줄 컬럼 이름들을 정의합니다.
DB를 사용한다면
, 이 컬럼 이름은 DB의 컬럼 이름과 동일할 것입니다. 또한 클라이언트가 쿼리와 같은 명령에서 컬럼을 지정하기 위해 사용할 수 있는
public static string 상수를 정의해 주어야 하겠죠. 이때 레코드는 자동증가값(AI) 를 가지는 '_id' 컬럼을 꼭 보유해야 합니다.



클라이언트를 위해 각각의 컬럼의 데이터타입을 문서화하여 제공합니다.



⊙ 새로운 데이터 타입을 취급한다면, ContentProvider.getType() 메소드를 구현하는 곳에서 새로운 MIME 타입을 리턴하도록 정의합니다. getType() 에 제시된 content: URI 가 특정 레코드에 대한 요청을 제한하는것에 상관없이 그 타입은 content: URI 에 의존합니다. 그것에는 하나의 레코드에 해당하는 MIME 타입 한개와 여러개의 레코드에 해당하는 또 다른 MIME 타입 형식이 있습니다. 무엇을 요구하는지에 대한 도움을 주는 URI 의 메소드들을 사용하면 되겠네요



⊙ 테이블에 넣기에는 큰 데이터를 사용하고 있다면, 그 데이터를 보여주는 필드는 실제 content: URI 를 포함해야 합니다. 이것은 그 데이터파일에 클라이언트가 접근하도록 주어지는 필드입니다. 그 레코드는 그 파일에 대한 디바이스 상의 정확한 파일 경로를 나타내는 "_data" 라는 이름의 필드가 있어야 합니다.

이 필드는 클라이언트가 아니라 컨텐트 리졸버에 의해 읽혀지기 위해 존재합니다. 클라이언트는 URI 를 보유하는 사용자가 접하는 필드에 대해 ContentResolver.openInputStream() 메소드를 호출할 것입니다. 컨텐트 리졸버는 그 레코드에 대한 '_data' 필드를 요청할 것이구요

이것은 클라이언트보다 더 높은 퍼미션을 가지고 있기 때문에 그 파일에 직접적으로 접근할 수 있어야 하며, 그 클라이언트에게 파일에 대한 읽을 수 있는
래퍼(wrapper) 를 리턴합니다.





컨텐트 프로바이더 선언하기

시스템에게 직접만든 컨텐트프로바이더에 관해 인식시키려면 매니페스트 파일에서 <provider> 엘리먼트를 사용하여 정의합니다.

매니페스트에 선언되지 않은 컨텐트프로바이더는 시스템에 없는것과 마찬가지 입니다.

name 속성은 컨텐트프로바이더 서브클래스(컨텐트프로바이더를 상속받은) 전체 이름으로 지정합니다.
authrities 속성은 프로바이더를 식별하는 content: URI 영역입니다.
예를들면,


authorities 속성이 content: URI 의 경로(path)를 생략하고 있습니다.
path는 매니페스트 안에 선언되지 않습니다. path가 아니라 authorities 가 프로바이더를 식별하는 것이지요. 프로바이더는 URI 의 path를 해석할 수 있다는 의미입니다.

다른 <provider> 속성들은 데이터를 읽고 쓰는 퍼미션을 설정하거나, 아이콘과 텍스트 지정, 프로바이더의 인스턴스화 여부 등을 설정하게 해줍니다.

만약 데이터가 컨텐트프로바이더 여러개와 동기화될 필요가 없다면, multiprocess 속성을 true 로 지정하세요. 이것은 프로바이더의 인스턴스가 각 클라이언트 프로세스에서 생성될 수 있도록 하기 때문에 IPC 실행을 막아줍니다!!





끝~~







관련글
[안드로이드] 컨텐트 프로바이더의 데이터 읽기/수정/추가/삭제
[안드로이드] 컨텐트 프로바이더 쿼리하기
[안드로이드] 컨텐트 프로바이더와 URI
[안드로이드] 컴포넌트 #4 - 컨텐츠 프로바이더





반응형

댓글

Designed by JB FACTORY