Android

Android Contents Provider 활용

임베디드 친구 2024. 11. 20. 13:03
반응형

이번 포스팅에서는 Android 애플리케이션에서 Contents Provider를 만들어서 활용하는 방법에 대해 알아보겠습니다. Contents Provider는 애플리케이션 간에 데이터를 공유할 수 있도록 돕는 중요한 구성 요소 중 하나입니다. 이 글에서는 간단한 Contacts 정보 저장소를 구현해보고, 이를 애플리케이션에서 활용하는 과정을 Kotlin 예제와 함께 설명합니다.

Contents Provider란?

Contents Provider는 Android의 주요 데이터 저장 메커니즘 중 하나로, 애플리케이션 간에 데이터를 안전하게 공유할 수 있게 해주는 기능입니다. 예를 들어, 기본 연락처 애플리케이션에서 연락처 정보를 다른 애플리케이션에서도 사용할 수 있게 하는 방식이 그 예입니다. Contents Provider를 통해 데이터베이스, 파일 시스템 등의 저장소에 있는 데이터를 다른 애플리케이션에서 사용할 수 있습니다.

Contents Provider를 사용하려면 데이터에 접근하기 위한 URI를 정의하고, 이를 통해 데이터를 조회, 삽입, 삭제, 수정할 수 있는 기능을 제공합니다.

Contents Provider 구현하기

이번 예제에서는 간단한 연락처 정보를 저장하고 제공하는 ContactsProvider를 만들어 보겠습니다. 이를 통해 Content Provider의 기본 기능을 이해할 수 있을 것입니다.

1. Content Provider 생성

먼저 새로운 클래스를 생성하여 ContactsProvider를 구현합니다. 이 클래스는 ContentProvider를 상속받고, 필요한 메서드를 오버라이드하여 기능을 정의합니다.

package com.example.mycontacts

import android.content.ContentProvider
import android.content.ContentUris
import android.content.ContentValues
import android.content.UriMatcher
import android.database.Cursor
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import android.net.Uri
import android.util.Log

class ContactsProvider : ContentProvider() {

    companion object {
        const val AUTHORITY = "com.example.mycontacts.provider"
        val CONTENT_URI: Uri = Uri.parse("content://$AUTHORITY/contacts")
        private const val CONTACTS = 1
        private const val CONTACT_ID = 2
        private val uriMatcher = UriMatcher(UriMatcher.NO_MATCH).apply {
            addURI(AUTHORITY, "contacts", CONTACTS)
            addURI(AUTHORITY, "contacts/#", CONTACT_ID)
        }
    }

    private lateinit var dbHelper: DatabaseHelper

    override fun onCreate(): Boolean {
        dbHelper = DatabaseHelper(context!!)
        return true
    }

    override fun query(
        uri: Uri,
        projection: Array<out String>?,
        selection: String?,
        selectionArgs: Array<out String>?,
        sortOrder: String?
    ): Cursor? {
        val db = dbHelper.readableDatabase
        return when (uriMatcher.match(uri)) {
            CONTACTS -> db.query("contacts", projection, selection, selectionArgs, null, null, sortOrder)
            CONTACT_ID -> {
                val id = ContentUris.parseId(uri)
                db.query("contacts", projection, "_id=?", arrayOf(id.toString()), null, null, sortOrder)
            }
            else -> throw IllegalArgumentException("Unknown URI: $uri")
        }
    }

    override fun insert(uri: Uri, values: ContentValues?): Uri? {
        val db = dbHelper.writableDatabase
        val id = db.insert("contacts", null, values)
        if (id > 0) {
            val insertedUri = ContentUris.withAppendedId(CONTENT_URI, id)
            context?.contentResolver?.notifyChange(insertedUri, null)
            return insertedUri
        }
        throw IllegalArgumentException("Failed to insert row into $uri")
    }

    override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int {
        val db = dbHelper.writableDatabase
        val count = when (uriMatcher.match(uri)) {
            CONTACTS -> db.delete("contacts", selection, selectionArgs)
            CONTACT_ID -> {
                val id = ContentUris.parseId(uri)
                db.delete("contacts", "_id=?", arrayOf(id.toString()))
            }
            else -> throw IllegalArgumentException("Unknown URI: $uri")
        }
        context?.contentResolver?.notifyChange(uri, null)
        return count
    }

    override fun update(
        uri: Uri,
        values: ContentValues?,
        selection: String?,
        selectionArgs: Array<out String>?
    ): Int {
        val db = dbHelper.writableDatabase
        val count = when (uriMatcher.match(uri)) {
            CONTACTS -> db.update("contacts", values, selection, selectionArgs)
            CONTACT_ID -> {
                val id = ContentUris.parseId(uri)
                db.update("contacts", values, "_id=?", arrayOf(id.toString()))
            }
            else -> throw IllegalArgumentException("Unknown URI: $uri")
        }
        context?.contentResolver?.notifyChange(uri, null)
        return count
    }

    override fun getType(uri: Uri): String? {
        return when (uriMatcher.match(uri)) {
            CONTACTS -> "vnd.android.cursor.dir/vnd.$AUTHORITY.contacts"
            CONTACT_ID -> "vnd.android.cursor.item/vnd.$AUTHORITY.contacts"
            else -> throw IllegalArgumentException("Unknown URI: $uri")
        }
    }

    private class DatabaseHelper(context: android.content.Context) : SQLiteOpenHelper(context, "contacts.db", null, 1) {
        override fun onCreate(db: SQLiteDatabase) {
            db.execSQL("CREATE TABLE contacts (_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, phone TEXT NOT NULL);")
        }

        override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
            db.execSQL("DROP TABLE IF EXISTS contacts")
            onCreate(db)
        }
    }
}

위 코드는 ContactsProvider를 구현한 것으로, 간단한 연락처 정보를 저장, 조회, 수정, 삭제할 수 있는 기능을 제공합니다. DatabaseHelper 클래스는 SQLite 데이터베이스를 생성하고 관리합니다.

2. Manifest 파일 설정

Contents Provider를 사용하려면 AndroidManifest.xml 파일에 이를 등록해야 합니다. 아래와 같이 <provider> 태그를 추가합니다.

<provider
    android:name=".ContactsProvider"
    android:authorities="com.example.mycontacts.provider"
    android:exported="true" />

3. Content Provider 활용하기

Content Provider를 사용해 데이터를 삽입하거나 조회하는 방법을 알아보겠습니다. 다른 애플리케이션이나 같은 애플리케이션의 다른 Activity에서 ContentResolver를 사용해 접근할 수 있습니다.

데이터 삽입

다음은 ContactsProvider에 새 연락처를 삽입하는 코드입니다.

val values = ContentValues().apply {
    put("name", "John Doe")
    put("phone", "123-456-7890")
}

val newContactUri = contentResolver.insert(ContactsProvider.CONTENT_URI, values)

데이터 조회

다음은 ContactsProvider에서 모든 연락처를 조회하는 코드입니다.

val cursor = contentResolver.query(ContactsProvider.CONTENT_URI, null, null, null, null)
cursor?.use {
    while (it.moveToNext()) {
        val name = it.getString(it.getColumnIndexOrThrow("name"))
        val phone = it.getString(it.getColumnIndexOrThrow("phone"))
        Log.d("ContactsProvider", "Contact: $name, Phone: $phone")
    }
}

위 코드에서는 ContentResolver를 사용해 Content Provider에 접근하고 데이터를 가져오는 방법을 보여줍니다.

마무리

이번 포스팅에서는 Contents Provider를 구현하고 이를 활용하는 방법에 대해 알아보았습니다. Contents Provider는 애플리케이션 간에 데이터를 안전하게 공유할 수 있는 강력한 도구입니다. 이를 잘 활용하면 데이터 관리와 공유를 효율적으로 할 수 있습니다.

예제 코드와 설명을 통해 Contents Provider의 기본적인 동작 원리와 구현 방법을 이해하셨길 바랍니다.

반응형