栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

在OS X Java应用程序中处理自定义URL方案

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

在OS X Java应用程序中处理自定义URL方案

对于目标C,可以在这里找到答案:通过注册的URL方案启动OSX应用程序时,如何访问完整的URL?

Java的解决方案是将ObjC代码重写为纯C,然后借助下的一组类将其转换为Java

org.eclipse.swt.internal.cocoa.*

作为ObjC到C转换的参考,我们需要Apple的Objective-
C运行时参考

普通C版本

首先,让我们翻译

[[NSAppleEventManager sharedAppleEventManager]    setEventHandler:targetObject        andSelector:@selector(handleAppleEvent:withReplyEvent:)      forEventClass:kInternetEventClass         andEventID:kAEGetURL];

到普通C中。要在普通C中调用ObjC函数,我们使用

objc_msgSend()
。此外,
@selector(method_footprint)
用代替,用
sel_registerName("method_footprint")
查找类
objc_getClass()
。类型
id
SEL
等效于指针(例如void
)或完整大小的int(即与void 相同的大小)。

结果:

// id mgr = [NSAppleEventManager sharedAppleEventManager]SEL sel_ sharedAppleEventManager = sel_registerName("sharedAppleEventManager");id mgr = objc_msgSend (objc_getClass("NSAppleEventManager"), sharedAppleEventManager);// and the restSEL sel_setEventHandler = sel_registerName("setEventHandler:andSelector:forEventClass:andEventID:");SEL sel_handleAppleEvent = sel_registerName("handleAppleEvent:withReplyEvent:");objc_msgSend (mgr, sel_setEventHandler, targetObject, sel_handleAppleEvent, kInternetEventClass, kAEGetURL);

如您所见,我们在这里有两个子例程调用:第一个调用该类的

sharedAppleEventManager
消息,从
NSAppleEventManager
该类中检索一个单例对象。第二个调用是将setEventHandler
…消息发送到该对象,并传递4个参数(目标对象,目标消息和两个事件说明符)。

回调函数的声明,最初是:

- (void)handleAppleEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent

在纯C中看起来像这样:

void handleAppleEvent (id self, SEL selector, NSAppleEventDescriptor* event, NSAppleEventDescriptor* replyEvent)

这意味着调用该函数时,不仅会发送其对象引用(id),而且还会发送其方法足迹(选择器)。

在ObjC中,回调代码如下所示以获取URL:

NSString url = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];

在纯C中:

id desc_id = objc_msgSend (event_id, sel_registerName("paramDescriptorForKeyword:"), '----');id url_id = objc_msgSend (desc_id, desc_id, sel_registerName("stringValue"));

仍然缺少一部分:

targetObject
需要在调用上面的代码之前进行初始化,并且
handleAppleEvent:withReplyEvent:
需要在该目标对象中创建与足迹匹配的方法,然后将其链接到我们的普通C事件处理程序(
handleAppleEvent()
)。

这意味着我们必须创建一个Objective C类,向其添加一个方法,然后为其创建一个对象实例:

// create an NSObject subclass for our target objectchar objcClassName[] = "ObjCAppleEventHandler";id objcClass = objc_allocateClassPair (objc_getClass("NSObject"), objcClassName);// add the callback method to the classSEL sel_handleAppleEvent = sel_registerName("handleAppleEvent:withReplyEvent:");class_addMethod (objcClass, sel_handleAppleEvent, handleAppleEvent, "i@:@@");// register the classobjc_registerClassPair (objcClass)// create an object instanceid targetObject = class_createInstance (objcClass, 0);// ... here follows the above pre with the setEventHandler invocation// (note: `SEL sel_handleAppleEvent` appears twice - the 2nd one can be removed)

到此结束纯C版本。

(注意:上面的代码未经测试就编写,因此可能包含错误。但是,下面的Java代码已经过测试。)

Java版本

从Plain C到Java的转换现在非常简单。

前面提到的ObjC Runtime函数都可以从org.eclipse.swt.internal.cocoa.OS获得。

首先,一些预设:

static final long class_NSAppleEventManager = OS.objc_getClass("NSAppleEventManager");static final long sel_sharedAppleEventManager = OS.sel_registerName("sharedAppleEventManager");static final long sel_setEventHandler = OS.sel_registerName("setEventHandler:andSelector:forEventClass:andEventID:");static final long sel_handleAppleEvent = OS.sel_registerName("handleAppleEvent:withReplyEvent:");static final long sel_paramDescriptorForKeyword = OS.sel_registerName("paramDescriptorForKeyword:");static final long sel_stringValue = OS.sel_registerName("stringValue");static final long kInternetEventClass = 0x4755524C; // 'GURL'static final long kAEGetURL = 0x4755524C; // 'GURL'static final long kCoreEventClass = 0x61657674; // 'aevt'static final long kAEOpenApplication = 0x6F617070; // 'oapp'static final long kAEReopenApplication = 0x72617070; // 'rapp'static final long keyDirectObject = 0x2d2d2d2d; // '----'

回调函数:

static long handleAppleEvent (long id, long sel, long event_id, long reply_id) {    // This is a handler for AppleEvents that are registered with [NSAppleEventManager setEventHandler:...]    // It matches this selector (footprint):    //   - (void)handleAppleEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)reply    // Invoke [[event paramDescriptorForKeyword:keyDirectObject] stringValue] to get the direct object containing the URL    long direct_desc_id = OS.objc_msgSend (event_id, sel_paramDescriptorForKeyword, keyDirectObject);    long direct_str_id = OS.objc_msgSend (direct_desc_id, sel_stringValue);    NSString nsStr = new NSString (direct_str_id);    String str = nsStr.getString();    // now 'str' contains the URL    System.out.println ("handleAppleEvent invoked -- argument: "+url);    return 0;}

和注册回调函数的代码:

// Get access to a callback function for receiving the sel_handleAppleEvent messageaeCallback = new Callback(Main.class, "handleAppleEvent", 4);long aeProc = aeCallback.getAddress();// Create a ObjC class that provides a method with the sel_handleAppleEvent footprintString objcClassName = "ObjCAppleEventHandler";long objcClass = OS.objc_allocateClassPair(OS.class_NSObject, objcClassName, 0);OS.class_addMethod(objcClass, sel_handleAppleEvent, aeProc, "i@:@@");OS.objc_registerClassPair(objcClass);long objcHandlerInstance = OS.class_createInstance (objcClass, 0);// Invoke [[NSAppleEventManager sharedAppleEventManager] setEventHandler:objcHandlerInstance andSelector:sel_handleAppleEvent forEventClass:kInternetEventClass andEventID:kAEGetURL]long sharedAppleEventMgr = OS.objc_msgSend (class_NSAppleEventManager, sel_sharedAppleEventManager);OS.objc_msgSend (sharedAppleEventMgr, sel_setEventHandler, objcHandlerInstance, sel_handleAppleEvent, kInternetEventClass, kAEGetURL);

剩下要做的就是根据此代码构建应用程序捆绑包,然后将CFBundleURLTypes条目添加到其Info.plist中。

完整的示例源文件可以在这里下载:http : //files.tempel.org/Various/ObjectiveC-
bridging.java.zip



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/497911.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号