Search code examples
androidandroid-studiokotlinandroid-mediaplayer

Why do I get NullPointerException when trying to instantiate Mediaplayer? Android Kotlin


package com.oyly.gpsdemo
import android.content.Context
import android.media.MediaPlayer

class SoundGenerator(context: Context) : MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener {
    private var mediaPlayer:    MediaPlayer = MediaPlayer()
    private var nextSound:      Int = R.raw.coast

    init {
        try { mediaPlayer = MediaPlayer.create(context, R.raw.coast) }
        catch (ex : Exception) { println("lyseoy11: $ex") }
            mediaPlayer.setOnPreparedListener(this)
            mediaPlayer.setOnCompletionListener (this)
    }
        override fun onPrepared(p0: MediaPlayer) {mediaPlayer.start()}
        override fun onCompletion(p0: MediaPlayer?) { playSound() }
        fun queueSound(resid: Int) {
            nextSound = resid
            if (!mediaPlayer.isPlaying) playSound()
        }
        fun playSound() {
            mediaPlayer.reset()
            mediaPlayer.setDataSource(resources.openRawResourceFd(nextSound))
            mediaPlayer.prepareAsync()
        }
}

The "mediaPlayer = MediaPlayer.create(context, R.raw.coast" line throws the following exception:

java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference

I have moved this code from a standalone app, where it worked, into this class of another app. Now it doesn't work and I can't understand why. The MediaPlayer.Create() method takes as arguments the context (which I pass on from the MainActivity class that calls this class), and an uri to the audio file to be played. Neither of them are null.

Why do I get this exception?

Edit:

The only place SoundGenerator is created is in the MainActivity Initializer:

class MainActivity : AppCompatActivity() {
    private             var soundGenerator : SoundGenerator = SoundGenerator(this)
    ...
}

Solution

  • Often it is best to wait to use the activity as a context until later in the lifecycle when things have been set up (e.g. in onCreate) to avoid initialization order issues. For exampe:

    class MainActivity : AppCompatActivity() {
        private lateinit var soundGenerator : SoundGenerator
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            //...
            soundGenerator = SoundGenerator(this)
        }
    }
    

    Alternately, sometimes you can use applicationContext instead of the current activity as an appropriate context.