Following are snippets of the GameActivity
and GameView
in my project:
GameActivity.kt
class GameActivity : Activity() {
private var gameView: GameView? = null
// We override the oncreate to add the gameview which will be showing the game
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
var display = windowManager.defaultDisplay
val size = Point()
display.getSize(size)
gameView = GameView(this, size)
setContentView(gameView)
}
}
GameView.kt
class GameView(context: Context, private val size: Point) : SurfaceView(context), Runnable {
private val gameThread = Thread(this)
...
private fun prepareLevel() {}
...
private fun update (fps: Long) {
if (RectF.intersects(powerup.position, player.position)) {
Toast.makeText(context, "Powerup intersects", Toast.LENGTH_SHORT).show()
}
}
...
}
The problem is when the intersection happens the code breaks with the following error:
E/AndroidRuntime: FATAL EXCEPTION: Thread-2
Process: com.example.sacredanimals, PID: 3367
java.lang.RuntimeException: Can't toast on a thread that has not called Looper.prepare()
at android.widget.Toast$TN.<init>(Toast.java:390)
at android.widget.Toast.<init>(Toast.java:114)
at android.widget.Toast.makeText(Toast.java:277)
at android.widget.Toast.makeText(Toast.java:267)
at com.example.sacredanimals.GameView.update(GameView.kt:96)
at com.example.sacredanimals.GameView.run(GameView.kt:78)
at java.lang.Thread.run(Thread.java:764)
I did some debugging, and probably the issue is happening because the Toast message should be called on the main thread rather on one of the child threads, as suggested in the link: Can't toast on a thread that has not called Looper.prepare() But, I am unable to resolve this for the case where I want to call the Toast.message from inside SurfaceView
Toast.makeText() should only be called from Main/UI thread. Looper.getMainLooper() helps you to achieve it:
Handler(Looper.getMainLooper()).post {
Toast.makeText(context, "Powerup intersects", Toast.LENGTH_SHORT).show()
}