Lets say you’re building a stand-alone SWT application (read: not eclipse RCP) and want to use the native OS X help system. You’d like to have the nice Apple Help menu in the menu bar and have your application register a HelpBook that gets indexed by the native help system. A very admirable goal that most developers would assume to be a trivial last step before the ship date.
Trivial depends on one key element in the preceding paragraph and that element is SWT. If I had typed Swing instead, well, you would have found many articles that tell you exactly what you need to do and you wouldn’t be reading this one.
This article walks you through a simple process to get your HelpBook registered properly if you’re developing a stand-alone SWT application.
NOTE - Before preceding, you should already be familiar with deploying Java applications in OS X as application bundles. There are various ways to do this, some better than others, but that is for another article.
The Problem
You google and search Apple’s developer connection site, eventually finding documentation on how to deploy and register your HelpBook.
Most developers, including myself, stop at registering the HelpBookFolder and HelpBookName properties in “Info.plist”. This works great for Cocoa applications, however, if you read a bit further, Apple lays down the money quote -
Carbon applications must call AHRegisterHelpBook even if they do not use any other Apple Help. If a Carbon application does not call AHRegisterHelpBook, the application’s help book does not open when the user chooses the application help item from the Help menu. In addition, Help Viewer does not include the help book in the Library menu.
Apple tells you exactly what you need to know IF you understand that SWT, as of version 3.4 and below, is based on Carbon and therefore your Java application is effectively a Carbon app.
Solution Time
First, make sure you register properties HelpBookFolder and HelpBookName in your Info.plist as described in Apple’s HelpBook documentation. You then need to use JNI so you can call AHRegisterHelpBook from your SWT application.
Java JNI Stub
This class is what you call from your SWT application to force the registration of your helpbook. All you do is call ‘HelpBookCarbon.registerHelpBook()’ at some point in your application’s startup.
package your.package.name;
public class HelpBookCarbon {
static {
System.loadLibrary("HelpBookCarbon");
}
public static native void registerHelpBook();
}
Native Code
Next you’ll need to create a simple native library called “HelpBookCarbon”. I suggest using XCode as its the easiest way to build a unversal binary JNI library.
JNIEXPORT void JNICALL Java_your_package_name_HelpBookCarbon_registerHelpBook(JNIEnv *env, jclass clazz) {
FSRef bundleRef;
CFBundleRef bundle = CFBundleGetMainBundle();
if (bundle == NULL) {
return;
}
CFURLRef bundleUrl = CFBundleCopyBundleURL(bundle);
if (bundleUrl == NULL) {
return;
}
if (CFURLGetFSRef(bundleUrl, &bundleRef)) {
AHRegisterHelpBook(&bundleRef);
}
}
You should end up with a library called ‘libHelpBookCarbon.jnilib’. Place this in your java system library path and you should be good to go. If you’re not familiar with loading JNI libraries, checkout
Sun’s guide to JNI
Other Notes
There are a couple of solutions posted on Apple’s mailing list that are a waste of time if you’re not planning on providing contextual help or controlling the Help viewer from within your application.
One of those is Apple’s Help Hook. While interesting to play with, this does not address the issue at hand - SWT/Carbon applications need to explicitly register their help with a call to AHRegisterHelpBook.
Download
I need to find a good place for providing file downloads. In the meantime, just send me an email, mcoopet@gmail.com, and I’ll send you the universal JNI library / XCode project.