I really need your expertise as I got stuck for a long time with this problem. I have a main activity which gets MP3 file uri from the emulator memory. It saves the uri in an SQLite database and reads the database than to populate a ListView. When a ListView item is selected, main activity starts another activity and handles it the file's uri to play the file. If I start the app first time it plays selected files just fine. When I close the app and start it again, I select a ListView item saved in SQLite last time. This time it cause the player activity crash at setDataSource stage. If I select a new MP3 file from emulator memory this time however, it works ok. Looks like the problem is connected to uri and SQLite. I checked that uri string is the same in both cases. Here is the main activity
class MainActivity : AppCompatActivity() {
val REQUEST_FILE = 1
lateinit var newFilePath: Uri
lateinit var newFileName: String
lateinit var AuDB: SQLiteDatabase
val auName = mutableListOf<String>("")
var auUri = mutableListOf<Uri>()
var audioFileValues: ContentValues = ContentValues()
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val MyDBHelper = AudioSQLhelper(this)
AuDB = MyDBHelper.writableDatabase
val auCursor = AuDB.query("myaudio", arrayOf("name", "uri"), null, null, null, null, "prio", null)
readcursor(auCursor)
val tbMain = findViewById<Toolbar>(R.id.toolbar1)
setSupportActionBar(tbMain)
val scAdapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, auName)
val lvData = findViewById<ListView>(R.id.lv1)
lvData.setAdapter(scAdapter)
lvData.setOnItemClickListener { parent, view, position, id ->
val playIntent: Intent = Intent(this, PlayTest::class.java)
playIntent.putExtra("aname", auName[position])
playIntent.setData(auUri[position])
startActivity(playIntent)
}
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu_main, menu)
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.action_select_file -> {
// Select a new audio file
val audioIntent: Intent = Intent(Intent.ACTION_GET_CONTENT)
audioIntent.setType("audio/mpeg")
audioIntent.addCategory(Intent.CATEGORY_OPENABLE)
startActivityForResult(audioIntent, REQUEST_FILE)
}
}
return super.onOptionsItemSelected(item)
}
private fun readcursor(auCursor: Cursor) {
auCursor.moveToFirst()
auName.clear()
auUri.clear()
while (auCursor.isAfterLast == false) {
auName.add(auCursor.getString(0))
auUri.add(Uri.parse(auCursor.getString(1)))
auCursor.moveToNext()
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_FILE && resultCode == RESULT_OK) {
newFilePath = data?.data!!
newFileName = newFilePath.lastPathSegment?.substringAfterLast('/').toString()
if (AuDB.query("myaudio", arrayOf("_id"), "name=?", arrayOf(newFileName), null, null, null).moveToFirst()) {
val au_text = "This file has already been added!"
val au_duration = Toast.LENGTH_SHORT
val toast = Toast.makeText(applicationContext, au_text, au_duration)
toast.show()
} else {
// Add the file to the database
audioFileValues.put("name", newFileName)
audioFileValues.put("uri", newFilePath.toString())
audioFileValues.put("prio", 1)
addRecord(audioFileValues)
}
}
}
// Add new file at the beginning if the list
fun addRecord(content: ContentValues) {
val MyDBHelper = AudioSQLhelper(this)
val AuDB = MyDBHelper.writableDatabase
// Increase others file priority fiels by one
AuDB.execSQL("UPDATE myaudio SET prio = prio + 1")
AuDB.insert("myaudio", null, content)
val auCursor = AuDB.query("myaudio", arrayOf("name", "uri"), null, null, null, null, "prio", null)
readcursor(auCursor)
val scAdapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, auName)
val lvData = findViewById<ListView>(R.id.lv1)
lvData.setAdapter(scAdapter)
}
}
Here is the player activity
class PlayTest : AppCompatActivity() {
var mPlayer = MediaPlayer()
lateinit var auUri: Uri
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_playtest)
val caption = findViewById<TextView>(R.id.txtAUName)
caption.text = intent.getStringExtra("aname")
auUri = intent.data!!
}
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
fun playClick(view: View) {
when (view.id) {
R.id.btnAStart -> {
mPlayer = MediaPlayer().apply {
setAudioAttributes(
AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.setUsage(AudioAttributes.USAGE_MEDIA)
.build()
)
setDataSource(this@PlayTest, auUri)
prepare()
}
mPlayer.start()
}
R.id.btnAStop -> {
mPlayer.pause()
}
R.id.btnAClose -> {
mPlayer.release()
finish()
}
}
}
}
Here is the Logcat. It doesn't say much to me
2021-04-03 01:10:51.193 11233-11233/com.example.test1 E/MediaPlayerNative: Unable to create media player
2021-04-03 01:10:51.195 11233-11233/com.example.test1 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.test1, PID: 11233
java.lang.IllegalStateException: Could not execute method for android:onClick
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:414)
at android.view.View.performClick(View.java:7448)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1119)
at android.view.View.performClickInternal(View.java:7425)
at android.view.View.access$3600(View.java:810)
at android.view.View$PerformClick.run(View.java:28305)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:409)
at android.view.View.performClick(View.java:7448)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1119)
at android.view.View.performClickInternal(View.java:7425)
at android.view.View.access$3600(View.java:810)
at android.view.View$PerformClick.run(View.java:28305)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: java.io.IOException: setDataSource failed.: status=0x80000000
at android.media.MediaPlayer.nativeSetDataSource(Native Method)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1175)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1162)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1079)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1004)
at com.example.test1.PlayTest.playClick(PlayTest.kt:46)
at java.lang.reflect.Method.invoke(Native Method)
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:409)
at android.view.View.performClick(View.java:7448)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1119)
at android.view.View.performClickInternal(View.java:7425)
at android.view.View.access$3600(View.java:810)
at android.view.View$PerformClick.run(View.java:28305)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)