[kotlin] 안드로이드 Content Provider

Leechaeyeon·2023년 7월 13일
0

코틀린 안드로이드

목록 보기
11/21

Content Provider

  • 안드로이드 4대 구성 요소 중 하나로 애플리케이션이 저장한 데이터를 다른 애플리케이션이 사용할 수 있도록 제공하는 개념이다.
  • 같은 어플리케이션 내부에 요소에서는 SQlite에 있는 데이터를 자유롭게 사용가능하지만 다른 애플리케이션이 사용할 수 있게 제공하고 싶다면, 직접 접근이 아닌 다른 접근으로 해야한다.
    => content provider에게 외부에 접근할 수 있도록 이름을 정의해주면 안드로이드 OS를 통해서 접근이 가능하다.

안드로이드 11 버전 부터 변경 점

  • 안드로이드 11 부터 다른 애플리케이션의 요소를 사용할 때는 **AndroidManifest.xml**에 명시해야 한다.
<queries>
    <provider android:authorities="kr.co.softcampus.dbprovider" />
</queries>

사용방법

Android_ContentProviderApp1

build.gradle에 설정

    viewBinding{
        enabled = true
    }

main_activty.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <Button
        android:id="@+id/ButtonSelectData"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="select" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <TextView
                android:id="@+id/textViewResult"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="textView" />
        </LinearLayout>
    </ScrollView>
</LinearLayout>

DataBase 설정

DBHelper.kt

import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper



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")
    }
}

mainActivity.kt

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.test.android75_contentproviderapp1.databinding.ActivityMainBinding

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.run{
                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()
            }
        }
    }
}

content provider


URI Authorities를 안붙이면 만들 수가 없음
-> content provider의 목적이 다른 어플리케이션에서 쓰라고 존재하는 것이기 때문에 꼭 설정을 해야지만 만들 수 있음

MyContentProvider.kt

 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
    }

    // 칼럼의 데이터 타입을 MIME 타입 형태로 문자열을 만들어 반환하는 메서드
    // 알려줄 필요가 없다면 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

        // 접속에 실패하면 false를 반환한다
        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
    }

App2

package com.test.android75_contentproviderapp2

import android.content.ContentValues
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.test.android75_contentproviderapp2.databinding.ActivityMainBinding
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

class MainActivity : AppCompatActivity() {

    lateinit var activityMainBinding: ActivityMainBinding

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

        activityMainBinding = ActivityMainBinding.inflate(layoutInflater)

        activityMainBinding.run {

            button.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)

                    textView.text = "저장 완료"
                }
            }
            button2.setOnClickListener {
                val uri = Uri.parse("content://com.test.dbprovider")
                // Content Provider를 통해서 데이터를 가져온다.

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

                textView.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!!)

                    textView.append("idx : ${idx}\n")
                    textView.append("textData : ${textData}\n")
                    textView.append("intData : ${intData}\n")
                    textView.append("doubleData : ${doubleData}\n")
                    textView.append("dateData : ${dateData}\n\n")
                }
            }
            button3.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)

                textView.text = "수정 완료"
            }
            button4.run{
                setOnClickListener {

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

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

                    contentResolver.delete(uri, where, args)

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


        }
        setContentView(activityMainBinding.root)
    }
}

0개의 댓글

관련 채용 정보