LAMW (solved) how to prevent location mocking / fake gps on LAMW
lazarus / 43-Android
----------------------------------------------------------------------
Mongkey · 2021-08-19 10:58
This is java article i've got, i knew it depreciated on API >25, but
it very interesting.
https://www.programcreek.com/java-api-examples/?class=android.telephon
y.TelephonyManager&method=getAllCellInfo
Since i am very beginner on java, i cant implement it, because the
return value like tstring.
----------------------------------------------------------------------
engkin · 2021-08-19 14:00
I think this is a Pascal problem. Any Java object is simply translated
as a pointer:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i unit
And_jni;...type.... jobject=pointer;
including jList.
While, up to this point, it might be eaiser to solve problems on the
Java side, I believe the proper way is to move the problem to the
Pascal side.
----------------------------------------------------------------------
engkin · 2021-08-19 14:05
For instance android.telephony.TelephonyManager is something like:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i unit
uATTelephonyManager; {$mode delphi} interface uses Classes, SysUtils,
And_jni, AndroidWidget, Laz_And_Controls, uAndroidCommon; type {
jTelephonyManager } jTelephonyManager=class(jCommon) protected
const CClassPath:string='android/telephony/TelephonyManager';
protected {Shared by *all* jTelephonyManager instances}
FjClass:jObject;static; FInitialized:boolean;static; //MethodId
fields jMethodId_getPhoneCount:jmethodID;static;
jMethodId_createForSubscriptionId:jmethodID;static;
jMethodId_getDeviceSoftwareVersion:jmethodID;static;
jMethodId_getDeviceId1:jmethodID;static;
jMethodId_getDeviceId2:jmethodID;static;
jMethodId_getCellLocation:jmethodID;static;
jMethodId_getNeighboringCellInfo:jmethodID;static;
jMethodId_getPhoneType:jmethodID;static;
jMethodId_getNetworkOperatorName:jmethodID;static;
jMethodId_getNetworkOperator:jmethodID;static;
jMethodId_isNetworkRoaming:jmethodID;static;
jMethodId_getNetworkCountryIso:jmethodID;static;
jMethodId_getNetworkType:jmethodID;static;
jMethodId_getDataNetworkType:jmethodID;static;
jMethodId_getVoiceNetworkType:jmethodID;static;
jMethodId_hasIccCard:jmethodID;static;
jMethodId_getSimState:jmethodID;static;
jMethodId_getSimOperator:jmethodID;static;
jMethodId_getSimOperatorName:jmethodID;static;
jMethodId_getSimCountryIso:jmethodID;static;
jMethodId_getSimSerialNumber:jmethodID;static;
jMethodId_getSubscriberId:jmethodID;static;
jMethodId_getGroupIdLevel1:jmethodID;static;
jMethodId_getLine1Number:jmethodID;static;
jMethodId_setLine1NumberForDisplay:jmethodID;static;
jMethodId_getVoiceMailNumber:jmethodID;static;
jMethodId_setVoiceMailNumber:jmethodID;static;
jMethodId_getVoiceMailAlphaTag:jmethodID;static;
jMethodId_getCallState:jmethodID;static;
jMethodId_getDataActivity:jmethodID;static;
jMethodId_getDataState:jmethodID;static;
jMethodId_listen:jmethodID;static;
jMethodId_isVoiceCapable:jmethodID;static;
jMethodId_isSmsCapable:jmethodID;static;
jMethodId_getAllCellInfo:jmethodID;static;
jMethodId_getMmsUserAgent:jmethodID;static;
jMethodId_getMmsUAProfUrl:jmethodID;static;
jMethodId_iccOpenLogicalChannel:jmethodID;static;
jMethodId_iccCloseLogicalChannel:jmethodID;static;
jMethodId_iccTransmitApduLogicalChannel:jmethodID;static;
jMethodId_iccTransmitApduBasicChannel:jmethodID;static;
jMethodId_iccExchangeSimIO:jmethodID;static;
jMethodId_sendEnvelopeWithStatus:jmethodID;static;
jMethodId_getIccAuthentication:jmethodID;static;
jMethodId_setPreferredNetworkTypeToGlobal:jmethodID;static;
jMethodId_hasCarrierPrivileges:jmethodID;static;
jMethodId_setOperatorBrandOverride:jmethodID;static;
jMethodId_canChangeDtmfToneLength:jmethodID;static;
jMethodId_isWorldPhone:jmethodID;static;
jMethodId_isTtyModeSupported:jmethodID;static;
jMethodId_isHearingAidCompatibilitySupported:jmethodID;static;
jMethodId_getVoicemailRingtoneUri:jmethodID;static;
jMethodId_isVoicemailVibrationEnabled:jmethodID;static; protected
class function get_jClass:jobject;override; class procedure
get_jIDs;override; public constructor
Create(AjObject:jObject=nil);overload; class procedure Init;
public //Procs function getPhoneCount:jint; function
createForSubscriptionId(_subId:jint):jobject; function
getDeviceSoftwareVersion:String; function
getDeviceId:String;overload; function
getDeviceId(_slotId:jint):String;overload; function
getCellLocation:jobject; function getNeighboringCellInfo:jobject;
function getPhoneType:jint; function
getNetworkOperatorName:String; function getNetworkOperator:String;
function isNetworkRoaming:boolean; function
getNetworkCountryIso:String; function getNetworkType:jint;
function getDataNetworkType:jint; function
getVoiceNetworkType:jint; function hasIccCard:boolean; function
getSimState:jint; function getSimOperator:String; function
getSimOperatorName:String; function getSimCountryIso:String;
function getSimSerialNumber:String; function
getSubscriberId:String; function getGroupIdLevel1:String;
function getLine1Number:String; function
setLine1NumberForDisplay(_alphaTag:String;_number:String):boolean;
function getVoiceMailNumber:String; function
setVoiceMailNumber(_alphaTag:String;_number:String):boolean;
function getVoiceMailAlphaTag:String; function getCallState:jint;
function getDataActivity:jint; function getDataState:jint;
procedure listen(_listener:jobject;_events:jint); function
isVoiceCapable:boolean; function isSmsCapable:boolean; function
getAllCellInfo:jobject; function getMmsUserAgent:String;
function getMmsUAProfUrl:String; function
iccOpenLogicalChannel(_AID:String):jobject; function
iccCloseLogicalChannel(_channel:jint):boolean; function iccTransmit
ApduLogicalChannel(_channel:jint;_cla:jint;_instruction:jint;_p1:jint;
_p2:jint;_p3:jint;_data:String):String; function iccTransmitApduBas
icChannel(_cla:jint;_instruction:jint;_p1:jint;_p2:jint;_p3:jint;_data
:String):String; function iccExchangeSimIO(_fileID:jint;_command:ji
nt;_p1:jint;_p2:jint;_p3:jint;_filePath:String):jbyte; function
sendEnvelopeWithStatus(_content:String):String; function getIccAuth
entication(_appType:jint;_authType:jint;_data:String):String;
function setPreferredNetworkTypeToGlobal:boolean; function
hasCarrierPrivileges:boolean; function
setOperatorBrandOverride(_brand:String):boolean; function
canChangeDtmfToneLength:boolean; function isWorldPhone:boolean;
function isTtyModeSupported:boolean; function
isHearingAidCompatibilitySupported:boolean; function
getVoicemailRingtoneUri(_accountHandle:jobject):jobject; function
isVoicemailVibrationEnabled(_accountHandle:jobject):boolean;
end; implementation { jTelephonyManager } constructor
jTelephonyManager.Create(AjObject:jObject);begin inherited
Create(AjObject);end; ...//code was removed to please the forum post
limit :(
This code is machine generated. For now, it ignores exceptions which
should be fixed.
You are interested in:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i
function getAllCellInfo:jobject;
Notice how it returns jobject. Now we need another class for
java.util.List:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i unit
uJUList; {$mode delphi} interface uses Classes, SysUtils, And_jni,
AndroidWidget, Laz_And_Controls, uAndroidCommon; type { jList }
jList=class(jCommon) protected const
CClassPath:string='java/util/List'; protected {Shared by *all*
jList instances} FjClass:jObject;static;
FInitialized:boolean;static; //MethodId fields
jMethodId_size:jmethodID;static;
jMethodId_isEmpty:jmethodID;static;
jMethodId_contains:jmethodID;static;
jMethodId_toArray1:jmethodID;static;
jMethodId_toArray2:jmethodID;static;
jMethodId_remove:jmethodID;static;
jMethodId_addAll:jmethodID;static;
jMethodId_removeAll:jmethodID;static;
jMethodId_clear:jmethodID;static;
jMethodId_equals:jmethodID;static; jMethodId_get:jmethodID;static;
jMethodId_add:jmethodID;static;
jMethodId_indexOf:jmethodID;static;
jMethodId_listIterator1:jmethodID;static;
jMethodId_listIterator2:jmethodID;static; protected class function
get_jClass:jobject;override; class procedure get_jIDs;override;
public constructor Create(AjObject:jObject=nil);overload; class
procedure Init; public //Procs function size:jint; function
isEmpty:boolean; function contains(__Param1:jobject):boolean;
function toArray:jobject;overload; function
toArray(__Param2:jobject):jobject;overload; function
remove(__Param1:jobject):boolean; function
addAll(__Param1:jobject):boolean; function
removeAll(__Param1:jobject):boolean; procedure clear; function
equals(__Param1:jobject):boolean; function
get(__Param1:jint):jobject; procedure
add(__Param1:jint;__Param2:jobject); function
indexOf(__Param1:jobject):jint; function
listIterator:jobject;overload; function
listIterator(__Param1:jint):jobject;overload; end; implementation {
jList } constructor jList.Create(AjObject:jObject);begin inherited
Create(AjObject);end;...//code is cut to please the forum editor
Just like the previous code, this was machine generated.
In theory, you take the jobject from getAllCellInfo and pass it to
jList.Create
jList should give you access to its items which are of type CellInfo,
so we need a third class:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i unit
uATCellInfo; {$mode delphi} interface uses Classes, SysUtils,
And_jni, AndroidWidget, Laz_And_Controls, uAndroidCommon; type {
jCellInfo } jCellInfo=class(jCommon) protected const
CClassPath:string='android/telephony/CellInfo'; protected {Shared
by *all* jCellInfo instances} FjClass:jObject;static;
FInitialized:boolean;static; //MethodId fields
jMethodId_isRegistered:jmethodID;static;
jMethodId_getTimeStamp:jmethodID;static;
jMethodId_hashCode:jmethodID;static;
jMethodId_equals:jmethodID;static;
jMethodId_toString:jmethodID;static;
jMethodId_describeContents:jmethodID;static;
jMethodId_writeToParcel:jmethodID;static; protected class function
get_jClass:jobject;override; class procedure get_jIDs;override;
public constructor Create(AjObject:jObject=nil);overload; class
procedure Init; public //Procs function isRegistered:boolean;
function getTimeStamp:jlong; function hashCode:jint; function
equals(_other:jobject):boolean; function toString:String;
function describeContents:jint; procedure
writeToParcel(__Param1:jobject;__Param2:jint); end; implementation {
jCellInfo } constructor jCellInfo.Create(AjObject:jObject);begin
inherited Create(AjObject);end; class procedure jCellInfo.Init;var
LjClass:jobject;begin if not FInitialized then begin
LjClass:=Get_jClassLocalRef(CClassPath);
FjClass:=Get_jObjGlobalRef(LjClass); Delete_jLocalRef(LjClass);
get_jIDs; FInitialized:=True; end;end; class function
jCellInfo.get_jClass:jobject;begin Result:=FjClass;end; class
procedure jCellInfo.get_jIDs;begin
jMethodId_isRegistered:=Get_jMethodID(FjClass,'isRegistered','()Z');
jMethodId_getTimeStamp:=Get_jMethodID(FjClass,'getTimeStamp','()J');
jMethodId_hashCode:=Get_jMethodID(FjClass,'hashCode','()I'); jMethodI
d_equals:=Get_jMethodID(FjClass,'equals','(Ljava/lang/Object;)Z'); jM
ethodId_toString:=Get_jMethodID(FjClass,'toString','()Ljava/lang/Strin
g;'); jMethodId_describeContents:=Get_jMethodID(FjClass,'describeCont
ents','()I'); jMethodId_writeToParcel:=Get_jMethodID(FjClass,'writeTo
Parcel','(Landroid/os/Parcel;I)V');end; function
jCellInfo.isRegistered:boolean;begin// ()Z
Result:=jmethod_get_boolean(jMethodID_isRegistered);end; function
jCellInfo.getTimeStamp:jlong;begin// ()J
Result:=jmethod_get_jlong(jMethodID_getTimeStamp);end; function
jCellInfo.hashCode:jint;begin// ()I
Result:=jmethod_get_jint(jMethodID_hashCode);end; function
jCellInfo.equals(_other:jobject):boolean;var jParams:array[0..0] of
jvalue absolute _other;begin// (Ljava/lang/Object;)Z
Result:=jmethod_get_booleanA(jMethodId_equals,jParams);end; function
jCellInfo.toString:String;begin// ()Ljava/lang/String;
Result:=jmethod_get_String(jMethodID_toString);end; function
jCellInfo.describeContents:jint;begin// ()I
Result:=jmethod_get_jint(jMethodID_describeContents);end; procedure
jCellInfo.writeToParcel(__Param1:jobject;__Param2:jint);var
jParams:array[0..1] of jvalue;begin// (Landroid/os/Parcel;I)V
jParams[0].l:=__Param1; jParams[1].i:=__Param2;
jmethod_voidA(jMethodId_writeToParcel,jParams);end; end.
It might be possible to use Pascal generics to make jList more like
its counterpart in Java.
Anyway, I could be wrong, but this is how I see it.
WARNING:
This code was not tested.
----------------------------------------------------------------------
Mongkey · 2021-08-19 22:05
Thank you bro! I'll do my best to follow your sample.
----------------------------------------------------------------------
Mongkey · 2021-08-19 23:34
i tried a lot, too much errors, not find symbol ,i dont understand
java, its difficult for me ,
I wish this attached code functions intact to LAMW jTelephony
component, or new component jGeoFencing
I got many fake gps coordinates, may be by retrieving from cell LAC,
MNC solving this problem.
New candidate -> geofencing sample.
Thank you anyway!
----------------------------------------------------------------------
jmpessoa · 2021-08-20 04:51
Done!
improved jTelephonyManager component
[need tests and maybe some fix....]
[need "android.permission.ACCESS_COARSE_LOCATION" granted by the
user! ]
GetLocationAreaCode()
GetBaseStationId()
GetMobileNetworkCode()
GetMobileCountryCode()
Thanks you!
PS. files changed:
"jTelephonyManager.java"
"telephonymanager.pas"
----------------------------------------------------------------------
Mongkey · 2021-08-20 05:36
,
thanks prof JM, you are the best!
Actually i get more 1 solution for this:
for API > 18
Code: Java [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i public
static boolean isMockLocationOn(Context context) { if
(Settings.Secure.getString(context.getContentResolver(),
Settings.Secure.ALLOW_MOCK_LOCATION).equals("0")) return
false; else return true;}
----------------------------------------------------------------------
Mongkey · 2021-08-20 06:29
Working very well on android 10, just tested get cell location, is it
compatible for dual sim android? I gonna test it soon!
----------------------------------------------------------------------
Mongkey · 2021-08-21 05:41
GetLocationAreaCode()
GetBaseStationId()
GetMobileNetworkCode()
GetMobileCountryCode()
After trying all, all retrieve same value (dual sim, sim1-> but with
expiring telco subscription , no card on sim2), yesterday just tried
GetLocationAreaCode(), not yet trying 3 others.
After inspecting -> working ok for dual sim -> detect on sim2 only, no
card on sim1 -> WORK
may be, retrieving same value if the card has expired -> useful for
detecting no longer in service telco simcard
----------------------------------------------------------------------
engkin · 2021-08-22 16:10
This took me longer than I like. I kept having stange exception with
an "invalid object". I tracked it down to a call in my code:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i
javContext:=gApp.GetContext();//<---- fails
which is:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i function
jApp.GetContext(): jObject;begin Result:=
jApp_GetContext(Self.Jni.jEnv, Self.Jni.jThis);//<--- this fails!!end;
I assumed Self.Jni.jThis is not holding a valid value anymore, so I
turned it into a Java global variable reference:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i var
gThis:jobject; gContext:jobject; procedure
Java_Event_pAppOnCreate(env: PJNIEnv; this: jobject; context:jobject;
layout:jobject; intent: jobject);begin
gThis:=env^.NewGlobalRef(env,this);
gContext:=env^.NewGlobalRef(env,context); gApp.IsAppActivityRecreate
:= gApp.FInitialized; gApp.FInitialized := False;
//gApp.Init(env,this,context,layout, intent);
gApp.Init(env,gThis,gContext,layout, intent);end;
Surprisingly that was not enough!!
then I skipped Self.Jni.jThis and used the global variable gThis
directly:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i function
jApp.GetContext(): jObject;begin Result:=
jApp_GetContext(Self.Jni.jEnv, gThis);end;
Now it works:
Quote
gApp.APILevel: 30
prob: 7
pasContext.TELEPHONY_SERVICE:
phone
pasList.size: 4
get(0)
CellInfo
CellInfoLte:{mRegistered=YES ....
get(1)
CellInfo
CellInfoLte:{mRegistered=NO ...
get(2)
CellInfo
CellInfoLte:{mRegistered=NO ...
get(3)
CellInfo
CellInfoLte:{mRegistered=NO ...
----------------------------------------------------------------------
jmpessoa · 2021-08-22 20:29
Quotefunction jApp.GetContext(): jObject;
begin
Result:= jApp_GetContext(Self.Jni.jEnv, Self.Jni.jThis);//<--- this
fails!!
end;
You can see in "Laz_And_Controls_Events.pas" and
"Laz_And_Controls.pas"
that all "Java_Event_*" call has some code like this:
Code: [Select]Procedure Java_Event_pOnTimePicker(env: PJNIEnv; this:
jobject; Obj: TObject; hourOfDay: integer; minute: integer);
begin
gApp.Jni.jEnv := env; // <----
if this <> nil then gApp.Jni.jThis := this; // <----
......
.......
end;
It keeps these global data always "up to date"!
the reference is here:
https://android-developers.googleblog.com/2011/11/jni-local-reference-
changes-in-ics.html
Are you "by passing" LAMW code architecture?
----------------------------------------------------------------------
engkin · 2021-08-22 21:40
No, I am not bypassing LAMW's architecture. I am trying to extend it
by bringing Java/Android classes to Pascal.
As your reference link shows, Java_Event_pAppOnCreate is expected to
use env->NewGlobalRef to store its parameters on the Pascal side,
otherwise these values become invalid because of the Garbage Collector
moving them around. How come you're not following that reference?
I made a simple app with a jButton and jEditText. The button calls
javContext:=gApp.GetContext();
That call fails because gApp.Jni.jThis became invalid.
Then I used NewGlobalRef as soon as I received the parameters in
Java_Event_pAppOnCreate
Passing the results to jApp.Init *seemed* not to work,
but NOW, thanks to your explanation, I think they got overwritten by
LOCAL references again.
That explains why it worked when I used gThis directly, because it
holds the GLOBAL reference.
If my understanding is correct, there is a bug in LAMW, it should set
the members of jApp.Jni once, AND it should use NewGlobalRef for that,
AND it should not change them inside Java_Event_* in unit
"Laz_And_Controls_Events.pas" or any other place.
Of course, at the end of the app it should delete the global
references.
----------------------------------------------------------------------
jmpessoa · 2021-08-22 22:29
So at the moment we are doing different readings of the document.....
this code:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i Procedure
Java_Event_pOnTimePicker(env: PJNIEnv; this: jobject; Obj: TObject;
hourOfDay: integer; minute: integer);begin gApp.Jni.jEnv := env;
// <---- if this <> nil then gApp.Jni.jThis := this; //
<---- ...... .......end;
is vital for the entire LAMW code architecture ... and yes "gApp" is
global, but properties
gApp.Jni.jEnv and gApp.Jni.jThis need to be continually updated
otherwise we will get "staled" object reference....
----------------------------------------------------------------------
engkin · 2021-08-22 23:44
When I said global, I was not talking about Pascal global variables.
I meant Jave global references. These references do not stall, the
Garbage Collector doesn't touch them.
What you receive in Java_Event_* is Java local references, these local
references will stall. If you intend to use them outside these
procedures, as in LAMW, you're supposed to turn the Java local
references to Java global references.
This is what the article you linked is saying, and it is what works on
my side.
If you are not convinced, can you show me one simple example where my
suggestion will not work?
----------------------------------------------------------------------
jmpessoa · 2021-08-23 02:16
Quotecan you show me one simple example where my suggestion .....
From reference:
QuoteNow there’s a per-thread local reference table, it’s vital that
you only use a JNIEnv* on the right thread.
QuoteIf you have a native peer (a long-lived native object
corresponding to a Java object, usually created when the Java object
is created and destroyed when the Java object’s finalizer runs), you
must not stash a jobject in that native object, because it won’t be
valid next time you try to use it. (Similar is true of JNIEnv*s. They
might be valid if the next native call happens on the same thread, but
they won’t be valid otherwise.)
and from here: https://developer.android.com/training/articles/perf-
jni
QuoteThe JNIEnv is used for thread-local storage. For this reason, you
cannot share a JNIEnv between threads.
Remember that "LAMW Pascal" side/code talk to "LAMW java" [multi-
thread?] side/code.....
So at some time if you comment out these two lines of code:
Quote gApp.Jni.jEnv := env; // <----
if this <> nil then gApp.Jni.jThis := this; // <---
you will get a staled object reference .....
----------------------------------------------------------------------
jmpessoa · 2021-08-23 16:07
QuoteI am trying to extend it by bringing Java/Android classes to
Pascal.
There is a "conceptual" attempt here:
"Laz_And_jni_Controls.pas" and demo "AppTest2"
----------------------------------------------------------------------
engkin · 2021-08-23 20:05
Quote from: jmpessoa on August 23, 2021, 04:16:09 amRemember that
"LAMW Pascal" side/code talk to "LAMW java" [multi-thread?]
side/code.....
All I mentioned was for a single thread, and I am leaving JNIEnv out
for now. Later both will be included. That's why I asked you for the
simplest example. In the simplest case with a single thread and a
single activity, any jobject we receive inside events is going to
stale by the end of the event. If we need the object outside that
event, then we need to turn it into a Java global reference.
For now, I can manage without any changes to LAMW. So let's keep LAMW
as is.
Quote from: jmpessoa on August 23, 2021, 06:07:47 pmThere is a
"conceptual" attempt here:
"Laz_And_jni_Controls.pas" and demo "AppTest2"
Yes, this is what I want to do. Can you please correct me if I state
something not accurate in any of the following:
I noticed IDs we get from calling Get_j*ID can be reused and we do not
need to call Get_j*ID again for the same member.
For instance instead of:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i procedure
TAndroidListView.NotifyDataSetChanged(jAdapter: jObject);var
jClass_arrayAdapter: jClass; jMethodId_notifyDataSetChanged:
jMethodID;begin jClass_arrayAdapter:=
Get_jClassLocalRef('android/widget/ArrayAdapter');
jMethodId_notifyDataSetChanged:= Get_jMethodID(jClass_arrayAdapter,
'notifyDataSetChanged','()V'); Call_jVoidMethod(jAdapter,
jMethodId_notifyDataSetChanged);end;
we can write:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i procedure
TAndroidListView.NotifyDataSetChanged(jAdapter: jObject);begin
Call_jVoidMethod(jAdapter, jMethodId_notifyDataSetChanged);end;
Assuming jMethodId_notifyDataSetChanged declared as a "static" member
of the TAndroidListView and has the correct value.
----------------------------------------------------------------------
engkin · 2021-08-23 20:25
Quote from: jmpessoa on August 23, 2021, 06:07:47 pm
QuoteI am trying to extend it by bringing Java/Android classes to
Pascal.
There is a "conceptual" attempt here:
"Laz_And_jni_Controls.pas" and demo "AppTest2"
I just installed this example on my phone, and now I want to know what
problems did you face to prevent you from moving in this direction?
Asked in a different way, why do you keep adding to the Java part?
----------------------------------------------------------------------
jmpessoa · 2021-08-23 21:38
QuoteI want to know what problems did you face to prevent you from
moving in this direction?
just absolute lack of time.....
QuoteAsked in a different way, why do you keep adding to the Java
part?
0) LAMW "GUI" was the way found after experiences/trials [and
frustrations] for me and for many others (felipemdc, simonsayz, .... )
1) Code reuse: thousands of java/android tutorials deliver ready-to-
use solutions....
2) we can embed all the logic (including asynchronous routines,
exception handle, ....) in java side and leaving to pascal only the
work of making the methods calls and responding to the events .....
making code generation [and use] on the pascal side "clear" and
easier.
side note 1: yes, it is still possible other approaches in LAMW "GUI"
and "fixes" including your suggestion about a global "gThis"
but we need a lot of [time and] code refactoring, testing/maturation
otherwise we run the risk of break/stop everything [legacy] that is
working ....
side note 2: @loaded is working in another direction: LAMW "NoGUI"
----------------------------------------------------------------------
loaded · 2021-08-25 12:30
Quote from: jmpessoa on August 23, 2021, 11:38:04 pmside note 2:
@loaded is working in another direction: LAMW "NoGUI"
LAMW, The Platform that pushes the limits of the possible.
We can't thank enough the legendary developers of LAMW for bringing
this masterpiece to us.
It's up to your imagination and skills to do what you want with
NoGUI...
https://youtu.be/SCAOeAN3eU4 In this study, I wanted to show how .so
files created with LAMW module can be used in Android Studio.
https://youtu.be/gBS0AMrJ50s Also, the CAD application named Polygon,
which I wrote with this method; He started running, he will be in the
1st league soon
----------------------------------------------------------------------
Mongkey · 2021-08-27 08:02
Amazing !