问题
您的 Mac OS X 应用程序包是使用与 Oracle 的 Java 7 包不兼容的应用程序捆绑器创建的。例如,您使用的捆绑器可能Jar Bundler
由 Apple 提供,它仅适用于 Apple 的 Java 6 系统包。
从 Java 7 及更高版本开始,Apple 已放弃对 Java 作为集成系统包的支持。因此,您必须选择 Oracle Java 7 第三方包及其应用程序包捆绑解决方案。这允许您在 Mac OS X 10.7.3 及更高版本上创建和部署基于 Oracle Java 7 的应用程序包。
您面临的潜在技术问题是 Apple 基于本机Objective-C
的JavaAppLauncher
二进制文件,它使用的格式Info.plist
仅适用于 Apple 的 Java 6 System Packages,而JavaAppLauncher
Info.plist
来自 Oracle 的组合仅适用于 Oracle 的 Java 7 Packages。
当您使用JavaAppLauncher
支持 Apple 的 Java 6 系统包时,它将始终选择安装在您的 Mac 上的 Apple Java 6 系统包。
有一个视频,Oracle 的 Java 平台 Mac OS X 端口的首席工程师 Scott Kovatch 在 DEVOXX 上详细讨论了 Oracle Java 7 的应用程序捆绑是如何工作的。
解决方案
创建基于 Mac OS X 10.7.3 及更高版本的应用程序包
及以上,您必须使用 Oracle 的 app bundler
使用 Oracle 的应用程序捆绑器,您现在可以选择使用安装在 Mac 上的默认 Oracle Java 7 包来运行打包的应用程序:
/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/
或您在打包应用程序中内联的 Oracle Java 7 JRE
MyJavaMacOSXApp.app/Contents/PlugIns/
注意:这两种方法各有利弊,但如果您想使用捆绑的应用程序访问 Apple App Store,则需要最后一种方法和您自己的 JRE。
需要做什么
- 下载
appbundler-1.0.jar
并移动到<project>/lib/appbundler-1.0.jar
将以下内容添加到您的<project>/build.xml
<property environment="env" />
<taskdef
name="bundleapp"
classname="com.oracle.appbundler.AppBundlerTask"
classpath="lib/appbundler-1.0.jar" />
<target name="bundle">
<bundleapp
outputdirectory="dist"
name="MyJavaMacOSXApp"
displayname="My Java Mac OS X App"
identifier="com.example.MyJavaMacOSXApp"
shortversion="1.0"
applicationCategory="public.app-category.developer-tools"
mainclassname="com.example.MyJavaMacOSXApp">
<runtime dir="${env.JAVA_HOME}" />
<classpath file="dist/MyJavaMacOSXApp.jar" />
</bundleapp>
</target>
注意:您需要替换MyJavaMacOSXApp
为您的应用程序数据。您可以在此处找到一些其他AppBundlerTask
选项,因为此示例仅以最简单的形式显示它是如何工作的。
运行bundle
目标后,ant bundle
您将MyJavaMacOSXApp.app
在<project>/dist
目录中找到。
<runtime dir="${env.JAVA_HOME}" />
元素是什么?
内联 Oracle Java 7 包 (JRE)
上面的 Ant 目标从您的
进入
MyJavaMacOSXApp.app/Contents/PlugIns
因此,应用程序包是完全独立的,根本不需要在目标系统上安装 Oracle Java 7 包 (JRE)。就像您在以下已部署的屏幕截图中看到的那样MyJavaMacOSXApp.app
:
![MyJavaMacOSXApp 内联 JRE](https://i.stack.imgur.com/jkLgF.jpg)
连接默认 Oracle Java 7 包 (JRE)
如果要使用安装在应用程序包目标 Mac 下的默认 Oracle Java 7 包 (JRE)
/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/
你必须删除
<runtime dir="${env.JAVA_HOME}" />
任务中的元素bundle
。就像您在以下已部署的屏幕截图中看到的那样MyJavaMacOSXApp.app
:
![MyJavaMacOSXApp 内联 JRE](https://i.stack.imgur.com/JpBem.jpg)
来源MyJavaMacOSXApp.java
package com.example;
import java.awt.*;
import javax.swing.*;
public class MyJavaMacOSXApp extends JPanel {
public MyJavaMacOSXApp() {
JLabel versionLabel = new JLabel("java.version=" + System.getProperty("java.version"));
JLabel homeLabel = new JLabel("java.home=" + System.getProperty("java.home"));
setLayout(new BorderLayout());
add(versionLabel, BorderLayout.PAGE_START);
add(homeLabel, BorderLayout.PAGE_END);
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("MyJavaMacOSXApp");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MyJavaMacOSXApp newContentPane = new MyJavaMacOSXApp();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
如果我的应用有多个 jar 文件怎么办?
只需根据需要添加尽可能多的<classpath file="dist/additional.jar" />
条目。
注意:捆绑任务中的元素顺序不会在捆绑应用程序的运行时保留。由本java.class.path
机在运行时构建,因为它从目录JavaAppLauncher
中读取*.jar
s 。MyJavaMacOSXApp.app/Contents/Java
为了完整起见,这Info.plist
看起来像:
<?xml version="1.0" ?>
<!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>GenericApp.icns</string>
<key>CFBundleIdentifier</key>
<string>com.example.MyJavaMacOSXApp</string>
<key>CFBundleDisplayName</key>
<string>My Java Mac OS X App</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>MyJavaMacOSXApp</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></string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.developer-tools</string>
<key>JVMRuntime</key>
<string>jdk1.7.0_17.jdk</string>
<key>JVMMainClassName</key>
<string>com.example.MyJavaMacOSXApp</string>
<key>JVMOptions</key>
<array>
</array>
<key>JVMArguments</key>
<array>
</array>
</dict>
</plist>
此答案基于的重要文件:
- http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/packagingAppsForMac.html
- http://java.net/projects/appbundler/pages/Home
- http://java.net/downloads/appbundler/appbundler.html
- http://intransitione.com/blog/take-java-to-app-store/
- http://www.parleys.com/#st=5&id=2891&sl=37
appbundle 本身也有一个维护良好的分支,具有更多功能和错误修复。