从数据库中获取照片并在列表视图中显示
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 消息中打印?