[안드로이드] 07. ContentProvider
ContentProvider
ContentProvider
동작 원리
ContentResolver에서 아래 메소드들 중 하나를 호출하면 ,
ContentResolver가 ContentProvider에게 해당 기능을 수행하라고 알려줌
query(): 데이터 읽기
1 2 3 4 5
public final @Nullable Cursor query(@RequirePermission.Read @NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder){ return query(uri, projection, selection, selectionArgs, sortOrder) }
- insert(): 데이터에 행 추가
- update(): 데이터 갱신
- delete(): 데이터로부터 행 삭제
주소록 가져오기
Intent로 다른 앱 호출
1 2 3 4 5 6 7 8 9
// 연락처 등록 binding.button2.setOnClickListener{ val intent = Intent().apply{ action= Intent.ACTION_INSERT data= Uri.parse("content://com.android.contacts/contacts") } startActivity(intent) }
URI Query로 접근
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
private fun init() { val textview = findViewById<TextView>(R.id.textview) val URI = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, "1".toLong()) val cursor= contentResolver.query(contactsURI, arrayOf<String>("_id", "display_name"), null, null, null) cursor.use{ it?.let{ while(it.moveToNext()){ for (i in 0..it.columnCount-1){ Log.d(TAG, "index: $i, name: ${it.getColumnName(i)}, value: ${it.getString(i)}") } } } } }
Adapter +
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
val adapter1 = CursorAdapter( this, R.layout.item_list, cursor!!, from, to, FLAG_REGISTER_CONTENT_OBSERVER ) listview.adapter = adapter1 ... } inner class CursorAdapter( context: Context, layout:Int, cursor:Cursor, from:Array<String>, to:IntArray, flag:Int ) : CursorAdapter(context, layout, cursor, from, to, flag){ override fun onContentChanged() { super.onContentChanged() Log.d(TAG, "onContentChanged: ") val newCursor = contentResolver.query(URI, null, null, null, null) changeCursor(newCursor) } }
ContentResolver로 갤러리에 접근하기
구현 과정
AndroidManifest에 권한 설정
1 2 3 4
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
권한 설정 추가: checkPermission()
퍼미션 획득 성공일 때: (SELECT _id, title, data taken FROM images ORDER BY datataken DESC LIMIT 2)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
getImage()?.use { cursor -> ... } } private fun getImage(): Cursor? { val resolver = contentResolver var queryUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI val what = arrayOf( MediaStore.Images.ImageColumns._ID, MediaStore.Images.ImageColumns.TITLE, MediaStore.Images.ImageColumns.DATE_TAKEN ) ... return resolver.query(queryUri, what, bundle, null, orderBy) // android 버전에 따라 정렬 & 건수 제한 (위의 경우는 이전 버전) }
권한 없으면 창 띄우기: checker.requestPermissionLauncher.launch(runtimePermissions)
ContentResolver로 미디어에 접근하기
구현 과정
AndroidManifest에 권한 설정
1
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
권한 설정 추가: checkPermission()
퍼미션 획득 성공일 때
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
getAudio()?.use { cursor -> ... } } private fun getAudio(): Cursor { val resolver = contentResolver val queryUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI val sortOrder = MediaStore.Audio.Media.TITLE + " ASC"; val what = arrayOf( MediaStore.Audio.Media._ID, MediaStore.Audio.Media.ALBUM_ID, MediaStore.Audio.Media.TITLE, MediaStore.Audio.Media.ARTIST, ) return resolver.query(queryUri, what, null, null, sortOrder)!! }
권한 없으면 창 띄우기: checker.requestPermissionLauncher.launch(runtimePermissions)
adapter 구성
1 2 3 4 5
val musicAdapter = MusicAdapter(musicList) findViewById<RecyclerView>(R.id.recyle_view).apply{ adapter = musicAdapter this.layoutManager = LinearLayoutManager(this@MediaActivity) }
같은 프로젝트에서 ContentProvider, ContentResolver 호출
- ContentProvider 작성
- AndroidManifest.xml에 등록
- 필수 메소드 구현
- query()
- insert()
- update()
- delete()
- getType()
- onCreate()
ContentResolver 작성
1 2 3 4 5 6 7 8 9 10 11 12
private fun saveState() { val values = ContentValues() values.put(Notes.TITLE, mTitleText.text.toString()) values.put(Notes.BODY, mBodyText.text.toString()) if (mRowId == -1L) { contentResolver.insert(Notes.CONTENT_URI, values)!! } else { val uri = ContentUris.withAppendedId(Notes.CONTENT_URI, mRowId) contentResolver.update(uri, values, null, null) } }
ContentProvider와 ContentResolver를 분리해서 호출
Provider의 AndroidManifest.xml
NotesDbHelper는 Provider 쪽에만 존재
1 2 3
<provider android:name=".NotesDbHelper" android:authorities="com.android.contentprovider.note" android:exported="true"/>
Resolver의 AndroidManifest.xml
1 2 3
<queries> <provider android:authorities="com.android.contentprovider.note" /> </queries>
This post is licensed under CC BY 4.0 by the author.