|
关于 调用 JNI JAR 的说明和注意事项,调用第三方 JAR SDK 和 翻译 安卓 JAVA 代码 的说明 V2017.10.18
转载请标明出处,否则死全家。
选择【复制链接】即可得到出处。
(* ************************************************ *)
(* *)
(* *)
(* 设计:爱吃猪头肉 & Flying Wang 2015-04-15 *)
(* 上面的版权声明请不要移除。 *)
(* *)
(* ************************************************ *)
本人所在的群(① FireMonkey[移动开发] 165232328)
对于安卓系统
谷歌 API 提供的是 JNI 接口。
第三方 JAR SDK 提供的也是 JNI 接口。
您的手机,一般会内置 安卓 SDK 的大部分接口。
但是有些 API 可能没有内置。
FMX 安卓工程默认会给您提供多个 谷歌的 SDK 。
因此 大部分 谷歌的 JAR,您都不需要自己去找。
对于 第三方的 SDK 来说。
基本上分为 jar + so、纯jar 和 纯so 三种。
纯so 就是类似于 dll 的接口。只需要注意 dll 是 stdcall 类型,其他所有平台都是 cdecl 类型。 不写是不行的。因为 delphi 不写的是默认的 pascall 类型。
如果你不会调用 dll 那么也就不会调用 so 。
本文不讨论调用 so。
但是告诉你们 SO 文件文件的路径:编辑 RemotePath 列。路径是(xe5) library\lib\armeabi (xe6或以上) library\lib\armeabi-v7a
以上路径的 so 一般是给 jar 加载用的。
自己加载可以用 LoadLibaray 或者 dlopen 。记得用对应的 FreeLibaray 和 dlclose
也可以像定义 DLL 一样,定义 so 的函数接口。这样就不用写代码加载了。
如果只有你自己用,也可以发布到其他你能访问的路径。但是,只能写代码加载了,路径要写完整。
armeabi-v7a 是 arm32 的,如果你需要支持 64bit 除了这个目录,还需要 arm64-v8a。
64bit 下凡是需要用到 so 的,这两个目录都需要放对应的 so。
对于 jar 无论它有没有提供 so 。我们都只能使用 jar 的对外接口。
除非是安卓基本 API,或者是 DELPHI 已经提供的 JAR 。否则 其他的 JAR ,只要你用到了,就必须加入到 安卓的 工程中。 具体如何添加,请自行百度。
即便是 基本 API,EMBT 也没有全部给大家 转成 JNI 接口。
所以当你用到一个 EMBT 没翻译的 API 的时候,请自行用 工具 翻译。
翻译:可以理解为 语言的转换,接口的导出,也就是变成 pascal语法的 pas 文件
当你得到一个 JAR 的时候,请用工具翻译成 pascal 文件。
目前推荐 2 个 工具。
1. 官方的 java2op.exe 。支持 .jar .java .class 三种格式的文件。
2. 爱吃猪头肉的 JarOrClass2pas 。支持 .jar .class 两种格式的文件。
其他工具都是垃圾。千万别用。否则活该。
当你用工具得到 pas 文件后,注意:
1. 一般会得到 大量的 无用的,错乱的,重复的 接口。请将它们删除。
2. 即便是没问题的接口,如果用不到,也请删除。
3. 转换工具会写出一些 uses 的单元,这些单元可能不存在。
对于jar 或 class 文件引用了别的 jar,就容易出现不认识的 unit 的 uses。请找到这些 jar 继续翻译。
当你 jar 已经加入到 安卓项目中。
jni pas 文件已经准备好,也加入到 安卓项目中。
就可以开始调用 jar 接口了。
接下来说明下基本的类型变化。
Int 就是 Integer ,很多基本对象大家都可以自己想到。
string 是 JString 。
Uri 要翻译成 Jnet_Uri。
上述两个类型 EMBT 提供了互相转换的函数。
还有个别的其他改变名称的类型。这里就无法一一列举了。如果 你发现一些 类名 EMBT 应该提供了,但是找不到,请通过 Signatur 在 Find in Files 对话框中查找。
例如 搜索 java/lang/Class 可以发现 JCalss 也改名了。
int [] 就是 TJavaArray<Integer> ,基本类型用 TJavaArray<>。
但是 string [] 是 TJavaObjectArray<JString>,对象类型的一般都用 TJavaObjectArray<>。
ArrayList<String> 要翻译成 JArrayList
而且任何 ArrayList<PendingIntent> 也就是 ArrayList<某对象> 都要翻译成 JArrayList。
有些类型的名称比较特别。例如 java 的 Phone 类型 EMBT 已经翻译成了 JCommonDataKinds_Phone。这是因为 Phone 是 CommonDataKinds 的内部类。
数据类型 OK 了。那么就谈谈 Java 类的 构造函数 类成员 类方法 和 普通成员 普通方法。
如果不懂这些,请自行百度。建议好好看看 面向对象开发 课程。
Java 类一般会提供默认构造函数,到了 pas 里头,他的函数名叫 init 小写。默认不带参数。
但是很多 java 类 会重载 构造函数,提供带参数的版本。
接下来,我们需要百度下你打算使用的 jni 的 demo 。
安卓开发,最大的优势就是,网上全是 demo ,虽然是 java 语言的。
找到 demo 代码之后,你就需要 按照 代码的逻辑,进行语言的翻译。
下面提供几种常见的 代码 翻译。
关键内容,请回复。
如果你使用一个方法,发生Segmentation fault(11) 可能是对象为 nil 或者 函数不存在(一般是版本不同,有的版本函数就不存在)。
如果你使用一个方法,发生非法操作,说明没有这个方法(大概是名称或参数有错误)。
如果提示你 java class xxx could not be found,如果是官方 xxx ,那么是你的手机内部没提供这个接口,你可以自己找官方的 jar 文件来加入、
如果是第三方的 xxx,那更简单了,这个 xxx 对应的 jar 文件,你肯定没加入到 你的工程中。
如果你确认你加了(参考 第二个箭头,确认加了,就删了再加一遍,还不行,可能是你编译出的结果目录,存在垃圾,删除编译结果目录试试。),建议做如下操作
打开你的 Android 工程,点菜单项 Project—>Deployment,打开部署子窗口,点 Revert to Default 按钮,就是那个向左的弯箭头:
出现 Revert to default 对话框:
选中第一项“Revert for all configurationsthe active platform”,点 OK。
注意:不论其默认选项如何,在这里都必须选择其中一个并点OK,否则你的Android程序在调用JAR文件时将会出现“Java Class xxx could not befound”的错误。
以上文字来源于 http://blog.sina.com.cn/s/blog_648d306d0102vfgq.html
如果 Objs 是 TJavaObjectArray<Jxxxx> 的 Objs.Items[x] 或者 Objs[x] 发生错误(Segmentation fault(11)),那么就是不能这样用,改用
TJxxxx.Warp(Objs.GetRawItem(x)) 试试。多谢 [深圳]机器猫(5909386) 的测试。
一般建议
uses
{$IF CompilerVersion >= 27.0} // >= XE6
Androidapi.Helpers,
{$ENDIF}
FMX.Helpers.Android,
Androidapi.JNI.JavaTypes,
Androidapi.NativeActivity;
关键内容,请回复。
无论如何,当你得到一个 java 对象一定要先检查 是不是 nil,否则轻则提示错误,重则闪退。
EMBT 经常忘了检查,所以就闪退,例如你在窗体中放了一个 IAP 支付控件,很多手机上都会闪退,就是因为没检查 nil。
如果是正在开发的 APP 在任何机器上闪退,特别是旧版本升级来的,别人复制给你的。一般是 发布信息混乱,造成的。工程的 发布(部署)信息需要【重新加载】。Deployment 需要 Revert to Default
如果是任何APP。包括新建的空 APP,在特定的机器上一运行就闪退。说明是一个 BUG。请在本群的 不看后悔 系列中 解压 找 XE 修复 APK 启动,提示 Cannot deploy," " file not found.txt。
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
|