Solved QJniObject.callObjectMethod "getString" on android.os.Bundle Returns "" Despite Bundle.toString() Showing Value
-
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.
-
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. -
@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.
-
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();
-
@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.
-
@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 -
So C++ bundle.toString() calls a Java method on java.lang.Object, via jobject, which is a supported JNI type.
That explains it.
Thank you.