从数据库中获取照片并在列表视图中显示

Posted

技术标签:

【中文标题】从数据库中获取照片并在列表视图中显示【英文标题】:Get photo from database and show it in list view 【发布时间】:2018-12-04 05:37:48 【问题描述】:

我正在使用 Kotlin 在 android studio 中开发 Note App。该应用程序有一个带有列表视图和浮动操作按钮的 Main Activity 和一个带有标题编辑文本、注释编辑文本、插入图片按钮、保存按钮和图像视图的 Add Note Activity。

当您触摸浮动按钮时,它会将您带到 App Note Activity。在那里,您可以写笔记、插入图片并在图像视图中查看,最后将它们保存在 SQLite 数据库中。当您返回主活动时,它应该在列表视图中显示标题及其图片。 最后一部分是我的问题!应用程序没有创建列表视图,而是崩溃了。

Android 清单:

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

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.CAMERA"></uses-permission>

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity android:name=".AddNoteActivity"></activity>
</application>
</manifest>

添加笔记活动:

class AddNoteActivity : AppCompatActivity() 

private val GALLERY = 1
private val CAMERA = 2
var path = myPath()

override fun onCreate(savedInstanceState: Bundle?) 
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_add_note)

    buttonAddPic.setOnClickListener 
        if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) 
            val array = Array<String>(1)  Manifest.permission.WRITE_EXTERNAL_STORAGE 
            ActivityCompat.requestPermissions(this, array, 1)
        
        if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) 
            val array = Array<String>(1)  Manifest.permission.READ_EXTERNAL_STORAGE 
            ActivityCompat.requestPermissions(this, array, 1)
        
        if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED) 
            val array = Array<String>(1)  Manifest.permission.CAMERA 
            ActivityCompat.requestPermissions(this, array, 1)
         else
            showPictureDialog()

    

    buttonSave.setOnClickListener 
        var dbManager = DBManager(this)

        var values = ContentValues()
        values.put("Title",editTextTitle.text.toString())
        values.put("Note", editTextNote.text.toString())

        val fis = FileInputStream(path.picPath)
        val image = ByteArray(fis.available())
        fis.read(image)

        values.put("Pic", image)

        val ID = dbManager.insert(values)

        fis.close()

        if (ID > 0)
        
            Toast.makeText(this,"Note was saved!",Toast.LENGTH_SHORT).show()
        
        else
            Toast.makeText(this,"Error",Toast.LENGTH_SHORT).show()

        finish()

    


override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) 
    if (requestCode == 1) 
        if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) 
            showPictureDialog()
        
    


private fun showPictureDialog() 
    val pictureDialog = AlertDialog.Builder(this)
    pictureDialog.setTitle("")
    val pictureDialogItems = arrayOf("Select photo from gallery", "Take photo with camera")
    pictureDialog.setItems(pictureDialogItems
    )  dialog, which ->
        when (which) 
            0 -> choosePhotoFromGallary()
            1 -> takePhotoFromCamera()
        
    
    pictureDialog.show()


fun choosePhotoFromGallary() 
    val galleryIntent = Intent(Intent.ACTION_PICK,
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI)

    startActivityForResult(galleryIntent, GALLERY)


private fun takePhotoFromCamera() 
    val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
    startActivityForResult(intent, CAMERA)


public override fun onActivityResult(requestCode:Int, resultCode:Int, data: Intent?) 

    super.onActivityResult(requestCode, resultCode, data)

    if (requestCode == GALLERY)
    
        if (data != null)
        
            val contentURI = data!!.data
            try
            
                val bitmap = MediaStore.Images.Media.getBitmap(this.contentResolver, contentURI)
                val path = saveImage(bitmap)
                Toast.makeText(this, "Photo was saved!", Toast.LENGTH_SHORT).show()
                imageViewShowPic!!.setImageBitmap(bitmap)

            
            catch (e: IOException) 
                e.printStackTrace()
                Toast.makeText(this, "Error!", Toast.LENGTH_SHORT).show()
            

        

    
    else if (requestCode == CAMERA)
    
        val thumbnail = data!!.extras!!.get("data") as Bitmap
        imageViewShowPic!!.setImageBitmap(thumbnail)
        saveImage(thumbnail)
        Toast.makeText(this, "Photo was saved!", Toast.LENGTH_SHORT).show()
    


fun saveImage(myBitmap: Bitmap):String 
    val bytes = ByteArrayOutputStream()
    myBitmap.compress(Bitmap.CompressFormat.JPEG, 90, bytes)
    val wallpaperDirectory = File(
            (Environment.getExternalStorageDirectory()).toString() + IMAGE_DIRECTORY)

    Log.d("fee",wallpaperDirectory.toString())
    if (!wallpaperDirectory.exists())
    

        wallpaperDirectory.mkdirs()
    

    try
    
        Log.d("heel",wallpaperDirectory.toString())
        val f = File(wallpaperDirectory, ((Calendar.getInstance()
                .getTimeInMillis()).toString() + ".jpg"))
        f.createNewFile()
        val fo = FileOutputStream(f)
        fo.write(bytes.toByteArray())
        MediaScannerConnection.scanFile(this,
                arrayOf(f.getPath()),
                arrayOf("image/jpeg"), null)
        fo.close()
        Log.d("TAG", "File Saved::--->" + f.getAbsolutePath())

        path.picPath=f.absolutePath

        return f.getAbsolutePath()

    
    catch (e1: IOException) 
        e1.printStackTrace()
    

    return ""


companion object 
    private val IMAGE_DIRECTORY = "/demonuts"

类 myPath:

class myPath 
var picPath:String? = null

SQLite 数据库:

class DBManager 

val dbName = "NotesDB"
val dbTable = "tblNotes"
val colID = "ID"
val colTitle = "Title"
val colNote = "Note"
val colPic = "Pic"
val dbVersion = 1

val sqlCreateTable = "CREATE TABLE IF NOT EXISTS " + dbTable + " " +
        "(" + colID + " INTEGER PRIMARY KEY, " + colTitle + " TEXT, " + colNote + " TEXT, " + colPic + " BLOB);"

var sqlDB: SQLiteDatabase? = null

constructor(context: Context)

    val db = DatabaseHelper(context)
    sqlDB = db.writableDatabase


inner class DatabaseHelper : SQLiteOpenHelper

    var context: Context? = null

    constructor(context: Context): super(context, dbName, null, dbVersion)
    
        this.context = context
    

    override fun onCreate(db: SQLiteDatabase?) 

        db!!.execSQL(sqlCreateTable)

    

    override fun onUpgrade(db: SQLiteDatabase?, p1: Int, p2: Int) 

        db!!.execSQL("DROP TABLE IF EXISTS " + dbTable)

    



fun insert (values: ContentValues) : Long

    val ID = sqlDB!!.insert(dbTable,"",values)
    return ID


fun RunQuery(columns:Array<String>, selection: String, selectionArgs:Array<String>, sortOrder: String): Cursor

    val qb = SQLiteQueryBuilder()
    qb.tables = dbTable
    val cursor = qb.query(sqlDB, columns, selection, selectionArgs, null, null, sortOrder)
    return cursor

主要活动:

class MainActivity : AppCompatActivity() 

var listOfNotes = ArrayList<Note>()

override fun onResume() 
    LoadData("%")
    super.onResume()


override fun onCreate(savedInstanceState: Bundle?) 
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    LoadData("%")

    floatingActionButton.setOnClickListener 
        var intent = Intent(this,AddNoteActivity::class.java)
        startActivity(intent)
    



fun LoadData(title:String)

    var dbManager = DBManager(this)

    val columns = arrayOf("ID", "Title", "Note", "Pic")
    val selectionArgs = arrayOf(title)

    val cursor = dbManager.RunQuery(columns,"Title like ?", selectionArgs,"Title")

    listOfNotes.clear()

    if (cursor.moveToFirst() == true)
    
        do
        
            val ID = cursor.getInt(cursor.getColumnIndex("ID"))
            val Title = cursor.getString(cursor.getColumnIndex("Title"))
            val Note = cursor.getString(cursor.getColumnIndex("Note"))
            val Pic = cursor.getBlob(cursor.getColumnIndex("Pic"))
            val BMP = BitmapFactory.decodeByteArray(Pic,cursor.getColumnIndex("Pic"),Pic!!.size)

            listOfNotes.add(Note(ID,Title,Note,BMP))

        
        while (cursor.moveToNext())
    


    var noteAdapter = NoteAdapter(this, listOfNotes)
    listViewNotes.adapter = noteAdapter



inner class NoteAdapter : BaseAdapter 

    var notesList = ArrayList<Note>()
    var context: Context? = null

    constructor(context: Context, notesList:ArrayList<Note>)
        this.notesList=notesList
        this.context = context
    

    override fun getView(position: Int, p1: View?, p2: ViewGroup?): View 

        var view = layoutInflater.inflate(R.layout.list_view_pattern,null)
        var note = notesList[position]

        view.textViewTitle.text = note.Title
        view.imageViewPic.setImageBitmap(note.BMP)

        return view
    

    override fun getItem(position: Int): Any 
        return notesList[position]
    

    override fun getItemId(position: Int): Long 
        return position.toLong()
    

    override fun getCount(): Int 
        return notesList.size
    

课堂笔记:

class Note 

var ID:Int? = null
var Title:String? = null
var Note:String? = null
var BMP:Bitmap? = null

constructor(id:Int,title:String,note:String,bmp:Bitmap)

    ID = id
    Title = title
    Note = note
    BMP = bmp

布局添加注释

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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_
    android:layout_
    tools:context=".AddNoteActivity">

    <EditText
        android:id="@+id/editTextNote"
        android:layout_
        android:layout_
        android:layout_marginBottom="64dp"
        android:layout_marginEnd="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginStart="8dp"
        android:ems="10"
        android:hint="Your Note ..."
        android:inputType="textMultiLine"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.508"
        app:layout_constraintStart_toStartOf="parent" />

    <Button
        android:id="@+id/buttonAddPic"
        android:layout_
        android:layout_
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="Add Picture"
        app:layout_constraintBottom_toTopOf="@+id/editTextNote"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/imageViewShowPic"
        app:layout_constraintVertical_bias="0.913" />

    <ImageView
        android:id="@+id/imageViewShowPic"
        android:layout_
        android:layout_
        android:layout_marginEnd="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="84dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.502"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:srcCompat="@mipmap/ic_launcher" />

    <Button
        android:id="@+id/buttonSave"
        android:layout_
        android:layout_
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="Save"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/editTextNote"
        app:layout_constraintVertical_bias="1.0" />

    <EditText
        android:id="@+id/editTextTitle"
        android:layout_
        android:layout_
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:ems="10"
        android:hint="Title"
        android:inputType="textMultiLine"
        app:layout_constraintBottom_toTopOf="@+id/imageViewShowPic"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

主布局:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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_
    android:layout_
    tools:context=".MainActivity">

    <ListView
        android:id="@+id/listViewNotes"
        android:layout_
        android:layout_
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/floatingActionButton"
        android:layout_
        android:layout_
        android:layout_marginBottom="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:clickable="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:srcCompat="@android:drawable/ic_input_add" />
</android.support.constraint.ConstraintLayout>

布局列表视图模式:

<?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_
    android:layout_
    android:layout_margin="10dp"
    android:background="#fff"
    android:paddingBottom="5dp"
    android:paddingLeft="10dp"
    android:paddingRight="10dp"
    android:paddingTop="10dp">

    <LinearLayout
        android:layout_
        android:layout_
        android:orientation="horizontal">

        <LinearLayout
            android:layout_
            android:layout_
            android:layout_weight="1"
            android:orientation="vertical">

            <TextView
                android:id="@+id/textViewTitle"
                android:layout_
                android:layout_
                android:layout_marginRight="8dp"
                android:layout_marginTop="10dp"
                android:textColor="#000"
                android:textSize="23sp" />

        </LinearLayout>

        <ImageView
            android:id="@+id/imageViewPic"
            android:layout_
            android:layout_
            tools:srcCompat="@mipmap/ic_launcher" />
    </LinearLayout>
</LinearLayout>

【问题讨论】:

您是否看到“错误”或“注释已保存!”吐司? @mTak 不,我没有 所以数据库中可能没有保存任何内容。你能发布你的logcat吗? @mTak uplooder.net/img/image/48/b39c413c445583203c8d009e68cf29bc/… 尝试将val BMP = BitmapFactory.decodeByteArray(Pic,cursor.getColumnIndex("Pic"),Pic!!.size)更改为val BMP = BitmapFactory.decodeByteArray(Pic,0,Pic!!.size) 【参考方案1】:

从日志中可以看出,错误是由于数组越界造成的,并且您的代码的最新调用来自 LoadData。 LoadData 中唯一的数组是转换为位图的字节数组。

解码/转换采用字节数组、偏移量和长度参数。它转换字节数组,从作为最后一个参数给出的字节数的偏移量开始。所以说你有一个 100 字节的数组并且列索引是 1 然后你说转换字节 1-100 字节 100 超出了界限(你只有 0 - 99)。

因此,您只需将 0 编码为偏移量。所以改变:-

BitmapFactory.decodeByteArray(Pic,cursor.getColumnIndex("Pic"),Pic!!.size)

BitmapFactory.decodeByteArray(Pic,0,Pic!!.size)

【讨论】:

以上是关于从数据库中获取照片并在列表视图中显示的主要内容,如果未能解决你的问题,请参考以下文章

如何从自定义列表视图中获取选定项目并在 toast 消息中打印?

如何从核心数据中获取数据并在表格视图中显示 iOS 6

从手机图库中获取随机图片并在视图中显示

如何从 iOS 照片库中获取图像并在 UIWebView 中显示

获取所有联系人并在列表视图中显示它们

通过意图获取数据并将其显示在列表视图中时,应用程序正在停止