androidc++android-ndkndk-buildandroid-native-library

Unable to get a jstring from R.string.* via JNI in a native C application


I'm working on a native c/c++ app, that uses string resources via the strings.xml file.

Attempting to use AAssetManager to load the "strings.xml" file, has no effect. Returns the same error

I've tried looking for various other implementations, but none have worked

Android API level (Project): 25

Android API level (Device): 30

The code I've attempted to use so far is the following:

JNIEnv* jni;
g_App->activity->vm->AttachCurrentThread(&jni, NULL);
jclass rcl = jni->FindClass("com.avetharun.rosemary.R$string");
// attempted the above as well as "... R.string" instead of "... R$string"
jfieldID fid = jni->GetStaticFieldID(rcl, "app_name", "s");
// attempted the above as well as "Ljava/lang/String;" instead of "s"
jstring jstr = (jstring)jni->GetObjectField(rcl, fid);
const char* str = jni->GetStringUTFChars(jstr, 0);

Directory tree:

assets
- test.txt
res
- values
- - strings.xml

strings.xml :

<string name="app_name">Rosemary Project</string>

Running this causes an error: 0x0000007f1881daac in __rt_sigtimedwait () from libc.so, as well as "Sequence contains more than one element"


Solution

  • You're looking for it in the wrong way. The value at R.string.some_string isn't the string itself- it's an integer that references the string. To get the actual string, you need to call Context.getResources().getString(), passing in the id you want to getString.

    It's set up this way for resource localization. The R class holds ids used to reference the strings, and can be used at any time. The Resources class holds a map of those ids to the actual strings, and different instances of Resources will be created for different locales, screen sizes, orientations, etc.