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

No good way to tell what type a JObject is #972

Closed
TheLastGimbus opened this issue Feb 27, 2024 · 1 comment
Closed

No good way to tell what type a JObject is #972

TheLastGimbus opened this issue Feb 27, 2024 · 1 comment

Comments

@TheLastGimbus
Copy link

TheLastGimbus commented Feb 27, 2024

Hello!

I'm not sure if there already is some underlying issue about this here, but I will just describe my problem:

As i continiued implementing BroadcastReceivers from #854, i wanted to get all the extras as a Map<String, dynamic> - I know there are already .getIntExtra() ..., which would be very type-safe, but I wanted to make use of Dart3 pattern matching ✨ So i made this:

@Keep
class TheLastUtils() {
    companion object {
        @JvmStatic
        fun getIntentExtras(intent: Intent): Map<String, Any?> {
            val extras = intent.extras
            val map = mutableMapOf<String, Any?>()
            if (extras != null) {
                for (key in extras.keySet()) {
                    map[key] = extras.get(key)
                }
            }
            return map
        }
    }
}
void onReceive(android.Context context, android.Intent intent) {
  // convert to Map<String, JObject>
  final map = android.TheLastUtils.getIntentExtras(intent)
      .map((key, value) => MapEntry(key.toDartString(), value));
  // turn into a record for handi switch-case:
  switch((intent.getAction().toDartString(), map))
    case (
        android.BluetoothAdapter.ACTION_STATE_CHANGED,
        {
          android.BluetoothAdapter.EXTRA_STATE: int state,
          android.BluetoothAdapter.EXTRA_PREVIOUS_STATE: int _,
          // int's didn't match, so i later also tried:
          // ...EXTRA_STATE: JInteger state
          // but also didn't work
        },
    ):
    // later, i catched them with var, and tried to:
    print('obj is:\n'
        'int: ${state is int}\n'
        'bool: ${state is bool}\n'
        'jint: ${state is JInteger}\n'
        'then its: ${state.getClass()} ; ${state.runtimeType} ; ${state.$type}');
    // it printed:
    // obj is:
    // int: false
    // bool: false // ofc
    // jint: false
    // then its: Instance of 'JClass' ; JObject ; Instance of 'JObjectType'

    // also, every time i tried to print(state), it printed the number corretly
    // so, i tried to dangerously:
    final jint = JInteger.fromRef(state.reference);
    // and it worked
    // but also did this:
    final jbool = JBoolean.fromRef(state.reference);
    // and this:
    print(jbool); // 13
    // only this finally crashed:
    print(jint.booleanValue() ? "true" : "falsh");
    // can't call boolean java.lang.Boolean.booleanValue() on instance of java.lang.Integer
}

So as of now, i don't see any way to tell what underlying class a JObject is :(

@HosseinYousefi
Copy link
Member

i don't see any way to tell what underlying class a JObject is

You need to check the runtime type of a Java object by calling IsInstanceOf JNI function. It's easier to expose this functionality outside of Jni.env.IsInstanceOf(obj, clazz) and there is an issue tracking this: #1033.

It's not possible to do pattern matching on Java runtime type of an object.

@HosseinYousefi HosseinYousefi closed this as not planned Won't fix, can't repro, duplicate, stale Apr 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants