我想通过双击Mac来启用与我的应用程序关联的文件。这个问题之前曾被问过(很多次),例如参见 Double click document file in Mac OS X to open Java application
然而,看起来自2009年(解决方案发布后)发生了变化。
该解决方案实际上基于2004年的文章
https://today.java.net/pub/a/today/2004/01/05/swing.html
并依赖于两个难题:
1. Java程序应该注册文件打开事件并采取适当的行动。这是使用com.apple.eawt应用程序和应用程序适配器完成的。
2.操作系统需要熟悉扩展,这是通过使用来完成的
CFBundleDocumentTypes包的.plist中的键。
2004 com.apple.eawt中使用的构造是折旧的,正如在几个讨论中提到的那样,包括 What's the alternative to using the now deprecated com.apple.eawt.ApplicationAdapter in Java Swing apps on the Mac? (2月11日) 需要注意的是,OpenFilesHandler取代了折旧的结构。答案中提到的API文档的链接不再起作用,因此不能立即清楚如何使用此构造。 我找到了以下参考资料来解释折旧的原因,但是文档的链接也已经过时了: http://lists.apple.com/archives/java-dev/2012/Jan/msg00101.html
我无法在线找到任何更新的API文档。 Apple Developer站点还引用了X代码中的示例,这些示例在我的版本(5.0.2)
中不存在在(2012)的讨论中 https://stackoverflow.com/questions/8857431/java-mac-jdk-7-beta-apple-application-listener-no-longer-works 在从jdk6切换到jdk7-beta的上下文中提到了OpenFilesEvent,结论是归因于jdk7-beta的一些错误。
最后,同样在2012年,提出了以下问题,其中OpenFilesHandler的使用类似。
Grabbing the openFileEvent on MacOSX (Can't get filename)
这是我能找到的最新帖子,我想重温那里发布的问题。
该线程中有两个答案:第一个建议切换到Java Web Start,这对我来说不是一个选项。第二个答案集中在拼图的第二部分 - 用.plist注册正确的信息。
具体而言,指出了对CFBundleDocumentTypes和UTExportedTypeDeclarations的需求。注册自定义文件扩展名需要后者。
使用app bundler无法灵活地将这些密钥包含在.plist中,因此我尝试在编译.plist生成包之后包含它们。 按照原始帖子的建议,我包括我的info.plist info.plist中:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList- 1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>JavaAppLauncher</string>
<key>CFBundleIconFile</key>
<string>myIcons.icns</string>
<key>CFBundleIdentifier</key>
<string>mypackage.MainClass</string>
<key>CFBundleDisplayName</key>
<string>MyProgram</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>ProgramName</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>NSHumanReadableCopyright</key>
<string>NOTICES.txt</string>
<key>JVMRuntime</key>
<string>jdk1.7.0_21.jdk</string>
<key>JVMMainClassName</key>
<string>mypackage.MainClass</string>
<key>JVMOptions</key>
<array/>
<key>JVMArguments</key>
<array/>
<key>UTExportedTypeDeclarations</key>
<dict>
<key>UTTypeIdentifier</key>
<string>com.myCompany.xxx</string>
<key>UTTypeReferenceURL</key>
<string>http://myCompany.com/xxx.html</string>
<key>UTTypeDescription</key>
<string>My program file</string>
<key>UTTypeIconFile</key>
<array>
<string>myIcons.icns</string>
</array>
<key>UTTypeConformsTo</key>
<array>
<string>com.apple.package</string>
</array>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<string>apn</string>
</dict>
</dict>
<key>CFBundleDocumentTypes</key>
<dict>
<key>CFBundleTypeName</key>
<string>y program file</string>
<key>CFBundleTypeIconFiles</key>
<array>
<string>myIcons.icns</string>
</array>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSHandlerRank</key>
<string>Owner</string>
<key>LSItemContentTypes</key>
<string>com.myCompany.xxx</string>
</dict>
</dict>
</plist>
这个info.plist工作到一定程度:文件确实与应用程序相关联,我可以通过双击打开它们。
唯一剩下的问题是文件不显示与文件关联的图标(任何大小)(无论我如何选择查看文件)。应用程序本身显示图标。我使用生成了一整套图标 iconutil来自png文件的文件夹,如上所述 https://apple.stackexchange.com/questions/59561/where-did-icon-composer-go-from-xcode 有趣的是,在某些时候,这些图标出现了,然后他们停了下来。如果我右键单击该文件,我的应用程序会显示一个图像,但文件本身没有图像。任何关于如何获得这些图像的建议都将受到高度赞赏。
问题似乎与此类似 OSX Custom extension icon Association 建议使用Jar Bundler,这是(据我所知)用AppBundler取代。
我也尝试刷新启动服务 - http://www.tekrevue.com/tip/rebuild-launchservices-fix-duplicate-entries-os-xs-open-menu/ 它没有帮助。
总之,描述的问题 Grabbing the openFileEvent on MacOSX (Can't get filename) 通过使用OpenFilesHandler成功解决,并且由于引入了自定义扩展,因此需要UTExportedTypeDeclarations。 感谢whiskeyspider确认我在正确的轨道上,因为我接近放弃了。唯一未解决的问题是与文件关联的实际图像。
答案 0 :(得分:2)
本回答重点介绍OpenFilesHandler的使用,并假设CFBundleDocumentTypes和UTExportedTypeDeclarations定义包含在Info.plist中(参见问题文本)。
回想一下,在Mac和PC中打开Java应用程序的方法之间存在基本差异,这很有用。在PC的情况下,一个依赖于要打开的文件的直接命令行规范。文件名是从命令行传递给Java程序的参数。因此,需要编写Java程序来接受这个参数并适当地处理它。 PC包装器,例如Inno Setup,提供了一种通过单击文件来调用带有所需参数的Java程序的方法。
相比之下,对于Mac,我们可以利用OpenFilesHandler传递有关需要打开的文件的信息。具体用法如下: Grabbing the openFileEvent on MacOSX (Can't get filename)
在我的实现中,我有一个FileSaving类,它有一个方法readFile,它将类File的实例作为参数,并完成读取文件的实际工作。在程序的主要部分,我有以下代码的相关片段:
public final static boolean SYSTEMISMAC=(System.getProperty("os.name")).startsWith("M"); // treating Mac separately
static protected FileSaving initialFiling;
........
initialFiling = new FileSaving(); // Initializing
if(SYSTEMISMAC){
Application a = Application.getApplication();
a.setOpenFileHandler(new MacFiles(initialFiling) );
}
……………
这里我们称之为实现OpenFilesHandler的Class MacFiles:
import java.io.File;
import java.util.List;
import com.apple.eawt.AppEvent.OpenFilesEvent;
import com.apple.eawt.Application;
import com.apple.eawt.OpenFilesHandler;
public class MacFiles implements OpenFilesHandler{
private List<File> files;
private FileSaving myFiling;
public MacFiles(FileSaving filing) {//
Application.getApplication().setOpenFileHandler(this);
myFiling=filing;
}
public List<File> getFiles() {
return files;
}
@Override
public void openFiles(OpenFilesEvent event) {
files = event.getFiles();
File myFile=new File(files.get(0).getAbsolutePath());
myFiling.readFile(myFile,true);
}
}
从某种意义上说,双击文件会打开它,但是在浏览文件时显示自定义图标的问题(如问题中所述)仍未解决。
答案 1 :(得分:0)
在您提供的Info.plist中,似乎不再支持CFBundleTypeIconFiles的条目。而是尝试使用以下CFBundleTypeIconFile条目替换它,该条目只是一个字符串值而不是数组。
<dict>
<key>CFBundleTypeName</key>
<string>y program file</string>
<key>CFBundleTypeIconFile</key>
<string>myIcons.icns</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSHandlerRank</key>
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>com.myCompany.xxx</string>
</array>
</dict>
我能够使文件关联和自定义图标显示工作,但是,当用户双击相关文件时,我仍然无法获得OpenFilesEvent。它只是将我的应用程序放在前面,尽管设置了所有相关的处理程序,但应用程序没有收到任何事件。
无论如何,我希望我的建议适合你。