Fix Android products arriving in GDScript as an opaque JavaObject#13
Open
DiplomaticRobot wants to merge 1 commit into
Open
Fix Android products arriving in GDScript as an opaque JavaObject#13DiplomaticRobot wants to merge 1 commit into
DiplomaticRobot wants to merge 1 commit into
Conversation
fetch_products emitted the products list as a java.util.ArrayList. Godot's Android JNI (jni_utils.cpp _jobject_to_variant) converts "[Ljava.lang.Object;", "[Ljava.lang.String;", and Dictionary/HashMap, but has no case for java.util.ArrayList/List — so the list reaches GDScript as an opaque JavaObject whose .get(i) returns null, and products/prices never load on Android. Emit an Object[] (arrayOfNulls<Any>) instead; the JNI converts it to a Godot Array, recursing into each Dictionary element. Note Array<Dictionary> does not work: the JNI check is an exact match on "[Ljava.lang.Object;", and Dictionary[] is "[Lorg.godotengine.godot.Dictionary;". Verified on-device (Godot 4.6.2, RevenueCat 10.1.2).
paulocoutinhox
requested changes
Jun 3, 2026
| val result = Dictionary() | ||
| result["products"] = ArrayList<Dictionary>() | ||
| // Empty Object[] (not ArrayList) — see the onGetStoreProducts note below. | ||
| result["products"] = arrayOfNulls<Any>(0) |
Contributor
There was a problem hiding this comment.
result["products"] = emptyArray()
| onError = { error -> | ||
| val result = Dictionary() | ||
| result["products"] = ArrayList<Dictionary>() | ||
| // Empty Object[] (not ArrayList) — see the onGetStoreProducts note below. |
Contributor
There was a problem hiding this comment.
remove unnecessary comments
| onGetStoreProducts = { products -> | ||
| val list = ArrayList<Dictionary>() | ||
|
|
||
| // Emit the products as an Object[] of Dictionary, NOT a java.util.ArrayList. |
Contributor
There was a problem hiding this comment.
remove unnecessary comments (279-288)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On Android,
fetch_productsnever delivers usable products to GDScript. The price/products silently fail to load even though RevenueCat returns the product correctly.The
productssignal emits the list as ajava.util.ArrayList<Dictionary>. Godot's Android JNI converter (platform/android/jni_utils.cpp,_jobject_to_variant) has conversion cases for:[Ljava.lang.Object;→Array(recursing into each element)[Ljava.lang.String;→PackedStringArrayorg.godotengine.godot.Dictionary/HashMap→Dictionary…but no case for
java.util.ArrayList/List. So the list reaches GDScript as an opaqueJavaObject, andraw.call("get", i)returnsnull— the product dictionaries are unreachable.Symptom in GDScript:
Fix
Emit the products as an
Object[](arrayOfNulls<Any>) instead of anArrayList. The JNI converts[Ljava.lang.Object;to a GodotArrayand recurses into eachDictionaryelement.Verification
Built and run on a physical device (Godot 4.6.2, RevenueCat 10.1.2, Android arm64). GDScript now receives a typed
Arrayof product dictionaries:Product fetch, purchase, and restore all work end-to-end.
Scope is intentionally limited to this marshalling bug — no behavior or API changes.