Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android: Fix JavaClassWrapper so it actually works #96182

Merged
merged 1 commit into from
Sep 3, 2024

Conversation

dsnopek
Copy link
Contributor

@dsnopek dsnopek commented Aug 27, 2024

Currently, JavaClassWrapper has most of the code in order to work, but is missing a bunch of the pieces to connect it all together, and, in fact, doesn't actually do anything. :-)

This PR aims to get it minimally working, so that you can create Java objects and call their methods.

It also allows JavaObjects to be passed as arguments to methods on JNISingletons registered by Godot Android Plugins, and for any unknown objects that are returned from such methods to be turned into JavaObjects.

Here's some example GDScript code:

var LocalDateTime = JavaClassWrapper.wrap("java.time.LocalDateTime")
var DateTimeFormatter = JavaClassWrapper.wrap("java.time.format.DateTimeFormatter")

var datetime = LocalDateTime.now()
var formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss")

print(datetime.format(formatter))

There's still a bunch of things that don't work, namely accessing fields and constants. Also, this code could use some refactoring and clean-up. There's also some amount of code duplication between JavaClassWrapper and JNISingleton.

But this PR doesn't address those things - just getting it minimally working. Further work can be done in follow-up PRs.

@Mickeon
Copy link
Contributor

Mickeon commented Aug 27, 2024

So it's true. I have been ASKING everyone. I have had people reach out to me, asking what these classes actually do because I used to be the only one brave enough to figure it out and you're telling me they did NOT work for who knows how long, potentially since their conception.

@dsnopek dsnopek force-pushed the java-class-wrapper branch from 469cacc to 44712f1 Compare August 27, 2024 20:31
@dsnopek
Copy link
Contributor Author

dsnopek commented Aug 27, 2024

you're telling me they did NOT work for who knows how long, potentially since their conception.

From the look of the code, I get the impression that these classes were partially ported from somewhere else where they were originally working, but the port was never fully finished. And, yeah, looking at the git blame, it's possible they haven't really worked for as long as Godot has been Open Source.

That said, the changes to get them working weren't really all that big :-)

@dsnopek dsnopek force-pushed the java-class-wrapper branch 2 times, most recently from ec49f18 to abd9dbb Compare August 30, 2024 13:10
Copy link
Contributor

@devloglogan devloglogan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have not been able to test this yet, but the code looks good to me!

doc/classes/JavaClass.xml Outdated Show resolved Hide resolved
doc/classes/JavaObject.xml Outdated Show resolved Hide resolved
@dsnopek dsnopek force-pushed the java-class-wrapper branch from abd9dbb to 98b9309 Compare August 30, 2024 20:51
@akien-mga akien-mga modified the milestones: 4.x, 4.4 Aug 31, 2024
doc/classes/JavaObject.xml Outdated Show resolved Hide resolved
@@ -395,10 +409,10 @@ Variant::Type get_jni_type(const String &p_type) {
idx++;
}

return Variant::NIL;
return Variant::OBJECT;
Copy link
Contributor

@m4gr3d m4gr3d Sep 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this assumes we have an object if we don't match any of the other types, correct?
Should it also checks if the type starts with L?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this assumes we have an object if we don't match any of the other types, correct?

Yes

Should it also checks if the type starts with L?

This particular function gets class names (for non-arrays) as plain strings without the L prefix and ; suffix. So, for example, I made a JNISingleton in a Godot Android plugin that takes a java.time.format.DateTimeFormatter as an argument, and this function gets exactly the string "java.time.format.DateTimeFormatter".

@akien-mga akien-mga merged commit 657dc36 into godotengine:master Sep 3, 2024
19 checks passed
@akien-mga
Copy link
Member

Thanks!

@Mickeon
Copy link
Contributor

Mickeon commented Sep 3, 2024

Just as a note, it would be nice to document in prior versions that these classes literally do not work.

@dsnopek
Copy link
Contributor Author

dsnopek commented Sep 3, 2024

Just as a note, it would be nice to document in prior versions that these classes literally do not work.

What form should that take? It could be a "note" in the description of the classes, although, it seems like that could potentially be easy to miss amid the description of what the classes and functions should be doing. Or should we remove the existing descriptions and only have the note? Only Godot 4.3 has full documentation of those classes - in Godot 4.2 and below they are undocumented - so returning to a largely undocumented state for 4.3 could make sense?

@akien-mga
Copy link
Member

Well if they really don't work in 4.3, this is a bugfix and should likely be cherry-picked, instead of documenting that they're useless.

@Mickeon
Copy link
Contributor

Mickeon commented Sep 3, 2024

They haven't worked since their conception. So "this" should be cherrypicked to 3.x as well, which I'm not sure is easier than noting it down.
Also this "bugfix" adds new methods to the API to actually have it work. I thought that for minor releases doing so is not exactly nice practice.

@dsnopek
Copy link
Contributor Author

dsnopek commented Sep 3, 2024

Well if they really don't work in 4.3, this is a bugfix and should likely be cherry-picked, instead of documenting that they're useless.

My first inclination would be to not cherry-pick this. Even though the classes existed, the fact that they didn't really work means this is basically totally new functionality. I feel like it'd be best to go through the usual dev -> beta -> rc process to get testing and shake out bugs.

@akien-mga akien-mga changed the title Fix JavaClassWrapper so it actually works Android: Fix JavaClassWrapper so it actually works Sep 10, 2024
m4gr3d added a commit to m4gr3d/godot that referenced this pull request Sep 26, 2024
The Android plugin implementation is updated to use `JavaClassWrapper` which was fixed in godotengine#96182, thus removing the limitation on supported types.

Note that `JavaClassWrapper` has also been updated in order to only provide access to public methods and constructor to GDScript.
m4gr3d added a commit to m4gr3d/godot that referenced this pull request Sep 26, 2024
The Android plugin implementation is updated to use `JavaClassWrapper` which was fixed in godotengine#96182, thus removing the limitation on supported types.

Note that `JavaClassWrapper` has also been updated in order to only provide access to public methods and constructor to GDScript.
m4gr3d added a commit to m4gr3d/godot that referenced this pull request Sep 26, 2024
The Android plugin implementation is updated to use `JavaClassWrapper` which was fixed in godotengine#96182, thus removing the limitation on supported types.

Note that `JavaClassWrapper` has also been updated in order to only provide access to public methods and constructor to GDScript.
m4gr3d added a commit to m4gr3d/godot that referenced this pull request Sep 26, 2024
The Android plugin implementation is updated to use `JavaClassWrapper` which was fixed in godotengine#96182, thus removing the limitation on supported types.

Note that `JavaClassWrapper` has also been updated in order to only provide access to public methods and constructor to GDScript.
m4gr3d added a commit to m4gr3d/godot that referenced this pull request Sep 26, 2024
The Android plugin implementation is updated to use `JavaClassWrapper` which was fixed in godotengine#96182, thus removing the limitation on supported types.

Note that `JavaClassWrapper` has also been updated in order to only provide access to public methods and constructor to GDScript.
m4gr3d added a commit to m4gr3d/godot that referenced this pull request Sep 26, 2024
The Android plugin implementation is updated to use `JavaClassWrapper` which was fixed in godotengine#96182, thus removing the limitation on supported types.

Note that `JavaClassWrapper` has also been updated in order to only provide access to public methods and constructor to GDScript.
m4gr3d added a commit to m4gr3d/godot that referenced this pull request Sep 26, 2024
Thanks for the fix of `JavaClassWrapper` in godotengine#96182 and the changes in the previous commit, this introduces an `AndroidRuntime` plugin which provides GDScript access to the Android runtime capabilities.

This allows developers to get access to various Android capabilities without the need of a plugin.
For example, the following logic can be used to check whether the device supports vibration:

```
var android_runtime = Engine.get_singleton("AndroidRuntime")
 if android_runtime:
 	print("Checking if the device supports vibration")
 	var vibrator_service = android_runtime.getApplicationContext().getSystemService("vibrator")
 	if vibrator_service:
 		if vibrator_service.hasVibrator():
 			print("Vibration is supported on device!")
 		else:
 			printerr("Vibration is not supported on device")
 	else:
 		printerr("Unable to retrieve the vibrator service")
 else:
 	printerr("Couldn't find AndroidRuntime singleton")
```
m4gr3d added a commit to m4gr3d/godot that referenced this pull request Sep 29, 2024
The Android plugin implementation is updated to use `JavaClassWrapper` which was fixed in godotengine#96182, thus removing the limitation on supported types.

Note that `JavaClassWrapper` has also been updated in order to only provide access to public methods and constructor to GDScript.
m4gr3d added a commit to m4gr3d/godot that referenced this pull request Sep 29, 2024
Thanks for the fix of `JavaClassWrapper` in godotengine#96182 and the changes in the previous commit, this introduces an `AndroidRuntime` plugin which provides GDScript access to the Android runtime capabilities.

This allows developers to get access to various Android capabilities without the need of a plugin.
For example, the following logic can be used to check whether the device supports vibration:

```
var android_runtime = Engine.get_singleton("AndroidRuntime")
 if android_runtime:
 	print("Checking if the device supports vibration")
 	var vibrator_service = android_runtime.getApplicationContext().getSystemService("vibrator")
 	if vibrator_service:
 		if vibrator_service.hasVibrator():
 			print("Vibration is supported on device!")
 		else:
 			printerr("Vibration is not supported on device")
 	else:
 		printerr("Unable to retrieve the vibrator service")
 else:
 	printerr("Couldn't find AndroidRuntime singleton")
```
laurentmackay pushed a commit to metapfhor/godot that referenced this pull request Oct 30, 2024
The Android plugin implementation is updated to use `JavaClassWrapper` which was fixed in godotengine#96182, thus removing the limitation on supported types.

Note that `JavaClassWrapper` has also been updated in order to only provide access to public methods and constructor to GDScript.
laurentmackay pushed a commit to metapfhor/godot that referenced this pull request Oct 30, 2024
Thanks for the fix of `JavaClassWrapper` in godotengine#96182 and the changes in the previous commit, this introduces an `AndroidRuntime` plugin which provides GDScript access to the Android runtime capabilities.

This allows developers to get access to various Android capabilities without the need of a plugin.
For example, the following logic can be used to check whether the device supports vibration:

```
var android_runtime = Engine.get_singleton("AndroidRuntime")
 if android_runtime:
 	print("Checking if the device supports vibration")
 	var vibrator_service = android_runtime.getApplicationContext().getSystemService("vibrator")
 	if vibrator_service:
 		if vibrator_service.hasVibrator():
 			print("Vibration is supported on device!")
 		else:
 			printerr("Vibration is not supported on device")
 	else:
 		printerr("Unable to retrieve the vibrator service")
 else:
 	printerr("Couldn't find AndroidRuntime singleton")
```
JayTropper pushed a commit to JayTropper/godot that referenced this pull request Nov 6, 2024
The Android plugin implementation is updated to use `JavaClassWrapper` which was fixed in godotengine#96182, thus removing the limitation on supported types.

Note that `JavaClassWrapper` has also been updated in order to only provide access to public methods and constructor to GDScript.
JayTropper pushed a commit to JayTropper/godot that referenced this pull request Nov 6, 2024
Thanks for the fix of `JavaClassWrapper` in godotengine#96182 and the changes in the previous commit, this introduces an `AndroidRuntime` plugin which provides GDScript access to the Android runtime capabilities.

This allows developers to get access to various Android capabilities without the need of a plugin.
For example, the following logic can be used to check whether the device supports vibration:

```
var android_runtime = Engine.get_singleton("AndroidRuntime")
 if android_runtime:
 	print("Checking if the device supports vibration")
 	var vibrator_service = android_runtime.getApplicationContext().getSystemService("vibrator")
 	if vibrator_service:
 		if vibrator_service.hasVibrator():
 			print("Vibration is supported on device!")
 		else:
 			printerr("Vibration is not supported on device")
 	else:
 		printerr("Unable to retrieve the vibrator service")
 else:
 	printerr("Couldn't find AndroidRuntime singleton")
```
ChrisBase pushed a commit to ChrisBase/godot that referenced this pull request Nov 15, 2024
The Android plugin implementation is updated to use `JavaClassWrapper` which was fixed in godotengine#96182, thus removing the limitation on supported types.

Note that `JavaClassWrapper` has also been updated in order to only provide access to public methods and constructor to GDScript.
ChrisBase pushed a commit to ChrisBase/godot that referenced this pull request Nov 15, 2024
Thanks for the fix of `JavaClassWrapper` in godotengine#96182 and the changes in the previous commit, this introduces an `AndroidRuntime` plugin which provides GDScript access to the Android runtime capabilities.

This allows developers to get access to various Android capabilities without the need of a plugin.
For example, the following logic can be used to check whether the device supports vibration:

```
var android_runtime = Engine.get_singleton("AndroidRuntime")
 if android_runtime:
 	print("Checking if the device supports vibration")
 	var vibrator_service = android_runtime.getApplicationContext().getSystemService("vibrator")
 	if vibrator_service:
 		if vibrator_service.hasVibrator():
 			print("Vibration is supported on device!")
 		else:
 			printerr("Vibration is not supported on device")
 	else:
 		printerr("Unable to retrieve the vibrator service")
 else:
 	printerr("Couldn't find AndroidRuntime singleton")
```
vgezer pushed a commit to vgezer/godot that referenced this pull request Nov 29, 2024
The Android plugin implementation is updated to use `JavaClassWrapper` which was fixed in godotengine#96182, thus removing the limitation on supported types.

Note that `JavaClassWrapper` has also been updated in order to only provide access to public methods and constructor to GDScript.
vgezer pushed a commit to vgezer/godot that referenced this pull request Nov 29, 2024
Thanks for the fix of `JavaClassWrapper` in godotengine#96182 and the changes in the previous commit, this introduces an `AndroidRuntime` plugin which provides GDScript access to the Android runtime capabilities.

This allows developers to get access to various Android capabilities without the need of a plugin.
For example, the following logic can be used to check whether the device supports vibration:

```
var android_runtime = Engine.get_singleton("AndroidRuntime")
 if android_runtime:
 	print("Checking if the device supports vibration")
 	var vibrator_service = android_runtime.getApplicationContext().getSystemService("vibrator")
 	if vibrator_service:
 		if vibrator_service.hasVibrator():
 			print("Vibration is supported on device!")
 		else:
 			printerr("Vibration is not supported on device")
 	else:
 		printerr("Unable to retrieve the vibrator service")
 else:
 	printerr("Couldn't find AndroidRuntime singleton")
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants