Archives
Recent Posts
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
Today
Total
관리 메뉴

안드로이드 개발자의 창고

[50일차 Android] Content Provider 본문

Computer/Android

[50일차 Android] Content Provider

Wise-99 2023. 7. 14. 18:28

 

 

 

출처 : 안드로이드 앱스쿨 2기 윤재성 강사님 수업 PPT

 

 

 

📖 Content Provider

  • 안드로이드 4대 구성 요소 중 하나로 애플리케이션이 저장한 데이터를 다른 애플리케이션이 사용할 수 있도록 제공하는 개념
  • 데이터를 제공하는 앱의 android:authorities를 알아야 사용할 수 있다.

 

 

 

예제 코드

데이터를 제공하는 앱 - AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application>
    
    ...
    
        <provider
            android:name=".MyContentProvider"
            android:authorities="com.test.dbprovider"
            android:enabled="true"
            android:exported="true"> </provider>
        
        ...
            
    </application>

</manifest>

 

 

 

데이터를 제공하는 앱 - DBHelper.kt

class DBHelper(context: Context) : SQLiteOpenHelper(context, "Test.db", null, 1){
    override fun onCreate(db: SQLiteDatabase?) {
        val sql = """
            create table TestTable(
                idx integer primary key autoincrement,
                textData text not null,
                intData integer not null,
                doubleData real not null,
                dateData date not null
            )
        """.trimIndent()

        db?.execSQL(sql)
    }

    override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
        TODO("Not yet implemented")
    }
}

 

 

 

데이터를 제공하는 앱 - MyContentProvider.kt

class MyContentProvider : ContentProvider() {

    lateinit var sqliteDatabase: SQLiteDatabase

    // delete
    // 두번째 매개변수 : 조건절
    // 세번째 매개변수 : 조건절의 ?에 설정될 값
    override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int {
        val cnt = sqliteDatabase.delete("TestTable", selection, selectionArgs)
        return cnt
    }

    // 컬럼의 데이터 타입을 MINE 타입 형태로 문자열을 만들어 반환하는 메서드
    // 알려줄 필요가 없다면 null을 반환
    override fun getType(uri: Uri): String? {
        return null
    }

    // insert
    // 두번째 매개변수 : 저장할 데이터의 칼럼 이름과 값이 담긴 객체
    override fun insert(uri: Uri, values: ContentValues?): Uri? {
        // 저장한다.
        sqliteDatabase.insert("TestTable", null, values)

        return uri
    }

    // Content Provider 객체가 생성되면 자동으로 호출되는 메서드
    // 데이터 베이스에 접근할 수 있는 객체를 생성하고 접속에 성공하면 true, 실패하면 false를 반환하도록 구현해준다.
    override fun onCreate(): Boolean {
        val dbHelper = DBHelper(context!!)
        sqliteDatabase = dbHelper.writableDatabase

        if(sqliteDatabase == null){
            return false
        }

        return true
    }

    // select
    // 두번째 매개변수 : 가져올 컬럼 목록
    // 세번째 매개변수 : 조건절
    // 네번째 매개변수 : 조건절 ?에 설정될 값
    // 다섯번째 매개변수 : 정렬 기준
    override fun query(
        uri: Uri, projection: Array<String>?, selection: String?,
        selectionArgs: Array<String>?, sortOrder: String?
    ): Cursor? {
        val cursor = sqliteDatabase.query("TestTable", projection, selection, selectionArgs, null, null, sortOrder)

        return cursor
    }

    // 두번째 매개변수 : 변경할 컬럼의 이름과 값이 있는 ContentValues 객체
    // 세번째 매개변수 : 조건절
    // 네번째 매개변수 : 조건절의 ?에 설정될 값들의 배열
    override fun update(
        uri: Uri, values: ContentValues?, selection: String?,
        selectionArgs: Array<String>?
    ): Int {
        val cnt = sqliteDatabase.update("TestTable", values, selection, selectionArgs)
        return cnt
    }
}

 

 

 

데이터를 제공하는 앱 - MainActivity.kt

class MainActivity : AppCompatActivity() {

    lateinit var activityMainBinding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(activityMainBinding.root)

        activityMainBinding.run{
            buttonSelectData.setOnClickListener{
                val sql = "select * from TestTable"

                val dbHelper = DBHelper(this@MainActivity)

                val cursor = dbHelper.writableDatabase.rawQuery(sql, null)

                textViewResult.text = ""

                // 테이블의 행이 있을 때까지 반복
                while(cursor.moveToNext()){
                    // 문자열에 해당하는 컬럼의 인덱스
                    val idx1 = cursor.getColumnIndex("idx")
                    val idx2 = cursor.getColumnIndex("textData")
                    val idx3 = cursor.getColumnIndex("intData")
                    val idx4 = cursor.getColumnIndex("doubleData")
                    val idx5 = cursor.getColumnIndex("dateData")

                    // 인덱스를 통해 데이터 추출
                    val idx = cursor.getInt(idx1)
                    val textData = cursor.getString(idx2)
                    val intData = cursor.getInt(idx3)
                    val doubleData = cursor.getDouble(idx4)
                    val dateData = cursor.getString(idx5)

                    textViewResult.append("idx : ${idx}\n")
                    textViewResult.append("textData : ${textData}\n")
                    textViewResult.append("intData : ${intData}\n")
                    textViewResult.append("doubleData : ${doubleData}\n")
                    textViewResult.append("dateData : ${dateData}\n\n")
                }

                dbHelper.close()
            }
        }
    }
}

 

 

 

데이터를 사용하는 앱 - AndroidManifest.xml

    ...
    
    </application>
    
    <!-- 다른 애플리케이션이 가지고 있는 Content Provider를 사용하기 위한 권한 -->
    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
        tools:ignore="QueryAllPackagesPermission"/>
        
</manifest>

 

 

 

데이터를 사용하는 앱 - MainActivity.kt

class MainActivity : AppCompatActivity() {

    lateinit var activityMainBinding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(activityMainBinding.root)

        activityMainBinding.run {
        
            buttonInsertData.run {
                setOnClickListener {
                    // 현재 날짜를 문자열로 생성
                    val sdf = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
                    val now = sdf.format(Date())

                    // 저장할 데이터를 ContentValues에 담아 준다.
                    val cv1 = ContentValues()
                    cv1.put("textData", "문자열1")
                    cv1.put("intData", 100)
                    cv1.put("doubleData", 11.11)
                    cv1.put("dateData", now)

                    val cv2 = ContentValues()
                    cv2.put("textData", "문자열2")
                    cv2.put("intData", 200)
                    cv2.put("doubleData", 22.22)
                    cv2.put("dateData", now)

                    // Content Provider의 이름을 가지고 있는 Uri 객체를 생성한다.
                    val uri = Uri.parse("content://com.test.dbprovider")

                    // Content Provider를 이용할 수 있는 객체를 통해 사용한다.
                    contentResolver.insert(uri, cv1)
                    contentResolver.insert(uri, cv2)

                    textViewResult.text = "저장 완료"
                }

                buttonSelectData.run {
                    setOnClickListener {
                        val uri = Uri.parse("content://com.test.dbprovider")
                        // Content Provider를 통해서 데이터를 가져온다.

                        // 두번째 : 가져올 컬럼 목록. null을 설정하면 모든 컬럼
                        // 세번째 : 조건절
                        // 네번째 : 조건절의 ?에 설정된 값 배열
                        // 다섯번째 : 정렬 기준 컬럼 목록
                        val cursor = contentResolver.query(uri, null, null, null, null)

                        textViewResult.text = ""

                        // 읽어올 행이 없을 때까지 반복
                        while(cursor?.moveToNext()!!){
                            val idx1 = cursor?.getColumnIndex("idx")
                            val idx2 = cursor?.getColumnIndex("textData")
                            val idx3 = cursor?.getColumnIndex("intData")
                            val idx4 = cursor?.getColumnIndex("doubleData")
                            val idx5 = cursor?.getColumnIndex("dateData")

                            val idx = cursor?.getInt(idx1!!)
                            val textData = cursor?.getString(idx2!!)
                            val intData = cursor?.getInt(idx3!!)
                            val doubleData = cursor?.getDouble(idx4!!)
                            val dateData = cursor?.getString(idx5!!)

                            textViewResult.append("idx : ${idx}\n")
                            textViewResult.append("textData : ${textData}\n")
                            textViewResult.append("intData : ${intData}\n")
                            textViewResult.append("doubleData : ${doubleData}\n")
                            textViewResult.append("dateData : ${dateData}\n\n")
                        }
                    }
                }

                buttonUpdateData.run {
                    setOnClickListener {
                        val cv1 = ContentValues()
                        cv1.put("textData", "새로운 문자열")

                        val where = "idx = ?"
                        val args = arrayOf("1")

                        val uri = Uri.parse("content://com.test.dbprovider")

                        // 수정한다.
                        contentResolver.update(uri, cv1, where, args)

                        textViewResult.text = "수정 완료"
                    }
                }

                buttonDeleteData.run {
                    setOnClickListener {
                        val where = "idx = ?"
                        val args = arrayOf("1")

                        val uri = Uri.parse("content://com.test.dbprovider")

                        contentResolver.delete(uri, where, args)

                        textViewResult.text = "삭제 완료"
                    }
                }
            }
        }
    }
}

'Computer > Android' 카테고리의 다른 글

[50일차 Android] Preferences Screen  (0) 2023.07.17
[50일차 Android] Preferences  (0) 2023.07.17
[44일차 Android] SQLiteDatabase  (0) 2023.07.10
[44일차 Android] assets  (0) 2023.07.10
[44일차 Android] Raw  (0) 2023.07.10