1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-21 14:57:09 +00:00

Make use of activity-alias as the launcher mechanism for the Godot editor and the Godot app template

This commit is contained in:
Fredia Huya-Kouadio
2025-11-06 11:30:07 -08:00
parent e47fb8b898
commit 2ed51e00a1
14 changed files with 391 additions and 81 deletions

View File

@@ -35,9 +35,11 @@ configurations {
dependencies {
// Android instrumented test dependencies
androidTestImplementation "androidx.test.ext:junit:1.3.0"
androidTestImplementation "androidx.test.espresso:espresso-core:3.7.0"
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:1.3.11"
androidTestImplementation "androidx.test.ext:junit:$versions.junitVersion"
androidTestImplementation "androidx.test.espresso:espresso-core:$versions.espressoCoreVersion"
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$versions.kotlinTestVersion"
androidTestImplementation "androidx.test:runner:$versions.testRunnerVersion"
androidTestUtil "androidx.test:orchestrator:$versions.testOrchestratorVersion"
implementation "androidx.fragment:fragment:$versions.fragmentVersion"
implementation "androidx.core:core-splashscreen:$versions.splashscreenVersion"
@@ -121,6 +123,15 @@ android {
missingDimensionStrategy 'products', 'template'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
// The following argument makes the Android Test Orchestrator run its
// "pm clear" command after each test invocation. This command ensures
// that the app's state is completely cleared between tests.
testInstrumentationRunnerArguments clearPackageData: 'true'
}
testOptions {
execution 'ANDROIDX_TEST_ORCHESTRATOR'
}
lintOptions {

View File

@@ -15,8 +15,12 @@ ext.versions = [
// Also update 'platform/android/detect.py#get_ndk_version()' when this is updated.
ndkVersion : '28.1.13356709',
splashscreenVersion: '1.0.1',
openxrVendorsVersion: '4.1.1-stable'
openxrVendorsVersion: '4.1.1-stable',
junitVersion : '1.3.0',
espressoCoreVersion: '3.7.0',
kotlinTestVersion : '1.3.11',
testRunnerVersion : '1.7.0',
testOrchestratorVersion: '1.6.1',
]
ext.getExportPackageName = { ->

View File

@@ -30,15 +30,19 @@
package com.godot.game
import android.content.ComponentName
import android.content.Intent
import android.util.Log
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.core.app.ActivityScenario
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.godot.game.test.GodotAppInstrumentedTestPlugin
import org.godotengine.godot.GodotActivity.Companion.EXTRA_COMMAND_LINE_PARAMS
import org.godotengine.godot.plugin.GodotPluginRegistry
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertNull
import kotlin.test.assertTrue
/**
@@ -49,28 +53,94 @@ class GodotAppTest {
companion object {
private val TAG = GodotAppTest::class.java.simpleName
}
@get:Rule
val godotAppRule = ActivityScenarioRule(GodotApp::class.java)
private const val GODOT_APP_LAUNCHER_CLASS_NAME = "com.godot.game.GodotAppLauncher"
private const val GODOT_APP_CLASS_NAME = "com.godot.game.GodotApp"
private val TEST_COMMAND_LINE_PARAMS = arrayOf("This is a test")
}
/**
* Runs the JavaClassWrapper tests via the GodotAppInstrumentedTestPlugin.
*/
@Test
fun runJavaClassWrapperTests() {
val testPlugin = GodotPluginRegistry.getPluginRegistry()
.getPlugin("GodotAppInstrumentedTestPlugin") as GodotAppInstrumentedTestPlugin?
assertNotNull(testPlugin)
ActivityScenario.launch(GodotApp::class.java).use { scenario ->
scenario.onActivity { activity ->
val testPlugin = GodotPluginRegistry.getPluginRegistry()
.getPlugin("GodotAppInstrumentedTestPlugin") as GodotAppInstrumentedTestPlugin?
assertNotNull(testPlugin)
Log.d(TAG, "Waiting for the Godot main loop to start...")
testPlugin.waitForGodotMainLoopStarted()
Log.d(TAG, "Waiting for the Godot main loop to start...")
testPlugin.waitForGodotMainLoopStarted()
Log.d(TAG, "Running JavaClassWrapper tests...")
val result = testPlugin.runJavaClassWrapperTests()
assertNotNull(result)
result.exceptionOrNull()?.let { throw it }
assertTrue(result.isSuccess)
Log.d(TAG, "Passed ${result.getOrNull()} tests")
Log.d(TAG, "Running JavaClassWrapper tests...")
val result = testPlugin.runJavaClassWrapperTests()
assertNotNull(result)
result.exceptionOrNull()?.let { throw it }
assertTrue(result.isSuccess)
Log.d(TAG, "Passed ${result.getOrNull()} tests")
}
}
}
/**
* Test implicit launch of the Godot app, and validates this resolves to the `GodotAppLauncher` activity alias.
*/
@Test
fun testImplicitGodotAppLauncherLaunch() {
val implicitLaunchIntent = Intent().apply {
setPackage(BuildConfig.APPLICATION_ID)
action = Intent.ACTION_MAIN
addCategory(Intent.CATEGORY_LAUNCHER)
putExtra(EXTRA_COMMAND_LINE_PARAMS, TEST_COMMAND_LINE_PARAMS)
}
ActivityScenario.launch<GodotApp>(implicitLaunchIntent).use { scenario ->
scenario.onActivity { activity ->
assertEquals(activity.intent.component?.className, GODOT_APP_LAUNCHER_CLASS_NAME)
val commandLineParams = activity.intent.getStringArrayExtra(EXTRA_COMMAND_LINE_PARAMS)
assertNull(commandLineParams)
}
}
}
/**
* Test explicit launch of the Godot app via its activity-alias launcher, and validates it resolves properly.
*/
@Test
fun testExplicitGodotAppLauncherLaunch() {
val explicitIntent = Intent().apply {
component = ComponentName(BuildConfig.APPLICATION_ID, GODOT_APP_LAUNCHER_CLASS_NAME)
putExtra(EXTRA_COMMAND_LINE_PARAMS, TEST_COMMAND_LINE_PARAMS)
}
ActivityScenario.launch<GodotApp>(explicitIntent).use { scenario ->
scenario.onActivity { activity ->
assertEquals(activity.intent.component?.className, GODOT_APP_LAUNCHER_CLASS_NAME)
val commandLineParams = activity.intent.getStringArrayExtra(EXTRA_COMMAND_LINE_PARAMS)
assertNull(commandLineParams)
}
}
}
/**
* Test explicit launch of the `GodotApp` activity.
*/
@Test
fun testExplicitGodotAppLaunch() {
val explicitIntent = Intent().apply {
component = ComponentName(BuildConfig.APPLICATION_ID, GODOT_APP_CLASS_NAME)
putExtra(EXTRA_COMMAND_LINE_PARAMS, TEST_COMMAND_LINE_PARAMS)
}
ActivityScenario.launch<GodotApp>(explicitIntent).use { scenario ->
scenario.onActivity { activity ->
assertEquals(activity.intent.component?.className, GODOT_APP_CLASS_NAME)
val commandLineParams = activity.intent.getStringArrayExtra(EXTRA_COMMAND_LINE_PARAMS)
assertNotNull(commandLineParams)
assertTrue(commandLineParams.contentEquals(TEST_COMMAND_LINE_PARAMS))
}
}
}
}

View File

@@ -31,23 +31,25 @@
<activity
android:name=".GodotApp"
android:label="@string/godot_project_name_string"
android:theme="@style/GodotAppSplashTheme"
android:launchMode="singleInstancePerTask"
android:excludeFromRecents="false"
android:exported="true"
android:exported="false"
android:screenOrientation="landscape"
android:windowSoftInputMode="adjustResize"
android:configChanges="layoutDirection|locale|orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
android:resizeableActivity="false"
tools:ignore="UnusedAttribute" >
tools:ignore="UnusedAttribute" />
<activity-alias
android:name=".GodotAppLauncher"
android:targetActivity=".GodotApp"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</activity-alias>
</application>