QJniObject.callObjectMethod "getString" on android.os.Bundle Returns "" Despite Bundle.toString() Showing Value
-
wrote on 28 Jan 2023, 17:27 last edited by
I have an android.os.Bundle which is passed to C++ from Java via a native function call. The received object, when printed with .toString() appears to contain all the expected values.
static ReceivedFileDetails fromBundle(QJniObject bundle) { qDebug() << "ReceivedFileDetails::fromBundle" << bundle.toString();
=> ReceivedFileDetails::fromBundle "Bundle[{my.package.aat.Bundle.Flags=50331649, my.package.aat.Bundle.Action=android.intent.action.VIEW, my.package.aat.Bundle.Scheme=content, my.package.aat.Bundle.Subject=null, my.package.aat.Bundle.Uri=content://com.google.android.apps.nbu.files.provider/2/1000001836, my.package.aat.Bundle.Data=content://com.google.android.apps.nbu.files.provider/2/1000001836, my.package.aat.Bundle.Path=null, my.package.aat.Bundle.Text=null, my.package.aat.Bundle.Type=application/octet-stream}]"
But I can't find a way to extract the individual values via QJniObject.callObjectMethod calls, for example:
jstring actionKey = QJniObject::fromString("my.package.aat.Bundle.Action").object<jstring>(); QString action = bundle.callObjectMethod("getString", "(Ljava/lang/String;)Ljava/lang/String;", actionKey).toString(); qDebug() << "action" << action;
=> action ""
The returned value is always "".
Please can anyone tell me what I am doing wrong?Thanks.
-
wrote on 30 Jan 2023, 16:07 last edited by JoeCFD
It may be your Java code is not made properly. Can you show your Java function?
Use new to create the return String in your Java code. -
It may be your Java code is not made properly. Can you show your Java function?
Use new to create the return String in your Java code.wrote on 30 Jan 2023, 18:36 last edited by@JoeCFD
This is the Java code, simplified:// ReceivedFileDetails is a Java class to hold parameters from the Intent public class ReceivedFileDetails { public static final String Action = "my.package.aat.Bundle.Action"; public String mAction; public Bundle getBundle() { Bundle bundle = new Bundle(); if (mAction != null) { bundle.putString(Action, new String(mAction)); } return bundle; } public static native void sendNativeBundle(Bundle bundle); // the native call to pass the Bundle to C++ } // In Activity.onCreate(): mDetails = new ReceivedFileDetails(); mDetails.mAction = getIntent().getAction(); Bundle bundle = mDetails.getBundle(); ReceivedFileDetails.sendNativeBundle(bundle);
When I first posted about this the code to insert the Action into the Bundle did not instantiate a new String. The new code, even with the new String(...) still gives "" for the return value from .Bundle.getString JNI call.
Thanks.
-
wrote on 30 Jan 2023, 18:57 last edited by JoeCFD
Not sure if what you did is right or not. How did you get bundle in in the following Qt code?
QString action = bundle.callObjectMethod("getString", "(Ljava/lang/String;)Ljava/lang/String;", actionKey).toString();
I guess you may not need to pass bundle to Qt code. Instead send back only a string.This is what I did and it works.
auto info_obj = QAndroidJniObject::callStaticObjectMethod( "java class name with path", "static func name", "(Landroid/content/Context;)Ljava/lang/String;", QtAndroid::androidContext().object() ); auto info_str = info_obj.toString();
-
Not sure if what you did is right or not. How did you get bundle in in the following Qt code?
QString action = bundle.callObjectMethod("getString", "(Ljava/lang/String;)Ljava/lang/String;", actionKey).toString();
I guess you may not need to pass bundle to Qt code. Instead send back only a string.This is what I did and it works.
auto info_obj = QAndroidJniObject::callStaticObjectMethod( "java class name with path", "static func name", "(Landroid/content/Context;)Ljava/lang/String;", QtAndroid::androidContext().object() ); auto info_str = info_obj.toString();
wrote on 30 Jan 2023, 19:39 last edited by@JoeCFD
The Bundle comes in effectively like this:static void receivedFileBundle(JNIEnv *env, jobject thiz, jobject jbundle) { QJniObject bundle(jbundle); qDebug() << "receivedFileBundle:" << bundle.toString(); jstring actionKey = QJniObject::fromString("my.package.aat.Bundle.Action").object<jstring>(); QString action = bundle.callObjectMethod("getString", "(Ljava/lang/String;)Ljava/lang/String;", actionKey).toString(); qDebug() << "action" << action; } const JNINativeMethod methods[] { { "sendNativeBundle", "(Landroid/os/Bundle;)V", reinterpret_cast<void *>(aat::ReceivedFileDetailsJavaClass::receivedFileBundle) }, }; sEnv.registerNativeMethods("my/package/aat/ReceivedFileDetails", methods, 1); // Java: In Activity.onCreate(): mDetails = new ReceivedFileDetails(); mDetails.mAction = getIntent().getAction(); Bundle bundle = mDetails.getBundle(); ReceivedFileDetails.sendNativeBundle(bundle);
I have since moved past this passing a String (Json) instead of a Bundle, and it works fine, as you say. But it would be good to know why using a Bundle doesn't work.
I note that "getString" is not a method of android.os.Bundle but of android.os.BaseBundle, but I doubt that that is the reason.
-
@JoeCFD
The Bundle comes in effectively like this:static void receivedFileBundle(JNIEnv *env, jobject thiz, jobject jbundle) { QJniObject bundle(jbundle); qDebug() << "receivedFileBundle:" << bundle.toString(); jstring actionKey = QJniObject::fromString("my.package.aat.Bundle.Action").object<jstring>(); QString action = bundle.callObjectMethod("getString", "(Ljava/lang/String;)Ljava/lang/String;", actionKey).toString(); qDebug() << "action" << action; } const JNINativeMethod methods[] { { "sendNativeBundle", "(Landroid/os/Bundle;)V", reinterpret_cast<void *>(aat::ReceivedFileDetailsJavaClass::receivedFileBundle) }, }; sEnv.registerNativeMethods("my/package/aat/ReceivedFileDetails", methods, 1); // Java: In Activity.onCreate(): mDetails = new ReceivedFileDetails(); mDetails.mAction = getIntent().getAction(); Bundle bundle = mDetails.getBundle(); ReceivedFileDetails.sendNativeBundle(bundle);
I have since moved past this passing a String (Json) instead of a Bundle, and it works fine, as you say. But it would be good to know why using a Bundle doesn't work.
I note that "getString" is not a method of android.os.Bundle but of android.os.BaseBundle, but I doubt that that is the reason.
wrote on 30 Jan 2023, 19:43 last edited by JoeCFD@KenAppleby-0 QJniObject has limited types to handle. Bundle is not one of them. Check out what QJniObject can handle.
Scroll all way down and look for JNI Types
https://doc.qt.io/qt-6/qjniobject.html -
@KenAppleby-0 QJniObject has limited types to handle. Bundle is not one of them. Check out what QJniObject can handle.
Scroll all way down and look for JNI Types
https://doc.qt.io/qt-6/qjniobject.htmlwrote on 30 Jan 2023, 20:01 last edited bySo C++ bundle.toString() calls a Java method on java.lang.Object, via jobject, which is a supported JNI type.
That explains it.
Thank you.
1/7