Delphi中Android运行和JNI交互分析

Androidapi.JNIBridge负责和JNI交互.,既然要交互,那么首先就是需要获得JNI的运行环境,Android本身内置的就有一个 Java(Dalvik)虚拟机。所以这个第一步就肯定是要这个虚拟机和我们当前的运行线程环境关联。这时候 Androidapi.JNIBridge中的 TJNIResolver就出场了。GetJNIEnv这个函数就是,
class function TJNIResolver.GetJNIEnv: PJNIEnv;
var
  PActivity: PANativeActivity;
begin
 if JNIEnvRes = nil then
  begin
    PActivity := PANativeActivity(System.DelphiActivity);
    PActivity^.vm^.AttachCurrentThread(PActivity^.vm, @JNIEnvRes, nil);
  end;
  Result := JNIEnvRes;
end;


首先会先判定有没有附加关联到当前的运行环境,如果没有则将当前线程环境附加一个到Android的Java虚拟机中去。于是我们的程序就进入他的环境了,这个里面有一个DelphiActivity,就是以前分析的运行过程中ANdroid入口的 ANativeActivity_onCreate这个由Android自己加载的函数的一个导入参数,Delphi中保存起来了,通过这个获得JVM虚拟机环境,然后附加当前线程到虚拟机。
附加进去了,那么就可以使用JNI的一些东西了。使用JNI的一些对象和数据等都是通过一个奇妙的类,这个类就是TRawVirtualClass,设计这个类的目的就是用来动态创建一些接口的实现,然后TJavaImport继承这个,然后TJavaGenericImport继承TJavaImport,通过TJavaGenericImport这个东西就可以实现对于Java的各种对象的包装,通过他的Wrap来包装一个Java对象到Delphi,然后就可以使用这些接口了。比如MainActivity就是
TJavaGenericImport.Wrap(Syste.DelphiActivity^.clazz);
通过这个代理实现,就相当于以后我们如果要使用Java中的东西,只用写类接口 JFMXNativeActivityClass和对象接口 JFMXNativeActivity就可以直接通过 TJavaGenericImport来转换包装获得Java对象接口了,当前前提是需要获得Java对象的数据指向。
再来看几个基本数据转换函数
function JStringToString(const JStr: JString): string;
begin
  if JStr = nil then
    Result := ''
  else
    Result:= JNIStringToString(TJNIResolver.GetJNIEnv, JNIString((JStr as ILocalObject).GetObjectID));
end;
将Java的字符串转换到Delphi中来,可见这个主要的还是通过TJNIResolver这个辅助类,获得实际JVM环境,然后通过这个来进行联系实现

你可能感兴趣的:(Delphi编程)