- 如何将现有分段的 MIDP 项目移植到 NetBeans
- 如何使用 IDE 的内置设备破碎解决方案
本教程使用的示例程序是流行的 J2ME 游戏 "Marv The Miner",这是在 GPL 下发布的程序,并且编写为在几个不同的移动平台上运行。
完成本教程大约需要两个小时的时间,并且包括以下主题:
- 从现有 MIDP 项目导入源。
- 创建和定制每个分发 Jar 的项目配置。
- 标记特定于每个配置的源代码段。
- 为项目生成几个分发 Jar。
- 通过 IDE 使用外部仿真器。
要完成本教程,您需要 MarvTheMiner_120_all.zip 文件,该文件包含此程序的原始源文件。单击此处,下载“Marv the Miner v1.2.0(包括级别编辑器)”,以获得源文件。
- 设置环境
- 获取所需源文件
- 在 NetBeans 中开发 Marv The Miner 应用程序
- 生成和执行 Marv the Miner 应用程序
- 深入探讨配置
- 使用不符合 UEI 的仿真器平台
设置环境
此节介绍如何在开始本教程之前对系统进行设置。
获取并安装所需软件 |
示例所需的软件如下:
使用下载站点提供的说明安装该软件。
|
启动 IDE |
要启动 NetBeans IDE,请执行以下操作:
- 在 Microsoft Windows 上
选择“开始”>“程序”>“NetBeans版本”> "NetBeans IDE"。
- 在 UNIX 或 Linux 环境上
在终端窗口中,键入 sh IDE-install-path/bin/runide.sh
IDE-install-path 变量代表 IDE 起始目录的路径。 |
获取所需源文件 |
MarvTheMiner_120_all.zip 文件包含原始 Marv The Miner 应用程序的源文件。该 zip 包括一个 MarvTheMiner 目录,其中包含您将在本教程中使用的 src 和 res 子目录。
要解压缩 MarvTheMiner_120_all.zip 文件,请执行以下操作:
- 在您的文件系统中,创建一个临时位置,用于放置 MarvTheMiner_120_all.zip 的内容。
例如,在本教程中,该目录指的是 C:\temp 目录。
- 使用用于解压缩文件的应用程序将 MarvTheMiner_120_all.zip 文件解压缩到 temp 目录。
temp 目录现在拥有 MarvTheMiner 目录,其中包含以下文件和子目录:
文件或子目录 |
描述 |
src |
构成 Marv The Miner 程序的源文件。 |
res |
包含该程序所使用的资源文件。其中包括图,以及用于定义游戏级别布局的 .map 文件。 |
MarvEditor |
级别编辑器(不在本教程的讨论范围之内)。 |
Nokia.full |
该游戏的 Nokia 生成形式。 |
MIDP.full |
该游戏的一般 MIDP 生成形式。 |
- 将 res 目录移动到 C:/temp/MarvTheMiner_120_all/src/。为了在创建新的 NetBeans 项目之后确保资源文件保持正确的相对路径,可以使用这种简单的解决方法。
|
在 NetBeans IDE 中开发 Marv The Miner 应用程序
本节介绍如何在 NetBeans IDE 中设置和使用现有项目源。
导入现有源
创建项目 |
第一步是在 NetBeans IDE 中创建一个新项目。
- 从主菜单中选择“文件”>“新建项目”。
将显示“新建项目”向导。
- 在“类别”列表中选择“移动”。然后选择“来自现有 MIDP 源的移动项目”,并单击“下一步”。
- 如果未使用安装程序安装 NetBeans,则此处将显示一个面板,指导您安装移动平台。按照说明执行操作,并安装某些版本的 Wireless Toolkit。然后单击“下一步”。
- 对于“导入的源的位置”,单击“浏览”按钮并导航至您在解压缩 MarvTheMiner_120_all.zip 文件时创建的 C:/temp/MarvTheMiner_120_all/src 目录。选择 src 目录,然后单击“打开”。单击“下一步”。
- 输入新项目的名称。例如,将其命名为 MarvTheMiner。
- 现在,选择新项目目录所在的目录。确保已选中“设置为主项目”复选框,并单击“完成”。
将创建新项目 MarvTheMiner,并且显示在 IDE 的“项目”标签中。
- 展开 MarvTheMiner 根项目节点,以查看该项目的源和资源。展开 <缺省包> 节点,然后双击 Main.java,以在编辑器中打开该文件。
|
创建项目配置
NetBeans 设备破碎解决方案基于对项目配置的使用。对于一个项目而言,为该项目创建的每个分发 Jar/Jad 都应该拥有一个项目配置。
如果您检查文件 Main.java
,将看到作者支持具有(Nokia 的 FullCanvas)和 Class.forname()
注释组合的多个平台。同时还定义了变量 vendor,该变量用于跟踪运行应用程序的电话。根据此信息,您可以看到他们支持五组不同的电话:
- Nokia Series 60
- 其他 Nokia 产品
- Motorola
- Vodafone
- 其他
同样,您将创建四个配置来处理这些分发之间的差异。
创建配置 |
- 右键单击 MarvTheMiner 项目节点,并选择“属性”。
此时将打开“项目属性”页面,用于控制项目多方面的内容。
- 单击该页顶部的“管理配置”按钮。此时将打开“管理配置”对话框。
- 单击“添加”,然后键入
NokiaSeries60 并按“确定”。
- 对于
Motorola 、Vodafone 和 NokiaOther 重复前面的步骤。单击“关闭”可关闭“管理配置”对话框。
位于“项目属性”页顶部的“项目配置”组合框现在应该包含五种配置。我们马上会使用这些设置,但是现在要向 IDE 添加一些仿真器。 |
向 IDE 添加仿真器 |
要使用已经安装在计算机上的仿真器平台运行项目,首先必须在 IDE 中进行注册。
- 在“项目配置”组合框中选择 "DefaultConfiguration",然后选择“平台”节点。单击“管理仿真器”按钮。将出现“平台管理器”对话框。
请注意,还可以从“工具”>“Java 平台管理器”的主菜单访问该对话框。
- 单击“添加平台”,并导航至安装 Nokia Series 60 仿真器的目录。单击“下一步”。
- 确保仿真器设置检测正确,然后单击“下一步”。
- 如果需要,在此您可以指向该仿真器的源文件和 javadoc 文件。否则,只需单击“完成”,以完成该平台的安装。
-
对于您的机器上已经安装的每个仿真器平台,以及要通过 IDE 使用的每个仿真器平台重复这些步骤。
请注意,IDE 只能检测到符合 UEI 标准的仿真器。遗憾的是,这意味着不能检测开发人员用于 Marv The Miner 的 Motorola 7.5 仿真器。本教程后面的章节将介绍通过 IDE 使用不符合 UEI 的仿真器的解决办法。 |
针对配置定制项目设置 |
可以针对每个项目配置单独定制“项目属性”页上的每个面板。缺省情况下,配置将使用在缺省配置中定义的设置。
- 打开“项目属性”页,并选择“平台”面板。确保在“项目配置”组合框中选中 "DefaultConfiguration"。
- 在“仿真器平台”组合框中选择 "J2ME Wireless Toolkit 2.x"。将单选按钮切换为 CLDC-1.0 和 MIDP-2.0。
缺省情况下,所有配置将使用此仿真器来生成和执行项目。然而,这并不是我们想要的结果,因为代码引用几个特定于平台的库。
- 从“项目配置”组合框中选择 NokiaSeries60 配置。
“平台”面板现在完全灰显。这是因为当前对此面板使用 "DefaultConfiguration" 中的值。
- 取消选中该面板顶部的“使用 "DefaultConfiguration" 中的值”复选框。
该面板中的所有元素现在将处于启用状态。从“仿真器平台”组合框中选择 Series 60 MIDP Concept SKD Beta 0.3.1 Nokia 平台。
如果在各个配置之间进行切换,您将看到,现在除了 NokiaSeries60 配置之外,所有配置都使用在 DefaultConfiguration 中指定的值。如果您更改了“DefaultConfiguration 平台”面板中的任何配置设置,所做的更改将传播到除 NokiaSeries60 之外的所有配置。
- 在“项目配置”组合框中选择 "NokiaOther" 配置。取消选中“使用 "DefaultConfiguration" 中的值”复选框,并选择一个您安装的其他 Nokia 平台。
- 也可以针对 Vodafone 平台重复这些步骤。
- 如上所述,Motorola 7.5 仿真器不符合 UEI,因此不能安装到 IDE 中。然而,为了进行编译,我们仍然可以指向其 API。激活 Motorla 配置,并选择“库和资源”面板。
- 取消选中“使用 "DefaultConfiguration" 中的值”复选框。
- 单击“添加 Jar/Zip”,并导航至
{motorola 安装目录}\Emulator7.5\lib 。选中每个 .zip 文件(使用 Ctrl+ 鼠标),然后单击“打开”。
- 单击“确定”退出项目属性。现在您已经完成项目配置的创建任务。
|
为每个配置创建定制代码块 |
设备破碎解决方案的第二部分是能够指定源文件中的某些代码块,以使其特定于一个或多个配置。通过使用右键单击编辑器上下文菜单中的操作或通过“编辑”>“预处理程序块”菜单可以完成此任务。
- 打开 Main.java,并检查 initStaticData() 方法。此处,该方法确定在运行时中哪些特定于设备的 API 可用,并随后执行相应的操作。这是一个非常智能的解决方案,可以解决设备破碎某些部分的问题。遗憾的是,该解决方案也存在会添加分发 Jar 的大小,从而影响运行时性能及提高源复杂性的问题,并且不能解决所有分段问题(您随后会看到这一点)。
以下是 initStaticData() 的相关部分: vendor = 0;
try
{
// Nokia
Class.forName("com.nokia.mid.sound.Sound");
vendor = 1;
try
{
Class.forName("com.nokia.mid.ui.DeviceControl");
com.nokia.mid.ui.DeviceControl.setLights(0,100);
vendor = 2;
}
catch(Exception ex2){}
}
catch(Exception ex){}
try
{
// Vodafone
Class.forName("com.vodafone.v10.system.device.DeviceControl");
com.vodafone.v10.system.device.DeviceControl.getDefaultDeviceControl().
setDeviceActive(com.vodafone.v10.system.device.DeviceControl.BACK_LIGHT,
true);
vendor = 3;
}
catch(Exception ex){}
try
{
// Motorola
Class.forName("com.motorola.multimedia.Vibrator");
Class.forName("com.motorola.multimedia.Lighting");
com.motorola.multimedia.Lighting.backlightOn();
vendor = 4;
}
catch(Exception ex){}
- 删除所有只涉及确定程序在哪个设备上运行的功能,因此剩下的代码如下:
// Nokia
com.nokia.mid.ui.DeviceControl.setLights(0,100);
// Vodafone
com.vodafone.v10.system.device.DeviceControl.
getDefaultDeviceControl().
setDeviceActive(com.vodafone.v10.system.device.DeviceControl.BACK_LIGHT,
true);
// Motorola
com.motorola.multimedia.Lighting.backlightOn();
现在您拥有与不同配置关联的三个代码块。
- 突出显示特定于 Motorola 的行,然后右键单击编辑器,并选择“预处理程序块”> "Motorola"。
- 对于 Vodafone 块重复此步骤(“预处理程序块”> "Vodafone")。
- 对于 Nokia 代码,选择“预处理程序块”>“管理预处理程序块”。
此时将打开“管理预处理程序块”对话框。
- 选择 "NokiaOther" 和 "NokiaSeries60" 的选项,然后单击“确定”。
这些代码块现在与预处理程序块的页眉和页脚中列出的配置相关联。如果活动配置是预处理程序块页眉和页脚的一部分,则更改项目的活动配置将触发一个预处理程序,该程序将注释或注释掉所基于的块。
- 通过使用主工具栏中的组合框可更改项目的活动配置。
还可以通过从主“生成”菜单中的相同菜单右键单击项目节点 >“设置活动项目配置”> 选择配置,或通过切换主工具栏中的“配置”组合框(如果项目当前是主项目)来完成此操作。
请注意,代码块突出显示的颜色将发生变化,以标识哪些块处于活动状态,哪些块处于非活动状态。活动配置名称也将在代码块的页眉/页脚中突出显示一个不同的颜色。
- 从
beep() 方法中删除 class.forName() 的所有实例。如果还要精简 if 块,则剩下以下代码: if (midlet.muteSound == 0)
{
// Nokia 3650, 7650
com.nokia.mid.sound.Sound sound = new com.nokia.mid.sound.Sound(1000,100);
sound.play(1);
// All other Nokias
com.nokia.mid.sound.Sound sound = new com.nokia.mid.sound.Sound(1000,100);
sound.play(1);
}
if (midlet.useVibra == 1)
{
// Nokia
com.nokia.mid.ui.DeviceControl.startVibra(50,500);
// Vodafone SDK
com.vodafone.v10.system.device.DeviceControl.
getDefaultDeviceControl().
setDeviceActive(
com.vodafone.v10.system.device.DeviceControl.VIBRATION,
true);
vibra_delay = 10;
// Motorola 7.5
com.motorola.multimedia.Vibrator.
setVibrateTone(
com.motorola.multimedia.Vibrator.VIBRATE_LONG);
com.motorola.multimedia.Vibrator.vibrateFor(500);
}
您应该能够将每个块与正确配置相关联。切记将 Nokia 振动控制调用与两个 Nokia 配置相关联。
- run() 方法也包含特定于 Vodafone 的调用。删除 try/catch 块,并将这两行与 Vodafone 配置相关联。
我们马上就能完成任务了。最后一步是以某种方式来处理 Nokia 的 FullCanvas。
- 激活 NokiaSeries60 配置。
- 右键单击 FullCanvas 声明,并选择“创建 If/Else 程序块”(NokiaSeries60)。
- 右键单击第一个块,并添加 NokiaOther。
- 右键单击第二个块,并添加 NokiaOther。
- 第二个块是倒置的块。将此倒置的块类定义更改为 extend Canvas。
完成后,类定义如下:
|
生成和执行 Marv the Miner 应用程序
生成和执行应用程序 |
此时,我们应该能够针对所有配置编译和运行该程序。单击主工具栏上的任何图标将对活动配置执行所选的操作。
- 在主菜单中,选择“生成”>“生成所有主项目配置”。
假设所有项目均已正确设置,现在应该可以生成所有配置了。
如果您不能访问包含正确 API 的一个或多个仿真器平台,则此步骤可能失败。如果出现这种情况,您应该手动注释掉任何对不存在的 API 进行的调用。
如果您未按照这些步骤手动安装不符合 UEI 的仿真器一节中描述的 Motorola 仿真器,则针对 Motorola 配置的预校验将失败。为了在不手动添加仿真器的情况下进行此配置的编译,您可以注释掉所有 motorola API 调用,并从“库和资源”面板中删除 motorola 库。
- 选择 IDE 左上方的“文件”标签,并展开 dist 文件夹。在此文件夹中,您应该拥有包含每个已成功生成配置的 Jar/JAD 的目录,以及代表 DefaultConfiguration 生成的 Jar/Jad。
- 按 F5 可采用当前选定的配置运行该程序。您可以切换配置,并再次按 F5,同时运行该程序的多个版本。
|
5. 深入探讨配置
通过本教程,您可以熟练掌握如何将现有 MIDP 项目导入到 NetBeans 环境中,但是它并未将 IDE 解决的所有设备破碎问题全部列出。以下列举了一些常见问题的更多示例及如何通过 IDE 来解决。
使用不符合 UEI 的仿真器平台
虽然 IDE 只能自动检测符合 UEI 规范的第三方仿真器平台,但是仍然可以使用不符合 UEI 的仿真器。本节介绍具体操作方式。
添加不符合 UEI 的仿真器 |
- 在 userhome 目录中(在 Windows 中的缺省位置为 C:\Documents and Settings\{username}\.netbeans,Linux 中的缺省位置为 /home/{username}/.netbeans),检查 {userhome}\config\Services\Platforms\org-netbeans-api-java-Platform 目录。
此目录包含定义已安装仿真器平台的 xml 文件。您可以为不符合 UEI 的任何仿真器手动创建这些文件。可以在以下网址找到此 xml 文件的 DTD:http://www.netbeans.org/dtds/j2me-platformdefinition-1_0.dtd
- 将以下文件保存为 SDK_4.1_MRI_7.5.xml,以使用本教程所需的 Motorola 7.5 仿真器。请注意,使用 " 是有一定作用的,应按原样保存。
<?xml version='1.0'?>
<!DOCTYPE platform PUBLIC '-//NetBeans//DTD J2ME PlatformDefinition 1.0//EN'
'http://www.netbeans.org/dtds/j2me-platformdefinition-1_0.dtd'>
<platform name="Motorola_7_5"
home="C:\WTK\Motorola\SDK v4.1 for J2ME\Emulator7.5"
type="custom"
displayname="Motorola 7.5"
srcpath=""
preverifycmd=""{platformhome}/bin/preverify.exe"
-classpath "{classpath}" -d "{destdir}"
"{srcdir}""
runcmd="">
<device name="Motorola_7_5" securitydomains="trusted,untrusted"
description="Motorola_7_5">
<configuration name="CLDC" version="1.1" displayname="CLDC"
classpath="${platform.home}/lib/cldc.zip"
dependencies="" default="true"/>
<profile name="MIDP" version="2.0" displayname="MIDP"
classpath=";${platform.home}/lib/midp.zip"
dependencies="" default="true"/>
</device>
</platform>
保存此 XML 文件之后,需要重新启动 IDE。完成操作之后,就可以选择 Motorola 7 5 作为平台,而选择 Motorola_7_5 作为设备。您应该将 Motorola 配置与这个新的平台相关联。请注意,您可能需要删除 {userhome}\var\cache 中的缓存文件,以便检测到手动安装的平台。此外,不应删除也可能位于此处的 mdrstorage 文件夹。
注意 runcmd 特性设置为空字符串。这是因为启动此 Motorola 仿真器的命令将 MIDlet 作为其参数之一来执行。这与 UEI 标准截然不同,IDE 中不能提供直接支持。但是...
-
如果您所使用的仿真器平台所需的信息不会比提供给 UEI 仿真器的信息要多,则可以跳过此步骤。以下信息将提供给 UEI 仿真器:
- 安全域
- 平台类型
- 平台起始目录
- Jad 位置
- Jad 目标目录/Jad 名称
如果您的仿真器需要额外信息(如项目 Jar 的位置或要执行的 MIDlet 的名称),则通过修改位于项目起始目录中的 build.xml 文件可以执行仿真器。
此文件控制所有项目操作。我们在此可以创建一个新目标,该目标不仅可以执行 motorola 仿真器,如果在 Motorola 配置上调用运行操作,则还可以传递所有适当的数据。
向项目的 build.xml 添加以下代码: <target description="Run MIDlet suite." depends="init" name="run">
<condition property="run.motorola">
<!-- arg2 must match the configuration name
you would like to use the special emulator -->
<equals arg1="${config.active}" arg2="Motorola"/>
</condition>
<ant inheritrefs="true" inheritall="true" target="run_normal"/>
<ant inheritrefs="true" inheritall="true" target="run_motorola"/>
</target>
<target description="Run MIDlet suite the normal way." depends="init"
name="run_normal" unless="run.motorola">
<nb-run commandline="${platform.runcommandline}"
securitydomain="${evaluated.run.security.domain}"
execmethod="${run.method}" platformtype="${platform.type}"
platformhome="${platform.home}" device="${platform.device}"
jadurl="${dist.jad.url}" jadfile="${dist.dir}/${dist.jad}"/>
</target>
<target description="Run MIDlet suite for motorola's non-UEI emulator."
depends="init" name="run_motorola" if="run.motorola">
<property name="project.home" location="."/>
<!-- the last arg line contains an value "Miner".
This must match the name of the midlet you want to execute -->
<java dir="${platform.home}/bin"
fork="true"
classname="com.mot.tools.j2me.emulator.Emulator"
classpath="${platform.home}/bin/Emulator.jar;${platform.home}/bin/configtool.jar">
<jvmarg value="-Djava.library.path=${platform.home}/lib"/>
<arg value="-classpath${project.home}/${dist.dir}/${dist.jar}"/>
<arg line="-deviceFile"/>
<arg value="${platform.home}/bin/RESOUR~1/T720I~1.PRO"/>
<arg line="javax.microedition.midlet.AppManager Miner -JSA 1 1"/>
</java>
</target>
因此,只要活动配置是 Motorola,就会运行 run_motorola 目标。否则,将调用 run_normal 目标(使用正常仿真器执行程序)。 |
其中包括 Marv the Miner 教程。