6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Kotlinで画像をデータベースに保存したい

Last updated at Posted at 2020-02-21

#目的
Kotlinでデータベース接続をし、画像の追加、削除までを実装する。

#環境
Android Studio 3.5.2
Build #AI-191.8026.42.35.5977832, built on October 31, 2019
JRE: 1.8.0_202-release-1483-b03 amd64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
Windows 10 10.0

##KotlinでのDB接続の手順
適当なクラス名でKotlinファイルを作成します。
###まずは定義を記述

DbHelper.kt
//テーブル定義
object PhotoTable : BaseColumns {
    const val TABLE_NAME = "photo"
    const val COLUMN_NAME_BITMAP = "bitmap"
}

//テーブル作成のSQL
private const val SQL_CREATE_PHOTO = "CREATE TABLE ${PhotoTable.TABLE_NAME}" +
        " (${BaseColumns._ID} INTEGER PRIMARY KEY," +
        " ${PhotoTable.COLUMN_NAME_BITMAP} BLOB NOT NULL)"
//テーブル削除のSQL
private const val SQL_DELETE_PHOTO = "DROP TABLE IF EXISTS ${PhotoTable.TABLE_NAME}"

private const val DATABASE_VERSION = 1
private const val DATABASE_NAME = "Practice.db"

画像はバイナリーデータとして保存するので型はBLOBになります。
###SQLiteOpenHelperクラスを継承

DbHelper.kt
class DbHelper(context: Context): SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) {
    override fun onCreate(db: SQLiteDatabase) {
        db.execSQL(SQL_CREATE_PHOTO)
    }
    override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
        db.execSQL(SQL_DELETE_PHOTO)
        onCreate(db)
    }
}

今回は最低限オーバーライドする必要があるCreateとUpgradeのみです。
##UI
viewを配置.PNG

  1. 画像表示用ImageView(id:imageView)
  2. 画像追加ボタン(id:addPhotoButton)
  3. 画像削除ボタン(id:deletePhotoButton)

##レコ―ドの追加
###画像追加ボタンのクリック処理

MainActivity.kt
addPhotoButton.setOnClickListener{
    val intent = Intent(Intent.ACTION_OPEN_DOCUMENT) 
    intent.addCategory(Intent.CATEGORY_OPENABLE)
    intent.type = "image/*"

    startActivityForResult(Intent.createChooser(intent,"写真を選択"),CHOOSE_PHOTO)
}

画像を選択するActivityを起動します。
###画像選択後の処理

MainActivity.kt
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)

    if(requestCode == CHOOSE_PHOTO
        && resultCode == Activity.RESULT_OK
        && data != null){

        //選択した画像のUriからBitmapを取得
        val bitmap = getBitmapFromUri(data.data)
        bitmap?:return

        //画像表示用のImageViewに表示させときます
        imageView.setImageBitmap(bitmap)

        //Bitmapをバイナリーに変換してDBに登録します
        val values = getContentValues(getBinaryFromBitmap(bitmap))
        val db = dbHelper.writableDatabase
        photoId = db.insert(PhotoTable.TABLE_NAME, null, values) //レコード追加
        db.close()

        Toast.makeText(this,"登録しました",Toast.LENGTH_LONG).show()
    }
}

//Bitmapを取得
//@param 画像Uri
//@return Bitmap
private fun getBitmapFromUri(uri: Uri?): Bitmap? {
    uri?:return null

    val parcelFileDescriptor: ParcelFileDescriptor? =
        this.contentResolver.openFileDescriptor(uri, "r")
    parcelFileDescriptor?:return null

    val fileDescriptor: FileDescriptor = parcelFileDescriptor.fileDescriptor
    val image: Bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor)
    parcelFileDescriptor.close()
    return image
}

//Binaryを取得
//@param Bitmap
//@return Binary
private fun getBinaryFromBitmap(bitmap:Bitmap):ByteArray{
    val byteArrayOutputStream = ByteArrayOutputStream()
    bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream)
    return byteArrayOutputStream.toByteArray()
}

//値セットを取得
//@param URI
//@return 値セット
private fun getContentValues(binary:ByteArray): ContentValues {
    return ContentValues().apply {
        put("${PhotoTable.COLUMN_NAME_BITMAP}",binary)
    }
}

レコードの追加は以上です。

##レコードの削除
###画像削除ボタンのクリック処理

MainActivity.kt
deletePhotoButton.setOnClickListener{
    val db = dbHelper.writableDatabase
    db.delete(PhotoTable.TABLE_NAME,"_ID = $photoId",null) //レコード削除
    db.close()

    //画像表示用ImageViewを元のに戻してます
    imageView.setImageResource(R.drawable.art)

    Toast.makeText(this,"削除しました",Toast.LENGTH_LONG).show()
}

レコードの削除は以上です。

#まとめ

  1. SQLiteOpenHelperを理解する
    https://developer.android.com/reference/kotlin/android/database/sqlite/SQLiteOpenHelper
  2. 画像をバイナリーに変換する
     ちなみに、バイナリーをBitmapに変換する際は
val binary = //DBから取得したBinary
val bitmap = BitmapFactory.decodeByteArray(binary,0,binary.size)

で、取得できます。
##参考にしたサイトとソースコード
参考サイト
https://developer.android.com/training/data-storage/sqlite?hl=ja

ソースコード
https://github.com/date62noka3/database-kotlin

#最後に
補足という形で新たに記事を投稿しました。
合わせてお読みください。
https://qiita.com/date62noka3/items/573dbf84b41013ed9812

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?