안드로이드 개발자의 창고
[50일차 Android] Content Provider 본문
출처 : 안드로이드 앱스쿨 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 |