Android Module Wizard : Try to get string from strings.xml lazarus / 43-Android ---------------------------------------------------------------------- thierrydijoux · 2014-10-19 07:52 Hi, i'm trying to get string from strings.xml. in And_jni_bridge.pas i added this code : Code: [Select]function  jSysInfo_GetResString        (env:PJNIEnv;this:jobject;context : jObject; AResName: string): string; Const  _cFuncName = 'getResString';  _cFuncSig  = '(Landroid/content/Context;Ljava/lang/String;)Ljava/lang/String;'; Var  _jMethod : jMethodID = nil;  _jParams : Array[0..1] of jValue;  _jString : jString;  _jBoolean: jBoolean; begin  jClassMethod(_cFuncName,_cFuncSig,env,gjClass,_jMethod);  _jParams[0].l := context;  _jParams[1].l := env^.NewStringUTF(env, pchar(AResName) );  _jString      := env^.CallObjectMethodA(env,this,_jMethod,@_jParams);  env^.DeleteLocalRef(env,_jParams[1].l);  Case _jString = nil of   True : Result    := '';   False: begin           _jBoolean := JNI_False;           Result    := String( env^.GetStringUTFChars(Env,_jString,@_jBoolean) );          end;  end; end; in AndroidWidget.pas i added Code: [Select]function jApp.GetResString(AResName: string): string; begin   Result:= jSysInfo_GetResString(Self.Jni.jEnv, Self.Jni.jThis, Self.Jni.jActivity, PChar(AResName)); end; in Controls.java i added this code Code: [Select]public String getResString(android.content.Context context, String resName) { int id = context.getResources().getIdentifier(resName, "string", context.getPackageName());     String value = id == 0 ? "" : (String) context.getResources().getText(id); // int id = getApplicationContext().getResources().getIdentifier("hello_world", "string", getApplicationContext().getPackageName()); // int id = getResources().getIdentifier("hello_world", "id", getPackageName()); // String value = id == 0 ? "" : (String) getApplicationContext().getResources().getString(id); return value; }  When i call jApp.GetResString(AResName: string): string; from a jbutton, app crash. if i define a public variable in jApp Class in the init procedure like that, i works. Code: [Select]TestRes:=jSysInfo_GetResString(env, this, activity, PChar('rxml')); How can i access the resource string dynamicly from the module (in my button) ? ps : sorry for my english ---------------------------------------------------------------------- jmpessoa · 2014-10-19 11:53 Hi, Quote...When i call jApp.GetResString(AResName: string) .... How? TestRes:= jApp.GetResString.... //error! or TestRes:= gApp.GetResString.... //ok! ---------------------------------------------------------------------- thierrydijoux · 2014-10-19 11:56 getting TestRes is working (when it's placed into app.init) when calling function jApp.GetResString(AResName: string): string; app crash ---------------------------------------------------------------------- thierrydijoux · 2014-10-19 12:01 It's the same when you try to call GetAppPath (from app class). Create a public function which calls   jSysInfo_PathApp(Self.Jni.jEnv, Self.Jni.jThis, Self.Jni.jActivity, PChar(FAppName){gjAppName}); and it also crash ---------------------------------------------------------------------- jmpessoa · 2014-10-19 12:05 Ok, Please, send me the unit1.pas... ---------------------------------------------------------------------- thierrydijoux · 2014-10-19 12:14 The project is attached. I joined the And_jni_Bridge.pas and androidwidget.pas. The java file is also modified (in d2\src\fr\test\tdi\d2) Try to find getResString. Thanks ---------------------------------------------------------------------- jmpessoa · 2014-10-19 12:38 Please, try this:  "jSysInfo_GetResString2" Code: [Select]function  jSysInfo_GetResString2(env:PJNIEnv;this:jobject;context : jObject; AResName: string): string; var     cls: jClass;  _jMethod: jmethodID;  _jParams : Array[0..1] of jValue;  _jString : jString;  _jBoolean: jBoolean; begin   cls := env^.GetObjectClass(env, this);   _jMethod:= env^.GetMethodID(env, cls, 'getResString', '(Landroid/content/Context;Ljava/lang/String;)Ljava/lang/String;');  _jParams[0].l := context;  _jParams[1].l := env^.NewStringUTF(env, pchar(AResName) );  _jString      := env^.CallObjectMethodA(env,this,_jMethod,@_jParams);  env^.DeleteLocalRef(env,_jParams[1].l);  Case _jString = nil of   True : Result    := '';   False: begin           _jBoolean := JNI_False;           Result    := String( env^.GetStringUTFChars(Env,_jString,@_jBoolean) );          end;  end; end; ---------------------------------------------------------------------- thierrydijoux · 2014-10-19 12:53 Thanks, from jbutton1 : shomessag(App.TestRes); OK ShowMessage(App.GetResString('rxml')); KO ---------------------------------------------------------------------- jmpessoa · 2014-10-19 13:35 Ok, In many implementations in "And_jni_Bridge.pas"  you can see a new [re-]implementation indicated by "2" I needed do that for support to Android API > 13 .... You can follow this pattern! ---------------------------------------------------------------------- thierrydijoux · 2014-10-19 15:30 Thanks, i tried using you instructions, but it looks like it only work when you call the function in the jApp.Init procedure. I must find a workaround to get those string values and have the multilanguage android way... ---------------------------------------------------------------------- jmpessoa · 2014-10-19 17:24 Please, Try this: Code: [Select]function jApp.GetResString2(AResName: string): string; begin   Result:= jSysInfo_GetResString(Self.Jni.jEnv, Self.Jni.jThis, gApp.GetContext, PChar(AResName)); end; Another [preferable] solution: in "Controls.java" Code: [Select]public String getResString(String resName) {     Context context = this.activity;     int id = context.getResources().getIdentifier(resName, "string", context.getPackageName());     String value = id == 0 ? "" : (String) context.getResources().getText(id);     return value; } in "And_jni_Bridge.pas" Code: [Select]function  jSysInfo_GetResString(env:PJNIEnv;this:jobject;context : jObject; AResName: string): string; var   cls: jClass;  _jMethod: jmethodID;  _jParams : Array[0..0] of jValue;  _jString : jString;  _jBoolean: jBoolean; begin   cls := env^.GetObjectClass(env, this);   _jMethod:= env^.GetMethodID(env, cls, 'getResString', '(Ljava/lang/String;)Ljava/lang/String;');  _jParams[0].l := env^.NewStringUTF(env, pchar(AResName) );  _jString      := env^.CallObjectMethodA(env,this,_jMethod,@_jParams);  env^.DeleteLocalRef(env,_jParams[0].l);  Case _jString = nil of   True : Result    := '';   False: begin           _jBoolean := JNI_False;           Result    := String( env^.GetStringUTFChars(Env,_jString,@_jBoolean) );          end;  end; ---------------------------------------------------------------------- thierrydijoux · 2014-10-20 16:26 Hi jmpessoa, it works ! The faulting code was the java one. I just modify the code with your in controls.java and the job was done :-) Now, the same way, we can access other resources ! Thanks for your help ! Just a question, do you mind if i fork the previous android module wizard (before the new form designer) ? ---------------------------------------------------------------------- jmpessoa · 2014-10-20 16:48 Yes, i can fork it! But it is quite outdated! The "form designer"  release has many improvements [and fix!] that are not there! In any case, thanks for your interest! ---------------------------------------------------------------------- thierrydijoux · 2014-10-20 16:51 ok, so the best to do is maybe send you some new code to include in the "official AMW" ---------------------------------------------------------------------- jmpessoa · 2014-10-20 16:55 Yes, send it for me! His contributions will be always welcome and utilized! Thank you! if you need: jmpessoa_hotmail_com PS. You can see there! Code: [Select]//thanks to  thierrydijoux function jApp.GetStringResourceId(_resName: string): integer; begin    Result:= jApp_GetStringResourceId(Self.Jni.jEnv, Self.Jni.jThis, PChar(_resName)); end; function  jApp.GetStringResourceById(_resId: integer): string; begin   Result:= jApp_GetStringResourceById(Self.Jni.jEnv, Self.Jni.jThis, _resId); end;