[Android] Fix handling of back navigation when targeting API level 36
This commit is contained in:
+55
@@ -34,8 +34,11 @@ import android.content.ComponentName
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
import androidx.test.core.app.ActivityScenario
|
||||
import androidx.test.espresso.Espresso
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import com.godot.game.test.GodotAppInstrumentedTestPlugin
|
||||
import org.godotengine.godot.Godot
|
||||
import org.godotengine.godot.GodotActivity.Companion.EXTRA_COMMAND_LINE_PARAMS
|
||||
import org.godotengine.godot.plugin.GodotPluginRegistry
|
||||
import org.junit.Test
|
||||
@@ -169,4 +172,56 @@ class GodotAppTest {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that the back press does not quit the game when 'quit_on_go_back' is disabled.
|
||||
*/
|
||||
@Test
|
||||
fun testGameNotQuittingOnBackPress() {
|
||||
ActivityScenario.launch(GodotApp::class.java).use { scenario ->
|
||||
val testPlugin = getTestPlugin()
|
||||
assertNotNull(testPlugin)
|
||||
|
||||
Log.d(TAG, "Waiting for the Godot main loop to start...")
|
||||
testPlugin.waitForGodotMainLoopStarted()
|
||||
|
||||
// Disable 'quit_on_go_back'.
|
||||
testPlugin.updateQuitOnGoBack(false)
|
||||
|
||||
// Trigger the back press event.
|
||||
Espresso.pressBackUnconditionally()
|
||||
|
||||
Log.d(TAG, "Waiting for the engine to terminate...")
|
||||
testPlugin.waitForEngineTermination(5_000L)
|
||||
|
||||
val godot = Godot.getInstance(InstrumentationRegistry.getInstrumentation().targetContext)
|
||||
assertTrue { godot.runStatus != Godot.RunStatus.TERMINATING }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that the back press event quits the game when 'quit_on_go_back' is enabled.
|
||||
*/
|
||||
@Test
|
||||
fun testGameQuittingOnBackPress() {
|
||||
ActivityScenario.launch(GodotApp::class.java).use { scenario ->
|
||||
val testPlugin = getTestPlugin()
|
||||
assertNotNull(testPlugin)
|
||||
|
||||
Log.d(TAG, "Waiting for the Godot main loop to start...")
|
||||
testPlugin.waitForGodotMainLoopStarted()
|
||||
|
||||
// Enable 'quit_on_go_back'.
|
||||
testPlugin.updateQuitOnGoBack(true)
|
||||
|
||||
// Trigger the back press event.
|
||||
Espresso.pressBackUnconditionally()
|
||||
|
||||
Log.d(TAG, "Waiting for the engine to terminate...")
|
||||
testPlugin.waitForEngineTermination(5_000L)
|
||||
|
||||
val godot = Godot.getInstance(InstrumentationRegistry.getInstrumentation().targetContext)
|
||||
assertTrue { godot.runStatus == Godot.RunStatus.TERMINATING }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ func _ready():
|
||||
if Engine.has_singleton(_plugin_name):
|
||||
_android_plugin = Engine.get_singleton(_plugin_name)
|
||||
_android_plugin.connect("launch_tests", _launch_tests)
|
||||
_android_plugin.connect("update_quit_on_go_back", _update_quit_on_go_back)
|
||||
else:
|
||||
printerr("Couldn't find plugin " + _plugin_name)
|
||||
get_tree().quit()
|
||||
@@ -28,6 +29,10 @@ func _launch_tests(test_label: String) -> void:
|
||||
_android_plugin.onTestsFailed(test_label, "Unable to launch tests")
|
||||
|
||||
|
||||
func _update_quit_on_go_back(quit_on_go_back: bool) -> void:
|
||||
get_tree().quit_on_go_back = quit_on_go_back
|
||||
|
||||
|
||||
func _on_plugin_toast_button_pressed() -> void:
|
||||
if _android_plugin:
|
||||
_android_plugin.helloWorld()
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ func run_tests():
|
||||
|
||||
# Scoped storage: Testing access to Downloads and Documents directory.
|
||||
var version = JavaClassWrapper.wrap("android.os.Build$VERSION")
|
||||
if version.SDK_INT >= 29:
|
||||
if version.SDK_INT >= 30:
|
||||
__exec_test(test_downloads_dir_access)
|
||||
__exec_test(test_documents_dir_access)
|
||||
|
||||
|
||||
+26
-2
@@ -38,6 +38,7 @@ import org.godotengine.godot.plugin.UsedByGodot
|
||||
import org.godotengine.godot.plugin.SignalInfo
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* [GodotPlugin] used to drive instrumented tests.
|
||||
@@ -47,14 +48,17 @@ class GodotAppInstrumentedTestPlugin(godot: Godot) : GodotPlugin(godot) {
|
||||
companion object {
|
||||
private val TAG = GodotAppInstrumentedTestPlugin::class.java.simpleName
|
||||
private const val MAIN_LOOP_STARTED_LATCH_KEY = "main_loop_started_latch"
|
||||
private const val ENGINE_TERMINATING_LATCH_KEY = "engine_terminating_latch"
|
||||
|
||||
private const val JAVACLASSWRAPPER_TESTS = "javaclasswrapper_tests"
|
||||
private const val FILE_ACCESS_TESTS = "file_access_tests"
|
||||
|
||||
private val LAUNCH_TESTS_SIGNAL = SignalInfo("launch_tests", String::class.java)
|
||||
private val UPDATE_QUIT_ON_GO_BACK_SIGNAL = SignalInfo("update_quit_on_go_back", java.lang.Boolean::class.java)
|
||||
|
||||
private val SIGNALS = setOf(
|
||||
LAUNCH_TESTS_SIGNAL
|
||||
LAUNCH_TESTS_SIGNAL,
|
||||
UPDATE_QUIT_ON_GO_BACK_SIGNAL
|
||||
)
|
||||
}
|
||||
|
||||
@@ -65,6 +69,8 @@ class GodotAppInstrumentedTestPlugin(godot: Godot) : GodotPlugin(godot) {
|
||||
// Add a countdown latch that is triggered when `onGodotMainLoopStarted` is fired.
|
||||
// This will be used by tests to wait until the engine is ready.
|
||||
latches[MAIN_LOOP_STARTED_LATCH_KEY] = CountDownLatch(1)
|
||||
// Add a countdown latch that is triggered when the engine terminates.
|
||||
latches[ENGINE_TERMINATING_LATCH_KEY] = CountDownLatch(1)
|
||||
}
|
||||
|
||||
override fun getPluginName() = "GodotAppInstrumentedTestPlugin"
|
||||
@@ -76,6 +82,11 @@ class GodotAppInstrumentedTestPlugin(godot: Godot) : GodotPlugin(godot) {
|
||||
latches.remove(MAIN_LOOP_STARTED_LATCH_KEY)?.countDown()
|
||||
}
|
||||
|
||||
override fun onGodotTerminating() {
|
||||
super.onGodotTerminating()
|
||||
latches.remove(ENGINE_TERMINATING_LATCH_KEY)?.countDown()
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by the instrumented test to wait until the Godot main loop is up and running.
|
||||
*/
|
||||
@@ -88,6 +99,19 @@ class GodotAppInstrumentedTestPlugin(godot: Godot) : GodotPlugin(godot) {
|
||||
}
|
||||
}
|
||||
|
||||
internal fun waitForEngineTermination(timeoutInMs: Long) {
|
||||
// Wait on the CountDownLatch for `onGodotTerminating`.
|
||||
try {
|
||||
latches[ENGINE_TERMINATING_LATCH_KEY]?.await(timeoutInMs, TimeUnit.MILLISECONDS)
|
||||
} catch (e: InterruptedException) {
|
||||
Log.e(TAG, "Unable to wait for engine termination event.", e)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun updateQuitOnGoBack(quitOnGoBack: Boolean) {
|
||||
emitSignal(UPDATE_QUIT_ON_GO_BACK_SIGNAL, quitOnGoBack)
|
||||
}
|
||||
|
||||
/**
|
||||
* This launches the JavaClassWrapper tests, and wait until the tests are complete before returning.
|
||||
*/
|
||||
@@ -104,7 +128,7 @@ class GodotAppInstrumentedTestPlugin(godot: Godot) : GodotPlugin(godot) {
|
||||
|
||||
private fun launchTests(testLabel: String): Result<Any>? {
|
||||
val latch = latches.getOrPut(testLabel) { CountDownLatch(1) }
|
||||
emitSignal(LAUNCH_TESTS_SIGNAL.name, testLabel)
|
||||
emitSignal(LAUNCH_TESTS_SIGNAL, testLabel)
|
||||
return try {
|
||||
latch.await()
|
||||
val result = testResults.remove(testLabel)
|
||||
|
||||
Reference in New Issue
Block a user