I know that sounds weird.
So in my MainActivity am declaring an Array of the object SongInfo which looks like this:
class SongInfo {
lateinit var title: String
lateinit var contentId: String
lateinit var filepath: String
}
This is how I am declaring the Array in my MainActivity:
lateinit var songInfo: Array<SongInfo?>
So, now when I press a button, the listener of this button executes this:
searchButton.setOnClickListener {
val cursor = contentResolver.query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
arrayOf(
"_id",
"_data",
MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.ARTIST,
MediaStore.Audio.Media.DURATION
),
"is_music == 1",
null, null
)
songInfo = arrayOfNulls(cursor!!.count)
for (index in songInfo.indices) {
songInfo[index] = SongInfo()
Log.d(tag, "searchButton: $index")
}
adapter = listMusicService.listMusic(cursor)
adapter.notifyDataSetChanged()
}
The ListMusicService class looks like this:
class ListMusicService(val context: Context, private var adapter: ArrayAdapter<Any>) {
private val tag = "MusicShare/ListMusicService"
fun listMusic(cursor: Cursor): ArrayAdapter<Any> {
val activity = MainActivity()
adapter.clear()
val songInfo = arrayOfNulls<SongInfo>(cursor.count)
var duration: Double
var index = 0
while (cursor.moveToNext()) {
duration = ((cursor.getDouble(4) / 600).roundToInt() / 100).toDouble()
adapter.add(cursor.getString(3) + ": " + cursor.getString(2) + " (" + duration + ")")
val filepath = File(cursor.getString(1))
Log.d(tag, "searchMusic: writing songInfo")
songInfo[index] = SongInfo()
songInfo[index]!!.title = filepath.name
songInfo[index]!!.filepath = filepath.absolutePath
activity.songInfo[index]!!.filepath = filepath.absolutePath
songInfo[index]!!.contentId = cursor.getString(0)
index++
}
return adapter
}
}
Pressing the searchButton now causes a kotlin.UninitializedPropertyAccessException: lateinit property songInfo has not been initialized.
But I don't understand why because in the listener method of searchButton I'm initializing every object of the array. Does anybody know why this happens and maybe what goes wrong?
EDIT: Creating the ListMusicService:
val listMusicService = ListMusicService(this, adapter)
You are creating a new object of MainActivity
val activity = MainActivity()
which is just an empty object, instead you need to pass this as an instance of MainAcitiy to listMusic method and use it.
ListMusicService class already taking a context object so seems like you are passing the activity's instance (no code about it), use the existing adapter instance of MainAcitivty.
// somewhere in main activity
val listMusicService = ListMusicService(this, adapter)
// inside searchButton.setOnClickListener
adapter = listMusicService.listMusic(cursor)
adapter.notifyDataSetChanged()
In ListMusicService
fun listMusic(cursor: Cursor): ArrayAdapter<Any> {
adapter.clear()
val songInfo = arrayOfNulls<SongInfo>(cursor.count)
var duration: Double
var index = 0
while (cursor.moveToNext()) {
duration = ((cursor.getDouble(4) / 600).roundToInt() / 100).toDouble()
adapter.add(cursor.getString(3) + ": " + cursor.getString(2) + " (" + duration + ")")
val filepath = File(cursor.getString(1))
Log.d(tag, "searchMusic: writing songInfo")
songInfo[index] = SongInfo()
songInfo[index]!!.title = filepath.name
songInfo[index]!!.filepath = filepath.absolutePath
activity.songInfo[index]!!.filepath = filepath.absolutePath
songInfo[index]!!.contentId = cursor.getString(0)
index++
}
return adapter
}
Related
I tried to convert a java file to kotlin file but i'm getting this error : An annotation argument must be a compile-time constant
#StringDef(
BillingEnum.ALL,
BillingEnum.PAID,
BillingEnum.PENDING,
BillingEnum.OVERDUE,
BillingEnum.OPEN,
BillingEnum.DELETED
)
annotation class BillingEnum {
companion object {
var ALL = ""
var PAID = "paid"
var PENDING = "pending"
var OVERDUE = "overdue"
var OPEN = "open"
var DELETED = "deleted"
}
}
Before it looked like this:
#StringDef({
BillingEnum.ALL,
BillingEnum.PAID,
BillingEnum.PENDING,
BillingEnum.OVERDUE,
BillingEnum.OPEN,
BillingEnum.DELETED
})
public #interface BillingEnum {
String ALL = "";
String PAID = "paid";
String PENDING = "pending";
String OVERDUE = "overdue";
String OPEN = "open";
String DELETED = "deleted";
}
You must write
annotation class BillingEnum {
companion object {
const val ALL = ""
const val PAID = "paid"
const val PENDING = "pending"
const val OVERDUE = "overdue"
const val OPEN = "open"
const val DELETED = "deleted"
}
}
I'm creating a kotlin app. I have an issue with mediaMetadataCompat. Maybe I have to put data to extras? I put data like this
audios = allAudios!!.map { audio ->
MediaMetadataCompat.Builder()
.putString(METADATA_KEY_WRITER, audio.writer._id)
.putString(METADATA_KEY_ARTIST, audio.writer.name)
.putString(METADATA_KEY_DISPLAY_SUBTITLE, audio.writer.name)
.putString(METADATA_KEY_MEDIA_ID, audio._id)
.putString(METADATA_KEY_TITLE, audio.title)
.putString(METADATA_KEY_DISPLAY_TITLE, audio.title)
.putString(METADATA_KEY_DISPLAY_ICON_URI, audio.writer.image)
.putString(METADATA_KEY_DATE, audio.createdAt)
.putString(METADATA_KEY_MEDIA_URI, audio.filePath)
.putString(METADATA_KEY_DISPLAY_DESCRIPTION, audio.description)
.build()
}
Get it like this
fun MediaMetadataCompat.toAudio(): Audio? {
return let {
Audio(
_id = it.description.mediaId ?: "",
title = it.description.title.toString(),
filePath = it.description.mediaUri.toString(),
description = it.description.description.toString(),
writer = User(
_id = it.description.extras?.getString("writerId").toString(),
name = it.description.subtitle.toString(),
image = it.description.iconUri.toString()
),
tags = listOf("Shit"),
listened = 1,
language = "en",
isForKids = false,
duration = 70,
createdAt = "2020:01:01"
)
}
}
It only gives my title, icon_uri, media_uri and media_id
Sharing a small part of my code:
Below is building object of MediaMetaDataCompat. I am adding couple of data there and have used in different parts of app.
var media = MediaMetadataCompat.Builder()
.putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, data.id.toString())
.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, data.artist_name)
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, data.title)
.putString(MediaMetadataCompat.METADATA_KEY_MEDIA_URI, data.audio_path)
.putString(MediaMetadataCompat.METADATA_KEY_DATE, data.track_year)
.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI, data.image_path)
.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, data.duration.toLong())
.build()
mediaItem is object of MediaMetadataCompat and that is how I am getting values of the fields which was added to object.
mediaItem is object of MediaMetadataCompat
var artist = mediaItem.bundle.getString(MediaMetadataCompat.METADATA_KEY_ARTIST)!!
var title = mediaItem.bundle.getString(MediaMetadataCompat.METADATA_KEY_TITLE)!!
var duration = mediaItem.bundle.getLong(MediaMetadataCompat.METADATA_KEY_DURATION)!!
var icon = mediaItem.bundle.getString(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI)!!
so I'm new to realm data base and I'm trying to show the data that the user wrote throw an Edit text and show it in a Textview..
My realm class
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
import io.realm.annotations.RealmClass
#RealmClass
open class GoodStudents : RealmObject(){
#PrimaryKey
var id: Long = 0
var name : String? = null
var grade : Int? = null
}
Main activity code
Realm.init(this)
val convig = RealmConfiguration.Builder()
.name("GoodStudents").build()
val realm = Realm.getInstance(convig)
realm.beginTransaction()
count = realm.where(GoodStudents::class.java).findAll().size
val goodStudents = realm.createObject(GoodStudents::class.java, count+1)
goodStudents.name = name.text.toString()
goodStudents.grade
realm.commitTransaction()
val readData = realm.where(GoodStudents::class.java).findAll()
saveButton.setOnClickListener {
Toast.makeText(this,"Data is saved", Toast.LENGTH_LONG).show()
var text = text.text
readData.forEach { save ->
save.name = text as String?
}
}
P.C. Java code is acceptable..
so I found out that writing this code will work
saveButton.setOnClickListener {
val convig = RealmConfiguration.Builder()
.name("GoodStudents").build()
val realm = Realm.getInstance(convig)
realm.beginTransaction()
count = realm.where(GoodStudents::class.java).findAll().size
val goodStudents = realm.createObject(GoodStudents::class.java, count+1)
goodStudents.name = name.text.toString()
goodStudents.grade = grade.text.toString().toInt()
val readData = realm.where(GoodStudents::class.java).findAll()
readData.forEach { save ->
text.text = "" + save.name + ": " + goodStudents.grade
}
realm.commitTransaction()
}
Hello guys I have a simple question ,
I have a Map full of element and I want to convert It in my Object , let me show you some code :
Here is my Object :
class Bundle(map: Map<String, Any>) {
var version: String?
var app: String?
var countries: ArrayList<Any>?
var currency: ArrayList<Any>?
var force: Boolean?
var name: String?
var service: ArrayList<Any>?
var money: Int?
init {
version= null
app= null
countries= arrayListOf()
currency= arrayListOf<Any>()
force= true
name = ""
service= arrayListOf<Any>()
money= 0
}
}
And there is the Map that i want to convert:
fun getBundle() {
var db = FirebaseFirestore.getInstance()
val docRef = db.collection("aa").document("bb")
docRef.get().addOnCompleteListener { task ->
if (task.isSuccessful) {
val document = task.result
if (document.exists()) {
Log.d("Doc", "DocumentSnapshot data: " + document.data!!)
// Here i want to take (document.data!!) and convert it to my Bundle class
} else {
Log.d("NO doc", "No such document")
}
} else {
Log.d("ERROR", "get failed with ", task.exception)
}
}
}
Thank you !
Ok I found the solution
I transformed my Bundle class in a data class :
data class Bundle(
var version: String? = null,
var app: String? = null,
var countries: ArrayList<Any> = arrayListOf(),
var currency: HashMap<String, Any> = hashMapOf(),
var force: Boolean = false,
var name: String? = null,
var service: ArrayList<Any> = arrayListOf(),
var money: Int = 0
)
And then I simply added this on my method , where I want to convert my Map to my Bundle Object :
val myObject = document.toObject(Bundle::class.java)
This is error, it says index out of bounds, but i couldn't how can i solve it, there are some Turkish words but they aren't important, i think:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.burhanozen.nothesaplama, PID: 26919
java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.example.burhanozen.nothesaplama/com.example.burhanozen.nothesaplama.MainActivity}: android.database.CursorIndexOutOfBoundsException: Index 1 requested, with a size of 1
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
at ........
I was trying to store some kind of student information. I have these errors, and I share codes below.
This is my MainActivity:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val toolbar = findViewById(R.id.toolbar) as Toolbar
setSupportActionBar(toolbar)
val fab = findViewById(R.id.fab) as FloatingActionButton
fab.setOnClickListener {
val intent = Intent(this#MainActivity,NotEkrani::class.java)
startActivity(intent) }
val studentsArray = ArrayList<String>()
val arrayAdapter = ArrayAdapter(this,android.R.layout.simple_list_item_1,studentsArray)
listView.adapter= arrayAdapter
try{
val myDatabase = this.openOrCreateDatabase("student", Context.MODE_PRIVATE,null)
myDatabase.execSQL("CREATE TABLE IF NOT EXISTS students (isim TEXT," +
" dersbir TEXT, dersbirkredi TEXT, dersbirort TEXT," +
" dersiki TEXT, dersikikredi TEXT, dersikiort TEXT) ")
val cursor = myDatabase.rawQuery("select * from students",null)
val nameIx = cursor.getColumnIndex("isim")
val dersbirIx = cursor.getColumnIndex("dersbir")
val dersbirkrediIx = cursor.getColumnIndex("dersbirkredi")
val dersbirortIx = cursor.getColumnIndex("dersbirort")
val dersikiIx = cursor.getColumnIndex("dersiki")
val dersikikrediIx = cursor.getColumnIndex("dersikikredi")
val dersikiortIx = cursor.getColumnIndex("dersikiort")
cursor.moveToNext()
while (cursor != null){
studentsArray.add(cursor.getString(nameIx))
studentsArray.add(cursor.getString(dersbirIx))
studentsArray.add(cursor.getString(dersbirkrediIx))
studentsArray.add(cursor.getString(dersbirortIx))
studentsArray.add(cursor.getString(dersikiIx))
studentsArray.add(cursor.getString(dersikikrediIx))
studentsArray.add(cursor.getString(dersikiortIx))
cursor.moveToNext()
arrayAdapter.notifyDataSetChanged()
}
while (cursor!=null){
cursor!!.close()
}
}catch (e:SQLException){
}
And this is my second Activity Page, i couldn't any error here, but may be this can help. I wrote database codes here.
fun kaydet(view:View){
val isim = isim.text.toString()
val dersbir = dersbir.text.toString()
val dersbirkredi = dersbirkredi.text.toString()
val dersbirort = dersbirort.text.toString()
val dersiki = dersiki.text.toString()
val dersikikredi = dersikikredi.text.toString()
val dersikiort = dersikiort.text.toString()
try {
val myDatabase = openOrCreateDatabase("student", Context.MODE_PRIVATE,null)
myDatabase.execSQL("CREATE TABLE IF NOT EXISTS students (isim TEXT," +
" dersbir TEXT, dersbirkredi TEXT, dersbirort TEXT," +
" dersiki TEXT, dersikikredi TEXT, dersikiort TEXT) ")
val sqlString = "INSERT INTO students (isim,dersbir,dersbirkredi,dersbirort,dersiki,dersikikredi,dersikiort) VALUES(?,?,?,?,?,?,?)"
val statement = myDatabase.compileStatement(sqlString)
statement.bindString(1,isim)
statement.bindString(2,dersbir)
statement.bindString(3,dersbirkredi)
statement.bindString(4,dersbirort)
statement.bindString(5,dersiki)
statement.bindString(6,dersikikredi)
statement.bindString(7,dersikiort)
statement.execute()
}catch (e:SQLException){
}
val intent = Intent(this,MainActivity::class.java)
startActivity(intent)
}
Change your while loop to look like this:
while (cursor.moveToNext()){
studentsArray.add(cursor.getString(nameIx))
...
}
(Remove all the other cursor.moveToNext() from your code)
You are checking for cursor != null in your while loop condition, but it won't become null after you read all the rows from cursor.
In the above code, cursor.moveToNext returns true if there is a row next. Otherwise returns false and the loop terminates.
And, just noticed, you should change this from,
while (cursor!=null){
cursor!!.close()
}
to an if check:
if (cursor!=null){
cursor.close()
}
Or, as Todd suggested in the comments, you can use the Higher order function use which automatically closes the cursor, which is simlar to Java 7 try-with-resources.
cursor.use {
while (cursor.moveToNext()){
studentsArray.add(cursor.getString(nameIx))
...
}
}
You are getting this error because your cursor size is 1. There is only one record in your database. But you are querying database more than 1 time. That is the reason of your Error.
First of all your complete code of execution is wrong.
You are creating a database in your activity. If you do you can't manage your database properly and efficiently.
First, you have to create a SqliteOpenHelper database in a separate class. Then you have to create a table there. Then write helper methods there to get and insert values from it.
Your database class should be like the below example.
class DbHelper(context: Context) : SQLiteOpenHelper(context, "example.db", null, 4) {
val TAG = javaClass<DbHelper>().getSimpleName()
val TABLE = "logs"
companion object {
public val ID: String = "_id"
public val TIMESTAMP: String = "TIMESTAMP"
public val TEXT: String = "TEXT"
}
val DATABASE_CREATE =
"CREATE TABLE if not exists " + TABLE + " (" +
"${ID} integer PRIMARY KEY autoincrement," +
"${TIMESTAMP} integer," +
"${TEXT} text"+
")"
fun log(text: String) {
val values = ContentValues()
values.put(TEXT, text)
values.put(TIMESTAMP, System.currentTimeMillis())
getWritableDatabase().insert(TABLE, null, values);
}
fun getLogs() : Cursor {
return getReadableDatabase()
.query(TABLE, arrayOf(ID, TIMESTAMP, TEXT), null, null, null, null, null);
}
override fun onCreate(db: SQLiteDatabase) {
Log.d(TAG, "Creating: " + DATABASE_CREATE);
db.execSQL(DATABASE_CREATE)
}
override fun onUpgrade(p0: SQLiteDatabase, p1: Int, p2: Int) {
}
}
Since you are using Kotin database is very easy with Anko-Sqlite. By this library storing and retrieving data from the database is so easy. You can check it here.
https://github.com/Kotlin/anko/wiki/Anko-SQLite#using-anko-sqlite-in-your-project