I am new to Kotlin, so I am having trouble on how to solve this.
I have created a bottom navigation view that I am using to switch between activities. When I call the BottomNavigationView.OnNavigationItemSelectedListener my app crashes and I dont know why. Can anyone please help?
I have searched, but I only find answers on fragments.
My MainActivity code:
class MainActivity : AppCompatActivity() {
private val navigasjonen = BottomNavigationView.OnNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.home -> {
return#OnNavigationItemSelectedListener false
}
R.id.leggTilNavigasjon -> {
val intent = Intent(this#MainActivity, AddRec::class.java)
startActivity(intent)
return#OnNavigationItemSelectedListener true
}
R.id.favoritter -> {
val intent = Intent(this#MainActivity, MyRecipes::class.java)
startActivity(intent)
return#OnNavigationItemSelectedListener true
}
R.id.utforsk -> {
return#OnNavigationItemSelectedListener true
}
}
false
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val bottomNavigation = findViewById<BottomNavigationView>(R.id.bottom_navigation)
//bottomNavigation.setSelectedItemId(R.id.home)
bottomNavigation.setOnNavigationItemSelectedListener(navigasjonen)
}
}
My xml code:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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"
android:background="#color/colorLys"
android:id="#+id/home">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/navigationView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:background="?android:attr/windowBackground"
app:menu="#menu/navigasjon" />
</androidx.constraintlayout.widget.ConstraintLayout>
My error:
2020-01-27 14:20:06.197 20309-20309/com.example.foodleaks E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.foodleaks, PID: 20309
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.foodleaks/com.example.foodleaks.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.google.android.material.bottomnavigation.BottomNavigationView.setOnNavigationItemSelectedListener(com.google.android.material.bottomnavigation.BottomNavigationView$OnNavigationItemSelectedListener)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.google.android.material.bottomnavigation.BottomNavigationView.setOnNavigationItemSelectedListener(com.google.android.material.bottomnavigation.BottomNavigationView$OnNavigationItemSelectedListener)' on a null object reference
at com.example.foodleaks.MainActivity.onCreate(MainActivity.kt:39)
at android.app.Activity.performCreate(Activity.java:7136)
at android.app.Activity.performCreate(Activity.java:7127)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
In your findViewById you are passing R.id.bottom_navigation:
val bottomNavigation = findViewById<BottomNavigationView>(R.id.bottom_navigation)
and in the layout it has the id:
android:id="#+id/navigationView"
You can either change the id on the layout:
android:id="#+id/bottom_navigation"
Or change it in the findViewById:
val bottomNavigation = findViewById<BottomNavigationView>(R.id.navigationView)
Be consistent so that it can find the BottomNavigationView element and it won't crash for a null object reference.
The error is present in the stacktrace. I recommend learning to read Java/Android stacktraces :)
The culprit in stacktrace:
Attempt to invoke virtual method 'void com.google.android.material.bottomnavigation.BottomNavigationView.setOnNavigationItemSelectedListener(com.google.android.material.bottomnavigation.BottomNavigationView$OnNavigationItemSelectedListener)' on a null object reference
Your BottomNavigationView is null. Why?
Look at your declaration in layout:
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/navigationView
And that's how you find the view:
findViewById<BottomNavigationView>(R.id.bottom_navigation)
You are using wrong view id.
Related
Am having problem while passing my arrayAdapter the ListViewAdapter in android using kotlin.
The error message java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a null object reference indicates that I am trying to call a method on an object reference which is null.
Here is my mainActivity:
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.ArrayAdapter
import android.widget.ListView
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val lv = findViewById<ListView>(R.id.myList)
val array = arrayOf("test", "test", "test", "test", "test")
val myAdapter: ArrayAdapter<String> =
ArrayAdapter(this, android.R.layout.simple_list_item_1, array)
lv.adapter = myAdapter
}
}
Here is the Layout file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/relativeLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingHorizontal="20dp"
tools:context=".MainActivity">
<ListView
android:id="#+id/myList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp" />
</LinearLayout>
And here is the error that I got
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a null object reference
at com.example.myapplication5.MainActivity.onCreate(MainActivity.kt:16)
at android.app.Activity.performCreate(Activity.java:7994)
at android.app.Activity.performCreate(Activity.java:7978)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
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)
2022-12-25 14:33:52.075 14422-14438/com.example.myapplication5 W/System: A resource failed to call close.
Debug shows that myAdapter contains corretly the array values
You are passing ArrayAdapter where in error you can check it needs ListAdapter.
Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)
You have to call setContentView(<Name of your layout file>) before accessing any views. See working example (in my case the name of the layout file is activity_main.xml):
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val lv = findViewById<ListView>(R.id.myList)
val array = arrayOf("test", "test", "test", "test", "test")
val myAdapter: ArrayAdapter<String> =
ArrayAdapter(this, android.R.layout.simple_list_item_1, array)
lv.adapter = myAdapter
}
}
I am developing an app where there are different user interfaces depending on what kind of client u are. I wanted to create different Bottom Navigations depending on what type of user is logged in. The if- clause works, so the Log tells me the correct user type but I am getting a fatal exception because it tells me that the id of the second bottom navigation is not existent, but like the first one works. I now it's not the cleanest way to do so but I couldn't find a different way. Here is my code:
This is the main.kt
class MainActivity : AppCompatActivity() {
lateinit var homeFragment: HomeFragment
lateinit var mapsFragment: MapsFragment
lateinit var profil: Profil
lateinit var chat: Chat
lateinit var homeFoto: HomeFoto
val COARSE_LOCATION_RQ = 101
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val mAuth = FirebaseAuth.getInstance()
lateinit var mDatabase : DatabaseReference
val user = mAuth.currentUser
val uid = user!!.uid
var snapshot: DataSnapshot
var anwender = "Suchender"
mDatabase = FirebaseDatabase.getInstance().getReference("User").child(uid)
//Log.e("keyKey",mDatabase.database.getReference("Anwendertyp").child(anwender).toString())
mDatabase!!.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
if (snapshot.exists() && snapshot.child("Anwendertyp").value.toString() == "Suchender" ){
Log.e("keyKey",snapshot.child("Anwendertyp").value.toString())
//findNavController(R.id.suchenderNavigation)
var bottomnav = findViewById<BottomNavigationView>(R.id.BottomNavMenu)
bottomnav.setOnNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.navigation_home -> {
homeFragment = HomeFragment()
supportFragmentManager
.beginTransaction()
.replace(R.id.frameLayout, homeFragment)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.commit()
}
R.id.mapsFragment -> {
mapsFragment = MapsFragment()
supportFragmentManager
.beginTransaction()
.replace(R.id.frameLayout, mapsFragment)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.commit()
}
R.id.navigation_notifications -> {
profil = Profil()
supportFragmentManager
.beginTransaction()
.replace(R.id.frameLayout, profil)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.commit()
}
}
true
}
}
else{
setContentView(R.layout.startseite_fotografvideograf)
Log.e("key",snapshot.child("Anwendertyp").value.toString())
// Navigation.findNavController(HomeFoto().requireActivity(), R.id.navigation_home_fotografvideograf)
//findNavController(R.id.fotografNavigation)
//This is the variable that triggers the fatal exception
var bottomn = findViewById<BottomNavigationView>(R.id.bottomNavFoto)
Log.e("heyo", bottomn.toString())
bottomn.setOnNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.navigation_home_fotografvideograf -> {
homeFoto = HomeFoto()
supportFragmentManager
.beginTransaction()
.replace(R.id.frameLayout, homeFoto)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.commit()
}
R.id.navigation_notifications -> {
profil = Profil()
supportFragmentManager
.beginTransaction()
.replace(R.id.frameLayout, profil)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.commit()
}
R.id.chatchat -> {
chat = Chat()
supportFragmentManager
.beginTransaction()
.replace(R.id.frameLayout, chat)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.commit()
}
}
true
}
}
}
override fun onCancelled(error: DatabaseError) {
}
})
}
This is the main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#E8E8E8">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNavigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_margin="30dp"
android:background="#drawable/buttom_bg"
android:elevation="2dp"
app:itemIconSize="30dp"
app:itemIconTint="#drawable/item_selector"
app:itemRippleColor="#android:color/transparent"
app:labelVisibilityMode="unlabeled"
app:menu="#menu/bottom_nav_menu" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNavFoto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_margin="30dp"
android:background="#drawable/buttom_bg"
android:elevation="2dp"
app:itemIconSize="30dp"
app:itemIconTint="#drawable/item_selector"
app:itemRippleColor="#android:color/transparent"
app:labelVisibilityMode="unlabeled"
app:menu="#menu/bottom_nav_fotograf" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
And here is the xml of the second bottom navigation:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/BottomNavFotograf"
>
<item
android:id="#+id/navigation_home_fotografvideograf"
android:icon="#drawable/ic_home_black_24dp"
android:title="#string/title_home" />
<item
android:id="#+id/navigation_notifications"
android:icon="#drawable/ic_baseline_person_24"
android:title="#string/profil" />
<item
android:id="#+id/chatchat"
android:icon="#drawable/ic_chat"
android:title="Chat" />
</menu>
Update
This is the FATAL EXCEPTION I'm getting:
E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.discoverme, PID: 4430 java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.google.android.material.bottomnavigation.BottomNavigationView.toString()' on a null object reference at com.example.discoverme.MainActivity$onCreate$1.onDataChange(MainActivity.kt:114) at com.google.firebase.database.core.ValueEventRegistration.fireEvent(ValueEventRegistration.java:75) at com.google.firebase.database.core.view.DataEvent.fire(DataEvent.java:63) at – Luzie Ewert 19 hours ago Delete
com.google.firebase.database.core.view.EventRaiser$1.run(EventRaiser.java:55) at android.os.Handler.handleCallback(Handler.java:751) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:154)
like, it's so confusing. I know it has to be something with the id's or the fact that there can not be two bottom navigations in one layout but I can't help myself any other way and I can't tell where the first id of the first bottom navigation is coming from, because it is nowhere declared and if I'm using one of the id's I used in the xml's the app crashes and I am getting trhe same fatal (axception that tells me the reference is on a null object.
okay so update: I found the correct id. Apparently there have been two existing main.xml files and I had to delete one, but now I am only getting one of the bottom navigations, no matter what user (wether searching person or photographer) is logged in. The question is still, how can I separate them?
Here is the updated xml:
<androidx.constraintlayout.widget.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:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#E8E8E8">
<FrameLayout
android:id="#+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/BottomNavMenu"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center"
android:layout_margin="30dp"
android:background="#drawable/buttom_bg"
android:elevation="2dp"
app:itemIconSize="30dp"
app:itemIconTint="#drawable/item_selector"
app:itemRippleColor="#android:color/transparent"
app:labelVisibilityMode="unlabeled"
app:menu="#menu/bottom_nav_menu"
tools:ignore="MissingConstraints">
</com.google.android.material.bottomnavigation.BottomNavigationView>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNavFoto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_margin="30dp"
android:background="#drawable/buttom_bg"
android:elevation="2dp"
app:itemIconSize="30dp"
app:itemIconTint="#drawable/item_selector"
app:itemRippleColor="#android:color/transparent"
app:labelVisibilityMode="unlabeled"
app:layout_constraintBottom_toBottomOf="#+id/frameLayout"
app:menu="#menu/bottom_nav_fotograf"
tools:ignore="MissingConstraints"
tools:layout_editor_absoluteX="30dp"></com.google.android.material.bottomnavigation.BottomNavigationView>
</androidx.constraintlayout.widget.ConstraintLayout>
Okay, I managed it by outsourcing the bottom navigations in new activities and starting those in the if-clause of the main activity.kt with new layouts.
I have created a To do List app with a Floating Actin Button and my code is returning three errors:
Expecting ')'
Expecting an Element
Unresolved Reference fab
The code was fine until I decided to add another button to the bottom of my activity_main.xml file and needed to add a relativelayout inside a coordinator layout to do it. The new button is to allow users to change the colour of the background. Once adding this code into the MainActivity.kt file the original findViewById code for the fab no longer works and gives the above errors.
MainActivity.kt file
abstract class MainActivity : AppCompatActivity() ,UpdateAndDelete {
private lateinit var database: DatabaseReference
var toDoList: MutableList<ToDoModel>? = null
lateinit var adapter: ToDoAdapter
private var listViewItem : ListView?=null
internal abstract var screenView:View
internal abstract var clickMe:Button
internal abstract var color:Array<Int>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
intArrayOf(Color.MAGENTA, Color.YELLOW, Color.BLUE, Color.BLACK)
screenView = findViewById(R.id.rView)
clickMe = findViewById(R.id.colorButton) as Button
clickMe.setOnClickListener(object:View.OnClickListener {
override fun onClick(view: View) {
val aryLength = color.size
val random = Random
val rNum = random.nextInt(aryLength)
screenView.setBackgroundColor(color[rNum])
}
}
val fab: View = findViewById(R.id.fab)
listViewItem = findViewById<ListView>(R.id.item_listView)
database = FirebaseDatabase.getInstance().reference
fab.setOnClickListener { view ->
val alertDialog = AlertDialog.Builder(this)
val textEditText = EditText (this)
alertDialog.setMessage("Add TODO Item")
alertDialog.setTitle("Enter TO DO Item")
alertDialog.setView(textEditText)
alertDialog.setPositiveButton("Add") {dialog, i ->
val todoItemData = ToDoModel.createList()
todoItemData.itemDataText = textEditText.text.toString()
todoItemData.done = false
val newItemData=database.child("todo").push()
todoItemData.UID = newItemData.key
newItemData.setValue(todoItemData)
dialog.dismiss()
Toast.makeText(this, "item saved", Toast.LENGTH_LONG).show()
}
alertDialog.show()
}
activity_main.xml file
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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"
android:background="#000000"
tools:context=".MainActivity">
<ListView
android:id="#+id/item_listView"
android:layout_width="match_parent"
android:layout_height="651dp"
android:background="#color/white"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:scrollbars="none" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:layout_gravity="bottom|end"
android:elevation="6dp"
app:pressedTranslationZ="12dp"
android:src="#drawable/ic_baseline_add_24" />
<RelativeLayout
android:id="#+id/rView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:gravity="bottom">
<Button
android:id="#+id/colorButton"
android:layout_width="170dp"
android:layout_height="58dp"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="true"
android:layout_marginStart="22dp"
android:layout_marginBottom="11dp"
android:backgroundTint="#color/teal_200"
android:text="Change Colour"
android:textColor="#color/black" />
</RelativeLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Looking at this bit of your code:
clickMe.setOnClickListener(object:View.OnClickListener {
override fun onClick(view: View) {
val aryLength = color.size
val random = Random
val rNum = random.nextInt(aryLength)
screenView.setBackgroundColor(color[rNum])
}
}
val fab: View = findViewById(R.id.fab)
You are getting the first error because you are not properly closing the call to clickMe.setOnClickListener by providing a ) after the } on the second to last line. The compiler realizes this on the last line that defines fab, and so it is that line that the compiler is actually complaining about.
To fix this, add a ) to the second to last line, like this:
clickMe.setOnClickListener(object:View.OnClickListener {
override fun onClick(view: View) {
val aryLength = color.size
val random = Random
val rNum = random.nextInt(aryLength)
screenView.setBackgroundColor(color[rNum])
}
})
val fab: View = findViewById(R.id.fab)
Once you have an initial syntax error, it doesn't really matter what other errors the compiler is producing. Fix this first error and re-evaluate where you're at.
If the code you supply is supposed to be complete...that is, the entire contents of the file MainActivity.kt is provided, then you are missing a number of closing curlies (}) at the end of the code.
I am trying to learn Kotlin and Android Studio by following a tutorial in Java that creates a MediaPlayer and plays a wave file. I am trying to adapt the code to Kotlin:
MainActivity.kt:
package com.example.debugwaveres
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.content.Context
import android.media.MediaPlayer
import android.view.View
//class MainActivity(private val context: Context) : AppCompatActivity() {
class MainActivity : AppCompatActivity() {
private var player: MediaPlayer? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
fun play(view: View) {
if (player == null) {
player = MediaPlayer.create(this, R.raw.metro1)
player?.setOnCompletionListener {
//stopPlayer()
}
}
player?.start()
}
}
The .wav resource R.raw.metro1 has been copied to the res/raw resource directory:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:gravity="center"
android:orientation="vertical" >
<Button
android:layout_width="99dp"
android:layout_height="wrap_content"
android:onClick="play"
android:text="Play" />
</LinearLayout>
This compiles fine in Android Studio using an AVD with target Android 9.0, but when I click the play button I get an Exception java.io.IOException: Prepare failed :
04/07 19:36:36: Launching 'app' on Pixel 2 API 28.
$ adb shell am start -n "com.example.debugwaveres/com.example.debugwaveres.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Connected to process 11210 on device 'Pixel_2_API_28 [emulator-5554]'.
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
E/MediaPlayerNative: error (1, -2147483648)
D/MediaPlayer: create failed:
java.io.IOException: Prepare failed.: status=0x1
at android.media.MediaPlayer._prepare(Native Method)
at android.media.MediaPlayer.prepare(MediaPlayer.java:1282)
at android.media.MediaPlayer.create(MediaPlayer.java:983)
at android.media.MediaPlayer.create(MediaPlayer.java:954)
at com.example.debugwaveres.MainActivity.play(MainActivity.kt:18)
at java.lang.reflect.Method.invoke(Native Method)
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:397)
at android.view.View.performClick(View.java:6597)
at android.view.View.performClickInternal(View.java:6574)
at android.view.View.access$3100(View.java:778)
at android.view.View$PerformClick.run(View.java:25885)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
I tried your code. It works fine. But you can try like this:
fun play(view : View) {
if (player == null) {
player = MediaPlayer.create(this, R.raw.metro1)
player?.setOnCompletionListener {
//stopPlayer()
}
}
player?.setOnPreparedListener {
it.start()
}
}
Here is the new logcat of the error, I do not understand what it is about I can't seem to figure out this error
11-25 15:56:18.773 6776-6776/com.example.ghost.prochat E/UncaughtException: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.ghost.prochat/com.example.ghost.prochat.MainActivity}: android.view.InflateException: Binary XML file line #2: Error inflating class
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2204)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2254)
at android.app.ActivityThread.access$600(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5069)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.view.InflateException: Binary XML file line #2: Error inflating class
at android.view.LayoutInflater.createView(LayoutInflater.java:613)
at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
at android.view.LayoutInflater.onCreateView(LayoutInflater.java:660)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:685)
at android.view.LayoutInflater.inflate(LayoutInflater.java:466)
at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
at android.support.v7.app.AppCompatDelegateImplV9.setContentView(AppCompatDelegateImplV9.java:284)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:140)
at com.example.ghost.prochat.MainActivity.onCreate(MainActivity.java:56)
at android.app.Activity.performCreate(Activity.java:5104)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1092)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2148)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2254)
at android.app.ActivityThread.access$600(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5069)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.constructNative(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
at android.view.LayoutInflater.createView(LayoutInflater.java:587)
at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
at android.view.LayoutInflater.onCreateView(LayoutInflater.java:660)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:685)
at android.view.LayoutInflater.inflate(LayoutInflater.java:466)
at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
at android.support.v7.app.AppCompatDelegateImplV9.setContentView(AppCompatDelegateImplV9.java:284)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:140)
at com.example.ghost.prochat.MainActivity.onCreate(MainActivity.java:56)
at android.app.Activity.performCreate(Activity.java:5104)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1092)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2148)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2254)
at android.app.ActivityThread.access$600(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5069)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.UnsupportedOperationException: Can't convert to dimension: type=0x1
at android.content.res.TypedArray.getDimensionPixelSize(TypedArray.java:463)
at android.view.View.(View.java:3340)
at android.view.ViewGroup.(ViewGroup.java:431)
at android.widget.LinearLayout.(LinearLayout.java:176)
at android.widget.LinearLayout.(LinearLayout.java:172)
at java.lang.reflect.Constructor.constructNative(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
at android.view.LayoutInflater.createView(LayoutInflater.java:587)
at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
at android.view.LayoutInflater.onCreateView(LayoutInflater.java:660)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:685)
at android.view.LayoutInflater.inflate(LayoutInflater.java:466)
at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
at android.support.v7.app.AppCompatDelegateImplV9.setContentView(AppCompatDelegateImplV9.java:284)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:140)
at com.example.ghost.prochat.MainActivity.onCreate(MainActivity.java:56)
at android.app.Activity.performCreate(Activity.java:5104)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1092)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2148)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2254)
at android.app.ActivityThread.access$600(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5069)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
my mainActivity is as follows
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
//defining view objects
private EditText editTextEmail;
private EditText displayUsername;
private EditText editTextPassword;
private Button buttonSignup;
private TextView textViewSignin;
private ProgressDialog progressDialog;
//defining firebaseauth object
private FirebaseAuth firebaseAuth;
/**
* ATTENTION: This was auto-generated to implement the App Indexing API.
* See https://g.co/AppIndexing/AndroidStudio for more information.
*/
private GoogleApiClient client;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//initializing firebase auth object
firebaseAuth = FirebaseAuth.getInstance();
//if getCurrentUser does not returns null
if (firebaseAuth.getCurrentUser() != null) {
//that means user is already logged in
//so close this activity
finish();
//and open profile activity
startActivity(new Intent(getApplicationContext(), ProfileActivity.class));
}
//initializing views
editTextEmail = (EditText) findViewById(R.id.editTextEmail);
displayUsername = (EditText) findViewById(R.id.displayUsername);
editTextPassword = (EditText) findViewById(R.id.editTextPassword);
textViewSignin = (TextView) findViewById(R.id.textViewSignin);
buttonSignup = (Button) findViewById(R.id.buttonSignup);
progressDialog = new ProgressDialog(this);
//attaching listener to button
buttonSignup.setOnClickListener(this);
textViewSignin.setOnClickListener(this);
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
}
private void registerUser() {
//getting email and password from edit texts
String email = editTextEmail.getText().toString().trim();
String password = editTextPassword.getText().toString().trim();
//checking if email and passwords are empty
if (TextUtils.isEmpty(email)) {
Toast.makeText(this, "Please enter email", Toast.LENGTH_LONG).show();
return;
}
if (TextUtils.isEmpty(password)) {
Toast.makeText(this, "Please enter password", Toast.LENGTH_LONG).show();
return;
}
//if the email and password are not empty
//displaying a progress dialog
progressDialog.setMessage("Registering Please Wait...");
progressDialog.show();
//creating a new user
firebaseAuth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
//checking if success
if (task.isSuccessful()) {
finish();
final FirebaseUser user = task.getResult().getUser();
UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder()
.setDisplayName(String.valueOf(displayUsername))
.setPhotoUri(Uri.parse("https://example.com/jane-q-user/profile.png"))
.build();
user.updateProfile(profileUpdates);
FirebaseDatabase.getInstance().getReference("users").child(user.getUid()).setValue(UserList.user);
startActivity(new Intent(getApplicationContext(), ProfileActivity.class));
} else {
//display some message here
Toast.makeText(MainActivity.this, "Registration Error", Toast.LENGTH_LONG).show();
}
progressDialog.dismiss();
}
});
}
#Override
public void onClick(View view) {
if (view == buttonSignup) {
registerUser();
}
if (view == textViewSignin) {
//open login activity when user taps on the already registered textview
startActivity(new Intent(this, LoginActivity.class));
}
}
/**
* ATTENTION: This was auto-generated to implement the App Indexing API.
* See https://g.co/AppIndexing/AndroidStudio for more information.
*/
public Action getIndexApiAction() {
Thing object = new Thing.Builder()
.setName("Main Page") // TODO: Define a title for the content shown.
// TODO: Make sure this auto-generated URL is correct.
.setUrl(Uri.parse("http://[ENTER-YOUR-URL-HERE]"))
.build();
return new Action.Builder(Action.TYPE_VIEW)
.setObject(object)
.setActionStatus(Action.STATUS_TYPE_COMPLETED)
.build();
}
#Override
public void onStart() {
super.onStart();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client.connect();
AppIndex.AppIndexApi.start(client, getIndexApiAction());
}
#Override
public void onStop() {
super.onStop();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
AppIndex.AppIndexApi.end(client, getIndexApiAction());
client.disconnect();
}
}
my main.activity is here, i cant see any errors
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/head"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.example.ghost.prochat.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="User Registration"
android:id="#+id/textView"
android:layout_gravity="center_horizontal" />
<EditText
android:id="#+id/displayUsername"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:hint="Username"
android:inputType="textEmailAddress" />
<EditText
android:id="#+id/editTextEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:hint="Enter email"
android:inputType="textEmailAddress" />
<EditText
android:id="#+id/editTextPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:hint="Enter password"
android:inputType="textPassword" />
<Button
android:id="#+id/buttonSignup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:text="Signup" />
<TextView
android:text="Already Registered? Signin Here"
android:id="#+id/textViewSignin"
android:textAlignment="center"
android:layout_margin="15dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
Your crash is caused by the following:
Caused by: java.lang.UnsupportedOperationException: Can't convert to
dimension: type=0x1 at
android.content.res.TypedArray.getDimensionPixelSize
So the problem is in one of your dimensions:
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
I can guess, that you used wrong dimension type, e.g. sp instead of dp
Here is how a right dimension should look:
<dimen name="activity_vertical_margin">36dp</dimen>
Also please ensure your dimension is defined in an xml in the valuesfolder as it mentioned in this answer