Skip to content

Commit 2d753ca

Browse files
riccardoblCopilot
andauthored
GLES and Android backend improvements and fixup (#2727)
* android fixup Co-authored-by: Copilot <copilot@github.com> * fix build * fixes Co-authored-by: Copilot <copilot@github.com> * better best depth format detection Co-authored-by: Copilot <copilot@github.com> * fixes and cleanup * support examples autorun Co-authored-by: Copilot <copilot@github.com> * update screenshots --------- Co-authored-by: Copilot <copilot@github.com>
1 parent bb76375 commit 2d753ca

62 files changed

Lines changed: 2998 additions & 2066 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,18 @@ You can optionally use the `-Pexample` property to specify an example to start w
125125
./gradlew runExamples -Pexample=jme3test.light.pbr.TestPBRSimple
126126
```
127127

128+
### Android examples
129+
130+
You can run the Android examples on a local android emulator with:
131+
132+
```bash
133+
./gradlew -PbuildAndroidExamples=true -PbuildNativeProjects=true runAndroidExamples
134+
# or for a specific example:
135+
# ./gradlew -PbuildAndroidExamples=true -PbuildNativeProjects=true runAndroidExamples -Pexample=jme3test.post.TestBloom
136+
```
137+
138+
*Make sure to have the SDK and NDK installed and configured properly, and the emulator running before executing the command.*
139+
128140

129141
## Running Tests
130142

build.gradle

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -182,17 +182,56 @@ task configureAndroidNDK {
182182
ndkBuildFile = "ndk-build.cmd"
183183
}
184184

185-
// ndkPath is defined in the root project gradle.properties file
186-
String ndkBuildPath = ndkPath + File.separator + ndkBuildFile
187-
//Use the environment variable for the NDK location if defined
188-
if (System.env.ANDROID_NDK != null) {
189-
ndkBuildPath = System.env.ANDROID_NDK + File.separator + ndkBuildFile
185+
def ndkCandidates = []
186+
if (System.env.ANDROID_NDK) {
187+
ndkCandidates << file(System.env.ANDROID_NDK)
188+
}
189+
if (System.env.ANDROID_NDK_HOME) {
190+
ndkCandidates << file(System.env.ANDROID_NDK_HOME)
191+
}
192+
if (project.hasProperty('ndkPath') && ndkPath) {
193+
ndkCandidates << file(ndkPath)
190194
}
191195

192-
if (new File(ndkBuildPath).exists()) {
196+
def localProperties = file('local.properties')
197+
if (localProperties.isFile()) {
198+
Properties properties = new Properties()
199+
localProperties.withInputStream { properties.load(it) }
200+
if (properties.getProperty('ndk.dir')) {
201+
ndkCandidates << file(properties.getProperty('ndk.dir'))
202+
}
203+
if (properties.getProperty('sdk.dir')) {
204+
ndkCandidates.addAll(findAndroidNdkDirs(file(properties.getProperty('sdk.dir'))))
205+
}
206+
}
207+
208+
if (System.env.ANDROID_HOME) {
209+
ndkCandidates.addAll(findAndroidNdkDirs(file(System.env.ANDROID_HOME)))
210+
}
211+
if (System.env.ANDROID_SDK_ROOT) {
212+
ndkCandidates.addAll(findAndroidNdkDirs(file(System.env.ANDROID_SDK_ROOT)))
213+
}
214+
ndkCandidates.addAll(findAndroidNdkDirs(file("${System.properties['user.home']}/Android/Sdk")))
215+
216+
def ndkBuildPath = ndkCandidates.collect { new File(it, ndkBuildFile) }.find { it.isFile() }
217+
if (ndkBuildPath != null) {
193218
ndkExists = true
194-
ndkCommandPath = ndkBuildPath
219+
ndkCommandPath = ndkBuildPath.absolutePath
220+
}
221+
}
222+
223+
def findAndroidNdkDirs(File sdkDir) {
224+
def ndkDirs = []
225+
def nestedSdkDir = new File(sdkDir, 'Sdk')
226+
if (nestedSdkDir.isDirectory()) {
227+
ndkDirs.addAll(findAndroidNdkDirs(nestedSdkDir))
228+
}
229+
def sideBySideDir = new File(sdkDir, 'ndk')
230+
if (sideBySideDir.isDirectory()) {
231+
ndkDirs.addAll(sideBySideDir.listFiles()?.findAll { it.isDirectory() }?.sort { a, b -> b.name <=> a.name } ?: [])
195232
}
233+
ndkDirs << new File(sdkDir, 'ndk-bundle')
234+
return ndkDirs
196235
}
197236

198237
gradle.rootProject.ext.set("usePrebuildNatives", buildNativeProjects!="true");

common-android-app.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ version = jmeFullVersion
66
repositories {
77
mavenCentral()
88
maven {
9-
url "http://nifty-gui.sourceforge.net/nifty-maven-repo"
9+
url "https://nifty-gui.sourceforge.net/nifty-maven-repo"
1010
}
1111
}

gradle/jacoco.gradle

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@ reporting {
6161

6262
def jacocoSubprojects = subprojects.findAll { p ->
6363
(p.file("src/main/java").exists() || p.file("src/main/groovy").exists()) &&
64-
(p.file("src/test/java").exists() || p.file("src/test/groovy").exists())
64+
(p.file("src/test/java").exists() || p.file("src/test/groovy").exists()) &&
65+
p.tasks.findByName('test') &&
66+
p.tasks.findByName('jacocoTestReport')
6567
}
6668

6769
dependencies {

gradle/libs.versions.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ spotbugs = "4.9.8"
1111
[libraries]
1212

1313
androidx-annotation = "androidx.annotation:annotation:1.7.1"
14+
androidx-fragment = "androidx.fragment:fragment:1.8.9"
1415
androidx-lifecycle-common = "androidx.lifecycle:lifecycle-common:2.7.0"
1516
android-build-gradle = "com.android.tools.build:gradle:9.1.0"
1617
android-support-appcompat = "com.android.support:appcompat-v7:28.0.0"
18+
androidx-test-runner = "androidx.test:runner:1.7.0"
1719
gradle-git = "org.ajoberstar:gradle-git:1.2.0"
1820
groovy-test = "org.apache.groovy:groovy-test:4.0.31"
1921
gson = "com.google.code.gson:gson:2.13.2"
@@ -23,6 +25,7 @@ jinput = "net.java.jinput:jinput:2.0.9"
2325
jna = "net.java.dev.jna:jna:5.18.1"
2426
jnaerator-runtime = "com.nativelibs4java:jnaerator-runtime:0.12"
2527
junit-bom = "org.junit:junit-bom:5.13.4"
28+
junit4 = "junit:junit:4.13.2"
2629
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter" }
2730
junit-platform-launcher = { module = "org.junit.platform:junit-platform-launcher" }
2831
lwjgl2 = "org.jmonkeyengine:lwjgl:2.9.5"

jme3-android-examples/build.gradle

Lines changed: 102 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
apply plugin: 'com.android.application'
22

3+
def examplesJar = project(':jme3-examples').tasks.named('jar')
4+
35
android {
46
namespace "org.jmonkeyengine.jme3androidexamples"
57
compileSdk 34
@@ -16,12 +18,13 @@ android {
1618
targetSdk 34 // Android 14
1719
versionCode 1
1820
versionName "1.0" // TODO: from settings.gradle
21+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1922
}
2023

2124
buildTypes {
2225
release {
2326
minifyEnabled false
24-
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
27+
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
2528
}
2629
}
2730

@@ -40,23 +43,117 @@ android {
4043
srcDir '../jme3-testdata/src/main/resources'
4144
srcDir '../jme3-examples/src/main/resources'
4245
}
46+
jniLibs {
47+
srcDir '../build/native/openalsoft'
48+
srcDir '../build/native/decode'
49+
srcDir '../build/native/allocator'
50+
}
4351
}
4452
}
4553
}
4654

4755
dependencies {
4856
implementation fileTree(dir: 'libs', include: ['*.jar'])
49-
testImplementation libs.junit4
50-
implementation libs.androidx.appcompat
51-
57+
testImplementation platform(libs.junit.bom)
58+
testImplementation libs.junit.jupiter
59+
testRuntimeOnly libs.junit.platform.launcher
60+
androidTestImplementation libs.junit4
61+
androidTestImplementation libs.androidx.test.runner
62+
implementation libs.androidx.fragment
5263
implementation project(':jme3-core')
5364
implementation project(':jme3-android')
5465
implementation project(':jme3-android-native')
5566
implementation project(':jme3-effects')
5667
implementation project(':jme3-jbullet')
68+
implementation project(':jme3-jogg')
5769
implementation project(':jme3-networking')
5870
implementation project(':jme3-niftygui')
5971
implementation project(':jme3-plugins')
72+
implementation project(':jme3-plugins-json')
73+
implementation project(':jme3-plugins-json-gson')
6074
implementation project(':jme3-terrain')
61-
implementation fileTree(dir: '../jme3-examples/build/libs', include: ['*.jar'], exclude: ['*sources*.*'])
75+
implementation files(examplesJar.flatMap { it.archiveFile })
76+
}
77+
78+
tasks.named('preBuild') {
79+
dependsOn examplesJar
80+
if (buildNativeProjects == "true") {
81+
dependsOn ':jme3-android-native:updatePreCompiledOpenAlSoftLibs'
82+
dependsOn ':jme3-android-native:updatePreCompiledLibs'
83+
dependsOn ':jme3-android-native:updatePreCompiledLibsBufferAllocator'
84+
} else if (skipPrebuildLibraries != "true") {
85+
dependsOn ':jme3-android-native:copyPreCompiledOpenAlSoftLibs'
86+
dependsOn ':jme3-android-native:copyPreCompiledLibs'
87+
dependsOn ':jme3-android-native:copyPreCompiledLibsBufferAllocator'
88+
}
89+
}
90+
91+
tasks.register('installAndroidExamples', Exec) {
92+
group = 'application'
93+
description = 'Install the Android examples selector on a connected emulator or device.'
94+
95+
dependsOn tasks.named('assembleDebug')
96+
97+
doFirst {
98+
def adbExecutable = findAdbExecutable()
99+
if (adbExecutable == null) {
100+
throw new GradleException("ADB not found. Set -Pandroid.sdk.path, ANDROID_HOME, or ANDROID_SDK_ROOT.")
101+
}
102+
def apkFile = layout.buildDirectory.file('outputs/apk/debug/jme3-android-examples-debug.apk').get().asFile
103+
if (!apkFile.isFile()) {
104+
throw new GradleException("Debug APK not found at ${apkFile}.")
105+
}
106+
executable adbExecutable.absolutePath
107+
args 'install', '-r', apkFile.absolutePath
108+
}
109+
}
110+
111+
tasks.register('runAndroidExamples', Exec) {
112+
group = 'application'
113+
description = 'Install and launch Android examples on a connected emulator or device. Use -Pexample=<class> to run a specific test directly.'
114+
115+
dependsOn tasks.named('installAndroidExamples')
116+
117+
doFirst {
118+
def adbExecutable = findAdbExecutable()
119+
if (adbExecutable == null) {
120+
throw new GradleException("ADB not found. Set -Pandroid.sdk.path, ANDROID_HOME, or ANDROID_SDK_ROOT.")
121+
}
122+
executable adbExecutable.absolutePath
123+
124+
def exampleClass = project.findProperty('example')?.toString()?.trim()
125+
if (exampleClass) {
126+
args 'shell', 'am', 'start',
127+
'-n', 'org.jmonkeyengine.jme3androidexamples/.TestActivity',
128+
'--es', 'Selected_App_Class', exampleClass,
129+
'--ez', 'Enable_Mouse_Events', 'true',
130+
'--ez', 'Enable_Joystick_Events', 'false',
131+
'--ez', 'Enable_Key_Events', 'true',
132+
'--ez', 'Verbose_Logging', 'false'
133+
} else {
134+
args 'shell', 'am', 'start',
135+
'-n', 'org.jmonkeyengine.jme3androidexamples/.MainActivity'
136+
}
137+
}
138+
}
139+
140+
def findAdbExecutable() {
141+
def adbName = System.properties['os.name'].toLowerCase().contains('windows') ? 'adb.exe' : 'adb'
142+
def sdkDirs = []
143+
if (project.findProperty('android.sdk.path')) {
144+
sdkDirs << file(project.findProperty('android.sdk.path'))
145+
}
146+
if (System.env.ANDROID_HOME) {
147+
sdkDirs << file(System.env.ANDROID_HOME)
148+
}
149+
if (System.env.ANDROID_SDK_ROOT) {
150+
sdkDirs << file(System.env.ANDROID_SDK_ROOT)
151+
}
152+
sdkDirs << file("${System.properties['user.home']}/Android/Sdk")
153+
154+
def expandedSdkDirs = sdkDirs.collectMany { sdkDir ->
155+
[sdkDir, new File(sdkDir, 'Sdk')]
156+
}.unique { it.absolutePath }
157+
158+
return expandedSdkDirs.collect { new File(new File(it, 'platform-tools'), adbName) }.find { it.isFile() }
62159
}
Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
package org.jmonkeyengine.jme3androidexamples;
22

3-
import android.app.Application;
4-
import android.test.ApplicationTestCase;
3+
import androidx.test.platform.app.InstrumentationRegistry;
4+
import org.junit.Test;
5+
6+
import static org.junit.Assert.assertEquals;
57

68
/**
79
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
810
*/
9-
public class ApplicationTest extends ApplicationTestCase<Application> {
10-
public ApplicationTest() {
11-
super(Application.class);
11+
public class ApplicationTest {
12+
@Test
13+
public void testApplicationPackage() {
14+
String packageName = InstrumentationRegistry.getInstrumentation()
15+
.getTargetContext()
16+
.getPackageName();
17+
assertEquals("org.jmonkeyengine.jme3androidexamples", packageName);
1218
}
13-
}
19+
}

jme3-android-examples/src/main/AndroidManifest.xml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
android:theme="@style/AppTheme">
1010
<activity
1111
android:name=".MainActivity"
12+
android:exported="true"
1213
android:label="@string/app_name"
1314
android:launchMode="singleTask">
1415
<intent-filter>
@@ -19,15 +20,16 @@
1920
</activity>
2021
<activity
2122
android:name=".TestActivity"
23+
android:exported="true"
2224
android:label="@string/app_name"
2325
android:launchMode="singleTask"
2426
android:screenOrientation="landscape">
2527
</activity>
2628
</application>
2729

28-
<!-- Tell the system that you need ES 2.0. -->
30+
<!-- Tell the system that you need ES 3.0. -->
2931
<uses-feature
30-
android:glEsVersion="0x00020000"
32+
android:glEsVersion="0x00030000"
3133
android:required="true"/>
3234

3335
<!-- Tell the system that you need distinct touches (for the zoom gesture). -->
@@ -41,6 +43,7 @@
4143
android:normalScreens="true"
4244
android:smallScreens="true"/>
4345

46+
<uses-permission android:name="android.permission.INTERNET"/>
4447
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
4548
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
4649
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

0 commit comments

Comments
 (0)