我正在用Kotlin在android studio中开发一个Note App。该应用程序具有一个带有列表视图和浮动操作按钮的主活动,以及一个带有标题编辑文本,注释编辑文本,插入图片按钮,保存按钮和图像视图的添加注释活动。
当您触摸浮动按钮时,它将进入“应用笔记活动”。在这里,您可以写笔记,插入图片并在图像视图中查看,最后将它们保存在SQLite数据库中。当您回到Main Activity时,它应该在列表视图中显示标题及其图片。 最后一部分是我的问题!该应用程序崩溃了,而不是创建列表视图。
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_width="match_parent"
android:layout_height="match_parent"
tools:context=".AddNoteActivity">
<EditText
android:id="@+id/editTextNote"
android:layout_width="311dp"
android:layout_height="141dp"
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_width="wrap_content"
android:layout_height="wrap_content"
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_width="145dp"
android:layout_height="149dp"
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_width="wrap_content"
android:layout_height="wrap_content"
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_width="309dp"
android:layout_height="wrap_content"
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_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ListView
android:id="@+id/listViewNotes"
android:layout_width="0dp"
android:layout_height="0dp"
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_width="wrap_content"
android:layout_height="wrap_content"
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>
布局list_view_pattern:
<?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="wrap_content"
android:layout_margin="10dp"
android:background="#fff"
android:paddingBottom="5dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/textViewTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_marginTop="10dp"
android:textColor="#000"
android:textSize="23sp" />
</LinearLayout>
<ImageView
android:id="@+id/imageViewPic"
android:layout_width="90dp"
android:layout_height="90dp"
tools:srcCompat="@mipmap/ic_launcher" />
</LinearLayout>
</LinearLayout>
答案 0 :(得分:0)
从日志中显示,该错误是由于数组越界引起的,并且代码中的最新调用是来自LoadData。 LoadData中唯一的数组是转换为位图的字节数组。
解码/转换将三个参数设为字节数组,偏移量和长度。它转换字节数组,从最后一个参数给出的字节数的偏移量开始。因此,假设您有一个100字节的数组,并且列索引为1,则表示转换字节1-100字节100超出范围(您只有0-99)。
因此,您只需要将0编码为偏移量即可。所以改变:-
BitmapFactory.decodeByteArray(Pic,cursor.getColumnIndex("Pic"),Pic!!.size)
到
BitmapFactory.decodeByteArray(Pic,0,Pic!!.size)