본문 바로가기
프로그래밍 놀이터/안드로이드, Java

[android] Content Provider ( 콘텐트 프로바이더 ) 에 대한 모든 것.

by 돼지왕 왕돼지 2012. 2. 20.
반응형

안녕하세요 돼지왕 왕돼지입니다.
오늘은 안드로이드 4대 Component 중 하나인 컨텐트 프로바이더 ( Content Provider ) 에 대해 파헤쳐보고자 합니다.


ContentProvider 가 뭐하는 거야?

ContentProvider 는 Database를 정해진 Interface 로 외부 package 에 노출하는 방법입니다.
즉, 한 Application 에서 관리하는 Database 를 다른 Application 에서 사용할 수 있도록 하는 방법이죠.
Interface도 제공하기 때문에 외부 Application 에서 쉽게 사용할 수 있습니다. ( 물론 제한적인 부분도 있지요. )




URI

ContentProvider 에 접근하기 위해서는 URI 를 사용합니다.


<URI 형태>
format) content://authority/path/id
content:// : provider 접근임을 명시하는 것으로 반드시 들어가야 함.
authority : 접근하는 provider 를 명시하는 것으로, 다른 provider 들과 중복되면 안된다. ( 보통 package name 사용 )
path : 정보 종류 지정하는 가상의 경로
id : 구체적 정보
 

 


 

 


<URI 관련 APIs>

 

static Uri parse (String uriString)
// URI 객체 return, URI를 잘못 작성해도 예외를 발생시키지 않기 때문에 주의해야 한다.
 
List<String> getPathSegments()
// 0번째 요소가 path, 1번째 요소가 id. String은 '/' 가 제외한 형태임.

 

 
 
<URI Matcher APIs>
UriMatcher class
provider에 접근하는 URI의 종류가 많을 때, URI를 일일이 구분하고 비교하려면 힘들다. URI 의 문자열 정보를 분석하여 일치하는 경우 result로 미리 지정해놓은 정수 코드를 리턴하는 편리한 class 이다.

 

void addURI (String authority, String path, int code)
// URI를 map에 등록. path에서 * 는 임의의 문자열과 대응. #은 숫자 하나와 대응
 
int match (Uri uri)
// 등록된 메서드와 비교하여 등록된 정수 코드 리턴. 해당하는 uri가 없으면 -1 리턴

 

 
 
 
 
 
ContentProvider 만들기
 
CP를 만들려면 우선 ContentProvider 클래스를 상속받아야 한다. 이 곳에서는 정보를 관리, 제공하는 메서드들을 재정의( override )해야 한다.
 
String getType (Uri uri) : 제공하는 데이터의 MIME 타입 조사
단수 : vnd.회사명.cursor.item/타입
복수 : vnd.회사명.cursor.dir/타입
(강제는 아님)


<example>

 

public class Provider extends ContentProvider{
   static final Uri CONTENT_URI = Uri.parse("content://exam.Data.EnglishWord/word");
   static final int ALLWORD = 1;
   static final int ONEWORD = 2;

  // content://exam. Data.EnglishWord/word : 모든 레코드 리턴
  // content://exam.Data.EnglishWordc/word/boy : boy 레코드만 리턴 
  static final UriMatcher Matcher;
  static{
      Matcher = new UriMatcher(UriMatcher.NO_MATCH);
      Matcher.addURI("exam.Data.EnglishWord", "word", ALLWORD);
      Matcher.addURI("exam.Data.EnglishWord", "word/*", ONEWORD);
   }
 
SQLiteDatabase db;
public boolean onCreate(){
   WordDBHelper helper = new WordDBHelper(getContext());
   db = helper.getWritableDatabase();
   return true;
}
 
public String getType(Uri uri){
   if ( Matcher.match(uri) == ALLWORD ){
      return "vnd.EnglishWord.Data.cursor.item/word";
   }
 
   if (Matcher.match(uri) == ONEWORD){
      return "vnd.EnglishWord.Data.cursor.dir/words";
   }
   return null;
}
 
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder){
   String sql = "SELECT eng, han FROM dic";
 
   if (Matcher.match(uri) == ONEWORD){
      sql += " where eng = '" + uri.getPathSegments().get(1) + "'";
   }
 
   Cursor cursor = db.rawQuery(sql, null);
   return cursor;
}
 
public Uri insert (Uri uri, ContentValues values){
   long row = db.insert("dic", null, values);
   if (row > 0){
      Uri notiuri = ContentUris.withAppendedId(CONTENT_URI, row);
      getContext().getContentResolver().notifyChange(notiuri, null);
      return notiuri;
   }
   return null;
}
 
public int delete(Uri uti, String selection, String[] selectionArgs){
   int count = 0;
   switch (Matcher.match(Uri)){
   case ALLWORD:
      count = db.delete("dic", selection, selectionArgs);
      break;
   case ONEWORD:
      String where = "eng = '" + uri.getPathSegments().get(1) + "'";
      if (TextUtils.isEmpty(selection) == false){
         wehre += " AND" + selection;
      }
      count = db.deelte("dic", where, selectionArgs);
      break;
   }
   getContext().getContentResolver().notifyChange(uri, null);
   return count;
}
 
/* Same phrase but raw query
String sql = "DELETE FROM dic";
if (Matcher.match(uri) == ONEWORD){
   sql += " where eng = '" + uri.getpathSegments().get(1) + "'";
}
db.execSQL(sql);
return 1;
*/
 
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs){
   int count = 0;
   switch (Matcher.match(uri)){
   case ALLWORD:
      count = db.update("dic", values, selection, selectionArgs);
      break;
   case ONEWORD:
      String where = "eng = '" + uri.getPathSegments().get(1) + "'";
      if (TextUtils.isEmpty(selection) == false){
         where += " AND " + selection;
      }
      count = db.update("dic", values, where, selectionArgs);
      break;
   }
   getContext().getContentResolver().notifyChange(uri), null);
   return count;
}
 
} // end class
 

 


 

 

 
<ContentProvider 의 manifest 등록 example>
<provide android:name="provider" android:authorities="exam.Data.EnglishWord"/>
 




ContentProvider 사용하기.

<example>

 

static final String WORDURI = "content://exam.Data.EnglishWord/word";
ContentResolver cr = getContentResolver();
 
// Read all
Cursor cursor = cr.query(Uri.parse(WORDURI), null, null, null, null);
 
// Read one
Cursor cursor2 = cr.query(Uri.parse(WORDURI+"/boy"), null, null, null, null);
 
// Insert
ContentValues row = new ContentValues();
row.put("eng", "school");
row.put("han", "학교");
cr.insert(Uri.parse(WORDURI), row);
 
// Delete
cr.delete(Uri.parse(WORDURI), null, null);
 
// Update
ContentValues row2 = new ContentValues();
row2.put("han", "핵교");
cr.update(Uri.parse(WORDURI + "/school"), row2, null, null);

 

 
 


ContentResolver

ContentProvider를 사용하려면 우선 ContentResolver 객체 필요합니다.
 
ContentResolver ContextWrapper.getContentResolver();
  어떤 Content Provider와 통신할 것인가는 각 메서드로 전달되는 URI에 의해 결정됩니다.
  시스템은 URI로부터 ContentProvider를 찾아 프로바이더를 로드하고 프로바이더의 메서드를 호출합니다.
  Manifest의 authority 값을 비교 검색하는 것이죠.
 
 
<제공하는 Default APIs>

 

Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
 
Uri insert(Uti uri, Contentvalues values)
 
int bulkInsert(Uri uri, ContentValues[] values)
 
int delete(Uri uri, String where, String[] selectionArgs)
 
int update(Uri uri, ContentValues values, String where, String[] selectionArgs)

 



 


 

 



Summary

1. Data를 다루는 class를 하나 만들고 ContentProvider extend
 
2. URI를 기반으로( Matcher.match(uri) ) Data나 Cursor 등을 return 해주는 function을 override 해줌.
 
3. Manifest에 content provider에 대한 내용 등록.
 
4. Content resolver 객체 구하기.
 
5. Manifest에 등록된 authority 정보를 Uri로 하여 content resolver를 통하여 기능 수행

 

 

 

반응형

댓글