JNI 翻译 转 Delphi 的 经验 方法
首发在
欢迎使用 FMX 开发手机程序的高手来访。
注意:如果您看了本文,翻译了 JNI,请发布到本群共享一份。
不同意本规定的,请立即删除本文。
凡是看了的,就表示您同意本规定。
请大家从群共享下载(①FireMonkey[移动开发] 16523232)
某某某 源代码 带调用非官方 JNI 示例.zip
里头的
Androidapi.JNI.TelephonyGemini.pas
就是我自己转的接口。
或者
重启你的手机 源代码 V1.1
里头也有一些转好的接口。
转换前需要先找到对应的 JAVA 定义文件。最好是 *.java 的。
而且要记住路径(相对于 sources\版本 的路径,下面的例子中自己参详)。
如果是第三方的 JAR 加入到 DELPHI 的 DEX 后 他也是有路径的。他的 JAVA 文件中的包名就是个路径。
一个接口对象分四部分完成。
type
//第一部分,预定义接口对象。后面的注释大家最好都加上。
{Class forward declarations}
JPhoneNumberFormattingTextWatcherEx = interface;//com.mediatek.telephony.PhoneNumberFormattingTextWatcherEX
JTelephonyManagerMTKGemini = interface;//com.mediatek.telephony.TelephonyManagerEx
JSmsManagerGeminiMTK = interface;//android.telephony.GeminiSmsManager
//第二部分,定义接口的类成员(类方法和属性)的对象。
JPhoneNumberFormattingTextWatcherExClass = interface(JObjectClass)
['{0A3E7ECF-F81E-4062-9487-032C3E209466}']
{Methods}
end;
//第三部分,定义接口的普通成员的对象。
[JavaSignature('com/mediatek/telephony/PhoneNumberFormattingTextWatcherEx')]
JPhoneNumberFormattingTextWatcherEx = interface(JObject)
['{752F5521-E746-449E-A9A8-7AE73FF63B05}']
{Methods}
end;
//第四部分,定义接口的构造器。
TJPhoneNumberFormattingTextWatcherEx = class(TJavaGenericImport<JPhoneNumberFormattingTextWatcherExClass, JPhoneNumberFormattingTextWatcherEx>) end;
其中
[JavaSignature('com/mediatek/telephony/PhoneNumberFormattingTextWatcherEx')]
[JavaSignature('android/telephony/gemini/GeminiSmsManager')]
这个必须注意,路径千万不能错。路径不包括扩展名,也不包括 sources\版本 目录。
但是类对象在 DELPHI 中的名称可以自己决定,当然一致最好。
然后要注意,接口中 GUID 请一定要用一个新的。用 CTRL+SHIFT+G 即可产生。
打开你的 XXX.java 文件(一般在 PlatformSDKs\adt-bundle-windows-x86-20130522\sdk\sources\版本 下面)。
查看下他的类型。如果是普通的类 class,那么我们称之为 JObject
如果是 interface ,那么我们称之为 IJavaInstance 。
在定义他们的 第二 和 第三 部分的时候,他们的 父类(基类) 就要做相应的调整。
如果 XXX 为 JObject
//第二部分,定义接口的类成员(类方法和属性)的对象。
JXXXClass = interface(JObjectClass)
//第三部分,定义接口的普通成员的对象。
[JavaSignature('com/mediatek/telephony/XXX')]
JXXX = interface(JObject)
注意大小写。注意 XXX 前头加了个 J。这是 EMB 的惯例。
如果 IYYY 为 IJavaInstance
//第二部分,定义接口的类成员(类方法和属性)的对象。
JIYYYClass = interface(IJavaClass)
//第三部分,定义接口的普通成员的对象。
[JavaSignature('com/mediatek/telephony/IYYY')]
JIYYY = interface(IJavaInstance)
注意大小写。注意 IYYY 前头加了个 J。这是 EMB 的惯例。
IYYY 前头的 I 是 java 的惯例。
这样大体的结构就有了。
接下来我们为 类成员建立具体的内容(第二部分)。
第一步 我们要从 *.java 文件中找出 public static 的 成员。有 普通的变量常量,也有函数。
如果是变量常量,就需要在下面的 2.1 部分写出读写的方法。大部分是只读的。读写函数必须是 _getXXXX 和 _setXXXX ,大小写要注意。XXXX 是被读写的属性。
这些属性放在 2.3 部分。
如果是函数则应该在 2.2 部分定义。
然后查找下有没有个叫 getDefault 的 类方法,这个一般是建议使用的构造函数。
其他没有名称的构造函数,都要翻译成 init 。而且可以重载。一般就一个。
如果就一个还是私有的,那么就没有默认构造函数,就不能写 init。
然后找剩下的 public static 的 函数。这些要翻译到 2.2 部分。
这里要感谢 全知全能的 [成都]白马王子(286258698) ,他发现了新的经验。
如果是 非 static 的 public 的变量常量,需要在下面的 3.1 部分写出读写的方法。这些属性放在 3.3 部分。
JXXXClass = interface(JObjectClass)
['{782DB705-BAF3-4F7B-98B2-DA3D6E304292}']
{Property Methods}
//2.1 这里是内置的静态属性读写定义。
function _getXXXX: Integer; cdecl;
function _getYYYY: JString; cdecl;
{Methods}
//2.2 这里是构造函数和类方法。
function init: JXXX; cdecl;
{Properties}
//2.3 这里是静态属性。
property XXXX: Integer read _getXXXX;
property YYYY: JString read _getYYYY;
end;
也就是说 JXXXClass 是 XXX 对象的构造、属性还有类方法的定义处。
剩下的 public 但不是 static 的 函数 也就是 非静态的方法,要定义到第三部分。
[JavaSignature('com/mediatek/telephony/XXX')]
JXXX = interface(JObject)
['{D70F5051-D98A-46B4-AC6F-D5874EC7612C}']
//3.1 这里是内置的非静态的属性读写定义。
function _getDDDD: Integer; cdecl;
procedure _SetDDDD(Value: Integer); cdecl;
function _getEEEE: JString; cdecl;
{Methods}
//3.2 这里是非静态的方法。
function theYYYY: Integer; cdecl;
{Properties}
//3.3 这里是非静态的属性。
property DDDD: Integer read _getDDDD write _setDDDD;
property EEEE: JString read _getEEEE;
end;
注意所有的方法都是 cdecl 调用规则。如果遇到同名的请重载。
接下来说明下基本的类型变化。
Int 就是 Integer ,很多基本对象大家都可以自己想到。
string 是 JString 。
Uri 要翻译成 Jnet_Uri。
int [] 就是 TJavaArray<Integer> ,基本类型用 TJavaArray<>。
但是 string [] 是 TJavaObjectArray<JString>,对象类型的一般都用 TJavaObjectArray<>。
ArrayList<String> 要翻译成 JArrayList
而且任何 ArrayList<PendingIntent> 也就是 ArrayList<某对象> 都要翻译成 JArrayList。
有些类型的名称比较特别。例如 java 的 Phone 类型 EMB 已经翻译成了 JCommonDataKinds_Phone。这是因为 Phone 是 CommonDataKinds 的内部类。
如果发现不认识的类型,那么就应该是别的文件定义的。
这时候就需要把这个“别的文件”也翻译过来,这样才能顺利的完成翻译。
例如
Build.java 中 Build 类,你完成他的翻译后,就可以使用 JBuild(按规则来的名称) 了。 当然这个类 EMB 已经翻译过了。
虽然 *.java 是分属在不同的文件中的,但是我们可以把一组相关的类都定义在一个 Unit 中。 大家可以参考 EMB 的做法。
如果一个 java 文件内有多个类对象,例如 ContactsContract.java 那么就应该按如下的方法写。
JContactsContract_Contacts = interface;//android.provider.ContactsContract$Contacts
类内部的类要如下写法。
JStreamItems_StreamItemPhotos = interface;//android.provider.ContactsContract$StreamItems$StreamItemPhotos
[JavaSignature( 后面的部分和上面的一样。
大家可以产考 Androidapi.JNI.Provider 的写法。
【好消息】:java2op 或者 JarOrClass2pas 都能自动翻译接口了。大家不用人工做了。
接口的对象的使用。
一般如果你打算使用类方法和属性,可以不建立对象。
使用 TJXXX..JavaClass.YYYY 就可以了。
如果是 创建对象,有 getDefault 就一定要用。没有就 init 。
一般建立的方法如下:
XJ对象 := YJ对象.某函数(返回 XJ对象)
或者
XJ对象 := TJ对象类.javaclass.init 或其他构造函数。
特殊J服务对象,需要用 SharedActivityContext.getSystemService(TJContext.JavaClass.某服务); 的方式建立。
例如:
procedure TMainForm.Button1Click(Sender: TObject);
var
TM: JTelephonyManager;
var
TelephonyServiceNative: JObject;
begin
TelephonyServiceNative := SharedActivityContext.getSystemService(TJContext.JavaClass.TELEPHONY_SERVICE);
if Assigned(TelephonyServiceNative) then
TM := TJTelephonyManager.Wrap((TelephonyServiceNative as ILocalObject).GetObjectID);
try
Edit1.Text := JStringToString(TM.getLine1Number);
except
on E: Exception do
begin
ShowMessage('发生错误' + sLineBreak + E.Message);
end;
end;
end;
如果你使用一个叫 JXXXX 的接口,但是运行发生错误提示,没有找到他。一般是 [JavaSignature( 这个地方的路径错误,或者说,这个机器上就没有这个接口。
如果你使用一个方法,发生非法操作,说明没有这个方法(大概是名称或参数有错误)。
如果你使用一个方法死机了,说明这个方法定义到了错误的位置。
如何实现一个 回调(事件),请参考下面的代码。
TAlertDialogOnClickListener
TCopyButtonClickListener
TVKListener
如何继承一个 接口,请参考下面的代码。(当然这个,最好别分成两个类,下面的代码是特殊需求。其实一个类就行。最好是参考 如何实现一个 回调(事件))
TCommonAlertDialogRunner
TInputQueryDialogRunner
在使用 回调或者事件 或者 操作 JNI UI 的时候,有时候需要用 CallInUiThread 来执行
例如如下的代码。
procedure Toast(const Msg: string; duration: TToastLength);
var
ToastLength: Integer;
begin
if duration = ShortToast then
ToastLength := TJToast.JavaClass.LENGTH_SHORT
else
ToastLength := TJToast.JavaClass.LENGTH_LONG;
CallInUiThread(
procedure
begin
TJToast.JavaClass.makeText(SharedActivityContext, StrToJCharSequence(Msg),
ToastLength).show
end);
end;
最后请大家看看 Androidapi.inc 和 Androidapi.NativeWindowJni 的内容,大家就知道如何调用 *.so 文件了。
(C)(P) By Flying Wang 2013-10-05
辅助 By 爱吃猪头肉。
上面的版权声明还有代码中的相关声明请不要移除。
JNI 翻译 转 Delphi 的 经验 方法的更多相关文章
- delphi cxgrid 使用方法
delphi cxgrid 使用方法1.绑定数据 方法 cxGrid1DBTableView1.DataController.DataSource:=DataSource12.去掉"Drag ...
- Delphi面向对象的方法
方法是属于一个给定对象的过程和函数,方法反映的是对象的行为而不是数据,前一篇提到的对象的两个重要的方法:构造方法和析构方法. 为了使对象能执行各种功能,你能在对象中定制方法 创建一个方法用两个步骤,首 ...
- 【转】对于JNI方法名,数据类型和方法签名的一些认识
[转]对于JNI方法名,数据类型和方法签名的一些认识 之前一直用jni,但是没有考虑Java重载函数,如何在jni-C++里命名,今天看到一篇文章,讲到了类型签名. 原文链接:http://www ...
- Delphi基本图像处理方法汇总
这篇文章主要介绍了Delphi基本图像处理方法,实例汇总了Delphi操作图像实现浮雕.反色.模糊.翻转等常用效果的方法,非常具有实用价值,需要的朋友可以参考下 本文实例汇总了Delphi基本图像 ...
- Delphi中匿名方法动态绑定事件
应恢弘之约,写了一个对其发布的匿名函数动态绑定到事件的封装,代码如下: type TAnonEvent=class public class function Wrap<T1,T2>(On ...
- Delphi GDI+ 安装方法
[转]Delphi GDI+ 安装方法转自:万一博客(http://www.cnblogs.com/del/)GDI+ 是 Windows 的一个函数库, 来自 Windows\System32\GD ...
- [翻译] Virtual method interception 虚方法拦截
原文地址:http://blog.barrkel.com/2010/09/virtual-method-interception.html 注:基于本人英文水平,以下翻译只是我自己的理解,如对读者造成 ...
- JNI系列——C文件中的方法调用Java中方法
1.创建xxx.jni包并在该包下实现一些Java的方法,和要调用的本地方法 2.实现MainActivity中的按钮点击事件-即点击按钮调用本地的方法 3.在C文件中的方法中回调Java的方法 3. ...
- delphi中locate方法
TDataSet控件以及它的继承控件,例如TSimpleDataSet/TClientDataSet等都可以使用Locate方法在结果数据集中查寻数据.程序首先必须使用SQL命令从后端数据库中取得数据 ...
随机推荐
- Python实战:扫描key完整性
之前在国际版本中,需要支持中英文切换功能,在如此繁多的源文件里要查找源文件里的key是语言资源包是否对应. 正好运用在之前学的python,写了个工具,支持自定义替换标签,批量处理源文件.现在看来,效 ...
- MySQL 高可用架构之MMM
简介 MMM(Master-Master replication manager for MySQL)是一套支持双主故障切换和双主日常管理的脚本程序.MMM使用Perl语言开发,主要用来监控和管理My ...
- iOS App 无代码入侵的方法hook
继续Objective-C runtime的研究 最近公司项目在做用户行为分析 于是App端在某些页面切换,交互操作的时候需要给统计系统发送一条消息 在几十个Controller 的项目里,一个一个地 ...
- java中类继承,到底继承了什么?
继承的最大好处就是为了实现代码的复用.那么,子类到底从父类得到的什么呢? 实例成员 父类的private成员不会被子类继承,子类不能访问.但是子类对象的确包含父类的私有成员. 父类的 包访问成员 继承 ...
- 基于ssh框架开发的购物系统的质量属性
根据前面的博客,我们已经大致了解了ssh架构开发整体概念:Struts是一个实现了MVC模式的经典的框架:Hibernate是轻量级Java EE应用的持久层解决方案,以面向对象的方式提供了持久化类到 ...
- 用NotePad如何实现大小写转换
1.小写转换大写 Ctrl + shift + U 2.大写转换小写 Ctrl + U
- Createjs学习一
需求1:根据后端返回过来的不同信息,实现长按保存图与文字片功能(图片都是一样的,文字信息不同) 首先我们来分析一下要求,得出需要用到哪些技术.长按保存这一功能只针对图片,文字长按的话只会出现复制.. ...
- 如何安装并使用hibernate tools
参考资料:http://radiumwong.iteye.com/blog/358585 http://linjia880714.iteye.com/blog/859334 Hibernate Too ...
- css重置reset.css
body, h1, h2, h3, h4, h5, h6, hr, p, blockquote,dl, dt, dd, ul, ol, li,pre,form, fieldset, legend, b ...
- 使用SSIS汇集监控数据
1.背景 数据库服务器部署有各类巡检脚本,现在想把巡检收集到的数据汇集到一起.Source源对应的是各业务数据库服务器,Destination目标对应的是保存汇集数据的服务器.前期部署的时候已将巡检相 ...