2Pascal-新时代的Pascal

标题: 关于 调用 JNI JAR java 的说明和注意事项,调用第 靠写不下了 [打印本页]

作者: wang_80919    时间: 2015-5-14 17:42
标题: 关于 调用 JNI JAR java 的说明和注意事项,调用第 靠写不下了
关于 调用 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 文件,你肯定没加入到 你的工程中。
如果你确认你加了(参考 [attach]746[/attach] 第二个箭头,确认加了,就删了再加一遍,还不行,可能是你编译出的结果目录,存在垃圾,删除编译结果目录试试。),建议做如下操作
打开你的 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。








作者: wang_80919    时间: 2015-5-14 17:43
相关工具
一种简单的 jar 转 pas 工具,不如 EMB 官方提供的 工具 强大。
JarOrClass2Pas FlyingWang V1.0.2016.426 附赠 java 转 Jar.zip
http://www.2pascal.com/forum.php?mod=viewthread&tid=891&fromuid=4
(出处: 2Pascal-新时代的Pascal)

如果你希望使用 EMB 官方工具,请打开你的 帮助,搜索 Java2OP.exe 。


RAD10RTM 加载 jar 存在 BUG
https://quality.embarcadero.com/browse/RSP-12335
QC 中有解决办法。
建议去 EMB 官网注册 EDN 账号,即可登录。
上面的  BUG 新版本已经 FIX 了。


手动翻译 JNI 的老文章
JNI 翻译 转 Delphi 的 经验 方法
http://www.2pascal.com/forum.php ... &tid=1100&fromuid=4
(出处: 2Pascal-新时代的Pascal)

作者: wang_80919    时间: 2015-11-11 11:40
当你使用一个 jni 对象的时候。如果是个可以显示的对象。很多时候需要:
CallInUiThread(
    procedure
    begin
      jni 代码。
    end);
有时候 还得换成 CallInUIThreadAndWaitFinishing。
只有这样 代码才不会死锁。
也就是 如果不这么写。你的 APP 就会出现 未响应。
有些不是显示的 jni 对象,也需要这样写。不过不常见。
如果你收到一个错误 CalledFromWrongThreadException,就是需要 CallInUiThread 了。

如果收到的是
Can't create handler inside thread that has not called Looper.prepare()
也是需要 CallInUiThread 了。多谢 [新会]supermay(15832782) 测试。

注意:不要将大片代码进入上述的代码块中。尽量减少相关代码。最好是用 DEBUG ,找出弹出这类错误提示的代码行。不会 DEBUG 请看书。

在 安卓的世界里,回调函数是不存在的。但是可以使用接口来做到回调。
一般这种接口 会被定义成 Listener。

当你需要继承(实现)一个 java 接口的时候,就需要查看有关代码了。

你会找到好多代码。
他们都是继承(实现) java 接口的好例子。

按照面向对象的说法 接口必须实现。所以上面找到的代码是必然的。
然后定义出这个类的 对象,就可以当参数在 jni 中使用了。
不过这种类型,是 delphi 的实现,所以别忘了 free。

个人建议大家好好研读【unit System.Android.Bluetooth;】。

有时候 接口提供的 回调函数 可能是在线程中运行的。
这时候你实现这个函数的时候,要注意。
UI 对象 无论是 FMX 的还是 jni 的。你都需要线程同步。

线程同步的简单方法就是。
...
//线程或回调函数里的一些代码。
TThread.Synchronize(nil, //或者 用线程自己的同步函数。 Synchronize(
        procedure
        begin
          //你的界面交互代码。
        end);
//继续线程或回调函数的代码。
...

如果是调用事件,
建议用
TThread.Queue(nil,
        procedure
        begin
          //你的事件调用。
        end);


如果你 DEBUG 中收到了 Bitmap size too big 的提示,有可能就是 该用同步,没同步造成的。
10.2 以后,不会再有这个提示。 Bitmap 支持线程中使用了。

10.2 开始,主线程和 UI 线程 为同一个线程了。
CallInUiThread 应该可以大批量的不用了。


有了以上知识,你基本上翻译 java 的代码,就不成问题了。
别说,你不会 顺序、判断、循环、函数调用。

如果你想了解一个 第三方 view 是如何显示到 FMX 中的。
可以参考 unit FMX.WebBrowser.Android 和 unit FMX.Media.Android。

另外,很多操作,都需要对应的权限,别忘了加上。

对于 4.4 以上的系统,想要访问外置存储卡。需要加上
<uses-permission android:name="android.permission.READ_MEDIA_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE"/>
这 2 个权限。
目前 IDE 没有提供。
您需要在 AndroidManifest.template.xml 文档中,自己加入,用 IDE 就能打开,找到 <%uses-permission%>,将上述权限文字加入到 这行下面就行。
但是,不保证所有机器都有效。


如果发现需要使用 安卓下面的 命令行,例如执行 su sh ping 等。
可以参考 QDac http://blog.qdac.cc 的代码,可能叫 QRuntime。
也可以参考 本群的 重启你的手机 源代码。


对于学习 翻译 安卓 java 代码为 pascal 。
最好先看 EMBT 的源代码。然后看 EMBT 的 Samples。
也可以好好看 本群的群共享。
里头好多调用 jni 的 DEMO。
作者: wang_80919    时间: 2016-9-26 14:04
可以参考的 DEMO。

BaiduLocation_百度定位_LBS_定位_5_SDK_DEMO_Add_Jar_BaiduLBS_Android5
http://2pascal.com/forum.php?mod=viewthread&tid=784&fromuid=4
(出处: 2Pascal-新时代的Pascal)


安卓 服务 的 一些 相关代码,自动启动服务或定时启动APP。
http://2pascal.com/forum.php?mod=viewthread&tid=2728&fromuid=4
(出处: 2Pascal-新时代的Pascal)


专门的 DELPHI 实现 JAVA 接口 的 DEMO。
消息注册接收 DEMO。
Java 的消息及事件的一般做法的 DELPHI 版 源码。

安卓 接口实现的事件 动态注册 接收 WIFI 变化消息 Demo
http://www.2pascal.com/forum.php ... &tid=3008&fromuid=4
(出处: 2Pascal-新时代的Pascal)


反射调用 java api
java demo
[mw_shl_code=java,true]    /**
     * VIVO
     * <p>
     * android.util.FtFeature
     * public static boolean isFeatureSupport(int mask);
     * <p>
     * 参数:
     * 0x00000020表示是否有凹槽;
     * 0x00000008表示是否有圆角。
     *
     * @param context Context
     * @return hasNotch
     */
    private static boolean hasNotchInVivo(Context context) {
    boolean hasNotch = false;
    try {
        ClassLoader cl = context.getClassLoader();
        Class ftFeature = cl.loadClass("android.util.FtFeature");
        Method[] methods = ftFeature.getDeclaredMethods();
        if (methods != null) {
            for (int i = 0; i < methods.length; i++) {
                Method method = methods;
                if (method.getName().equalsIgnoreCase("isFeatureSupport")) {
                    hasNotch = (boolean) method.invoke(ftFeature, 0x00000020);
                    break;
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
        hasNotch = false;
    }
    return hasNotch;
}[/mw_shl_code]

作者:brucevanfdm
链接:https://www.jianshu.com/p/fb3efdd5b61a


delphi demo

作者: hiderek    时间: 2017-3-7 09:23
怎么要回复了!
作者: ygm_mm    时间: 2017-3-10 11:29
关键内容查看
作者: lmz84828    时间: 2017-3-16 10:51
多谢楼主分享
作者: guodown    时间: 2017-3-27 16:39

作者: test28    时间: 2017-3-28 11:17
thanks...
good
作者: abc2000    时间: 2017-5-11 17:27
感谢!!!!!!!!!!!!!!!!!!!
作者: ssxbxk    时间: 2017-5-12 11:55
看看隐藏内容
作者: ytxiaokang    时间: 2017-5-12 13:44
谢谢猫哥
作者: runter    时间: 2017-5-13 09:17
kankankankankan
作者: delphixxx    时间: 2017-5-23 16:03
thanks  a  lot
作者: wfymqj    时间: 2017-5-23 18:14
谢谢分享了!
作者: yaoyl    时间: 2017-5-23 19:42
感谢分享!
作者: lhb9900    时间: 2017-5-23 23:16
多谢分享!!!
作者: reborntercel    时间: 2017-5-24 16:38
好资料,谢谢分享!!!
作者: net_ss    时间: 2017-5-25 14:30
关键内容查看
作者: smshsieh    时间: 2017-5-25 18:09
多谢楼主分享
作者: windblast    时间: 2017-5-30 19:34
感谢老猫
作者: rush_h    时间: 2017-5-31 10:38
好教程,谢谢分享。
作者: kgmnsh    时间: 2017-6-5 18:52
多谢楼主分享
作者: badboy3000    时间: 2017-6-5 21:18

多谢楼主分享
作者: hsanming    时间: 2017-6-7 15:12
好文,谢谢!
作者: zzhyy    时间: 2017-6-19 14:44
牛,非常感谢
作者: Connrad    时间: 2017-8-19 02:20
Vielen herzlichen Dank!!!
作者: tataishan    时间: 2017-8-21 22:47
于 调用 JNI JAR java 的说明和注意事项,调用第 靠写不下了
作者: xiangqk    时间: 2017-8-28 17:42
我要看关键内容
作者: suny212    时间: 2017-9-16 08:23
看了半天还是迷迷糊糊

作者: michaeldoer    时间: 2017-9-25 09:06
多谢楼主分享。
作者: ruoyu    时间: 2017-9-25 12:55
非常感谢 非常感谢
作者: soyoung    时间: 2017-10-7 20:44
感謝分享~~
作者: benbenzai    时间: 2017-10-13 08:58
谢谢 楼主
作者: xiubing0377    时间: 2017-10-14 16:32
正找这些答案,单元会有帮助
作者: xiubing0377    时间: 2017-10-14 16:33
正找这些答案,单元会有帮助
作者: luchao900    时间: 2017-10-15 06:03
下面提供几种常见的 代码 翻译。
关键内容,请回复。
作者: pbxyliang    时间: 2017-10-16 19:40
学习中,感谢分享                                       
作者: liyilinlilo    时间: 2017-10-17 09:52
谢谢,谢谢
作者: flyhorsefj    时间: 2017-10-18 17:11
多谢楼主分享
作者: bjabc    时间: 2017-10-21 11:33
多谢老猫分享
作者: bjabc    时间: 2017-10-24 09:28
感谢老猫
作者: xmchcly    时间: 2017-10-27 17:16
新学习好好学习
作者: jingtao    时间: 2017-10-27 19:10
多谢楼主分享
作者: J20Weilong    时间: 2017-11-4 12:42
感谢版主 感谢老猫 感谢所有执着于Delphi/Pascal的人
作者: 我就是谁    时间: 2017-11-5 09:17
不得不说,这个肥肠游泳
作者: DelphiTeacher    时间: 2017-11-10 22:41
不错,学习了
作者: achou.wong    时间: 2017-11-14 16:00
看完整回复的
作者: coolwd    时间: 2017-11-15 21:53
看看看  看看看
作者: lu0123yang    时间: 2017-11-16 10:14
来学习的
作者: Luke    时间: 2017-11-16 10:15
感谢分享!
作者: jsddzxy    时间: 2017-11-16 11:47
好文章,必看!
作者: fbao888    时间: 2017-12-1 10:29
支持看看
!!!!!
作者: fanly    时间: 2017-12-4 08:42
多谢楼主分享
作者: bryce    时间: 2017-12-20 10:58
好东西,,正在学习。。。感谢
作者: Win2003    时间: 2017-12-20 12:54
关键内容,请回复...

作者: szandylee    时间: 2017-12-23 18:01
谢谢!谢谢!谢谢!谢谢!谢谢!
作者: bjlg    时间: 2017-12-30 01:05
thanks...
good
作者: fumin081    时间: 2018-1-4 07:16
很有用的資料,感謝!
作者: ybj316    时间: 2018-1-6 01:50
好文章!!!
作者: bjchang888    时间: 2018-1-9 06:20
看了这个才明白啊,为啥我一直没调用成功。
作者: 2007700216    时间: 2018-1-11 09:14
靠写不下了
作者: ggggcexx    时间: 2018-1-18 04:46
哈哈哈哈哈哈哈哈哈哈哈哈哈哈
作者: hjrocket    时间: 2018-1-20 07:51
谢谢楼主!我正需要这个程序!
作者: msinye    时间: 2018-1-26 03:23
学习学习
作者: chscheese    时间: 2018-1-31 06:38
刚好用到....
作者: cnyahoo    时间: 2018-2-8 02:34
fffffffffffffff
作者: tqdyz    时间: 2018-3-5 08:06
谢谢共享!
作者: process    时间: 2018-3-15 10:14
多谢老猫分享!!
作者: xuewuchen    时间: 2018-3-24 02:30
感谢楼主的说明
作者: pilgrim851    时间: 2018-3-24 18:22
好文拜讀...thanks
作者: mouselost    时间: 2018-3-28 04:21
学习学习
作者: fishhao    时间: 2018-4-10 13:58
非常感谢  这么有用的 教程
作者: h585    时间: 2018-4-12 05:08

thanks...
good
作者: cqbscxh    时间: 2018-4-12 05:30
xie xie fen xiang
作者: a200332    时间: 2018-6-19 09:29
有没有  百度地图的例子
作者: cntlis    时间: 2018-7-14 03:46
给看下家uti怎么处理吧
作者: wowdarklym    时间: 2018-7-28 01:40
666新手需要看看
作者: sdzlb    时间: 2018-8-6 08:53
老猫写的不错,谢谢
作者: mytool    时间: 2018-8-8 02:52
谢谢,老猫
作者: quakestone    时间: 2018-8-14 22:19
很好很好很好很好很好很好很好很好
作者: fuckdelphi    时间: 2018-8-15 08:21
JAR JAVA的调用
作者: hymht    时间: 2018-9-6 09:38
很好,很好,很好,很好,很好,很好,很好,很好,很好,很好,很好,很好,很好,很好,
作者: water1974    时间: 2018-9-30 02:02
楼主辛苦啦
作者: xj307    时间: 2018-10-5 14:50
谢谢,正需要!
作者: abea008    时间: 2018-10-17 16:19
感谢大神无私奉献!!!!!
作者: gebriel_chen    时间: 2018-11-29 04:03
ddassdfasdfasdf
作者: xyghzhb    时间: 2018-12-1 01:46
DELPHI 实现 JAVA 接口 的 DEMO。
作者: lai_ke    时间: 2018-12-2 03:41
一直在找这个
作者: sun_998    时间: 2018-12-10 09:42
很不错,非常感谢楼主
作者: eoslla    时间: 2018-12-18 13:34
先支持下 !!!!
作者: ikillmeba    时间: 2018-12-21 06:43
感谢分享,居然Delphi
作者: ikillmeba    时间: 2018-12-21 09:15
感谢,非常感谢!
作者: Yorke81    时间: 2018-12-21 09:56
碰到问题,赶紧来学习
作者: cn0754    时间: 2018-12-22 16:21
看看下调用的DEMO
作者: oasis_wp    时间: 2019-1-3 07:48
必须得给赞
作者: desai    时间: 2019-1-4 01:29
看看高手
作者: carcode    时间: 2019-1-7 08:16
多谢楼主分享

作者: lai_ke    时间: 2019-1-11 01:56

作者: stlcours    时间: 2019-1-11 11:45
关键内容查看




欢迎光临 2Pascal-新时代的Pascal (http://2pascal.com/) Powered by Discuz! X3