6.2 在Windows命令行中创建Hello World! Activity
在这一节中您将使用Windows命令行界面来编辑项目文件。这些项目文件由前一节中所述的ActivityCreator.bat创建。您将在不使用Eclipse的情况下编辑这些文件并增加代码.
6.2.1 编辑项目文件
使用任意一种XML editor打开main.xml(如果您没有XML Editor也可以使用记事本)。使用它,您可以编辑文件和从中移除有关<TextView/>的 定义。如下图,保存main.xml 。
保存后的main.xml是一个空的框架。这提供了一个平台使您可以编辑自己的<activity>.java文件。<activity>.java文件在较深一点的目录里, AndroidHelloWorld\src\android\programmers\guide。
为了创建您的Hello World! 应用程序,增加如下的代码以创建、设置和使用一个TextView:
/**Hello World JFD */
/**BEGIN */
/**Create TextView */
TextView HelloWorldTextView = new TextView(this);
/**Set text to Hello World */
HelloWorldTextView.setText("Hello World!");
/**Set ContentView to TextView */
setContentView(HelloWorldTextView);
/**END */
不要忘记在文件的开头增加TextView包。
import android.widget.TextView;
完成后的HelloWorldCommandLine.java文件看起来像是这样:
这样,您的项目文件就已经完成,您可以编译这个程序并在Android Emulator中运行。
6.2.2 增加JAVA_HOME变量
当您保存后的main.xml是一个空的框架。这提供了一个平台使您可以编辑自己的<activity>.java文件。<activity>.java文件在较深一点的目录里, AndroidHelloWorld\src\android\programmers\guide。
在开始编译以前,您需要在您的PC上增加一个环境变量—JAVA_HOME,它指向JDK(译者注:不是JRE)目录。即使JDK目录已经被包含在您的PATH变量中,您仍需要创建这个JAVA_HOME这个新的环境变量。
注:并不仅仅是在命令行方式下才需要JAVA_HOME变量,如果您只适用Eclipse,您也要增加它。
1. 右键点击“我的电脑”并选择属性
2. 在“系统”属性窗口中选择“高级”选项卡,点击“环境变量”按钮。这将打开一个“环境变量”窗口。
3. 点击“新增”按钮,增加一个新的变量,命名为JAVA_HOME。它的值应该是您的Java SDK完整路径
6.2.3 编译和安装应用程序
现在我们开始实际的实验。您可以使用ANT来编辑您的命令行项目了。完成以后,您将要把它安装在Emulator上。
6.2.3.1 使用ANT编译项目
当您已经增加了JAVA_HOME环境变量,并且在PATH环境变量中已经加入了ANT工具的路径后,您就可以找到包括build.xml的目录,并且简单的运行ant命令。打开一个Windows命令提示窗口,并运行ant。
运行的结果是将会生成.apk文件,它可以直接安装到您的手机或Emulator上。使用Eclipse时,它会自动安装.apk到Emulator上,这里,您需要手动安装。您将会使用the Android Debug Bridge (adb)工具来安装应用程序,这将在下一节中讨论。
6.2.3.2 如果ant产生了错误…
如果在运行ant时产生了错误,不要害怕。因为在本书写作时,Android仍处在初级的阶段,一些部分仍然需要微调。当您使用新技术时,这里或那里做一些小的改动是难免的。当我试图运行ant编译我的项目时,我遇到了如下所示的错误。
在Google Android开发者论坛中对于这个问题的研究给出了这样一个有趣的解决方案:重写build.xml,调整额其中的一些命令。下面是修改过的build.xml,关键的修改使用了粗体。比较这个文件与原始文件,您会发现明显的差别。
<?xml version="1.0" ?>
<project name="HelloWorldCommandLine" default="package" basedir=".">
<property name="sdk-folder" value="c:\Android\android-sdk_m5
rc14_windows\android-sdk_m5-rc14_windows" />
<property name="android-tools" value="c:\Android\android-sdk_m5
rc14_windows\android-sdk_m5-rc14_windows\tools" />
<property name="android-framework" value="${android-tools}/lib/framework.aidl"
/>
<!-- The intermediates directory -->
<!-- Eclipse uses "bin" for its own output, so we do the same. -->
<!-- Use full path for output dir - FIX - BLOCK START -->
<property name="outdir" value="${basedir}/bin" />
<!-- Use full path for output dir - FIX - BLOCK END -->
<!-- No user servicable parts below. -->
<!-- Input directories -->
<property name="resource-dir" value="res" />
<property name="asset-dir" value="assets" />
<property name="srcdir" value="src" />
<!-- Output directories -->
<property name="outdir-classes" value="${outdir}/classes" />
<!-- Create R.java in the source directory -->
<property name="outdir-r" value="src" />
<!-- Intermediate files -->
<property name="dex-file" value="classes.dex" />
<property name="intermediate-dex" value="${outdir}/${dex-file}" />
<!-- The final package file to generate -->
<property name="out-package" value="${outdir}/${ant.project.name}.apk"/>
<!-- Tools -->
<property name="aapt" value="${android-tools}/aapt" />
<property name="aidl" value="${android-tools}/aidl" />
<condition property="dx" value="${android-tools}/dx.bat" else="${android
tools}/dx" >
<os family="windows"/>
</condition>
<property name="dx" value="${android-tools}/dx" />
<property name="zip" value="zip" />
<property name="android-jar" value="${sdk-folder}/android.jar" />
<!-- Rules -->
<!-- Create the output directories if they don't exist yet. -->
<target name="dirs">
<mkdir dir="${outdir}" />
<mkdir dir="${outdir-classes}" />
</target>
<!-- Generate the R.java file for this project's resources. -->
<target name="resource-src" depends="dirs">
<echo>Generating R.java...</echo>
<exec executable="${aapt}" failοnerrοr="true">
<arg value="compile" />
<arg value="-m" />
<arg value="-J" />
<arg value="${outdir-r}" />
<arg value="-M" />
<arg value="AndroidManifest.xml" />
<arg value="-S" />
<arg value="${resource-dir}" />
<arg value="-I" />
<arg value="${android-jar}" />
</exec>
</target>
<!-- Generate java classes from .aidl files. -->
<target name="aidl" depends="dirs">
<apply executable="${aidl}" failοnerrοr="true">
<fileset dir="${srcdir}">
<include name="**/*.aidl"/>
</fileset>
</apply>
</target>
<!-- Compile this project's .java files into .class files. -->
<target name="compile" depends="dirs, resource-src, aidl">
<javac encoding="ascii" target="1.5" debug="true" extdirs=""
srcdir="."
destdir="${outdir-classes}"
bootclasspath="${android-jar}" />
</target>
<!-- Convert this project's .class files into .dex files. -->
<target name="package-dex" depends="dex, package-res">
<echo>Packaging dex...</echo>
<exec executable="${zip}" failοnerrοr="true">
<!--<arg value="-Xmx384M" />-->
<!-- Move Xmx parameter to dx.bat - FIX - BLOCK END -->
<arg value="--dex" />
<arg value="--output=${intermediate-dex}" />
<arg value="--locals=full" />
<arg value="--positions=lines" />
<arg path="${outdir-classes}" />
</exec>
</target>
<!-- Put the project's resources into the output package file. -->
<target name="package-res-and-assets">
<echo>Packaging resources and assets...</echo>
<exec executable="${aapt}" failοnerrοr="true">
<arg value="package" />
<arg value="-f" />
<arg value="-c" />
<arg value="-M" />
<arg value="AndroidManifest.xml" />
<arg value="-S" />
<arg value="${resource-dir}" />
<arg value="-A" />
<arg value="${asset-dir}" />
<arg value="-I" />
<arg value="${android-jar}" />
<arg value="${out-package}" />
</exec>
</target>
<!-- Same as package-res-and-assets, but without "-A ${asset-dir}" -->
<target name="package-res-no-assets">
<echo>Packaging resources...</echo>
<exec executable="${aapt}" failοnerrοr="true">
<arg value="package" />
<arg value="-f" />
<arg value="-c" />
<arg value="-M" />
<arg value="AndroidManifest.xml" />
<arg value="-S" />
<arg value="${resource-dir}" />
<!-- No assets directory -->
<arg value="-I" />
<arg value="${android-jar}" />
<arg value="${out-package}" />
</exec>
</target>
<!-- Invoke the proper target depending on whether or not
an assets directory is present. -->
<!-- TODO: find a nicer way to include the "-A ${asset-dir}" argument
only when the assets dir exists. -->
<target name="package-res">
<available file="${asset-dir}" type="dir"
property="res-target" value="and-assets" />
<property name="res-target" value="no-assets" />
<antcall target="package-res-${res-target}" />
</target>
<!-- Put the project's .class files into the output package file. -->
<target name="package-java" depends="compile, package-res">
<echo>Packaging java...</echo>
<jar destfile="${out-package}"
basedir="${outdir-classes}"
update="true" />
</target>
<!-- Put the project's .dex files into the output package file. -->
<target name="package-dex" depends="dex, package-res">
<echo>Packaging dex...</echo>
<exec executable="${zip}" failοnerrοr="true">
<arg value="-qj" />
<arg value="${out-package}" />
<arg value="${intermediate-dex}" />
</exec>
</target>
<!-- Create the package file for this project from the sources. -->
<target name="package" depends="package-dex" />
</project>
修改完成以后,您可以再次运行ant。
6.2.3.3 使用adb安装应用程序
运行Emulator的第一步,是在Android /tools文件集中,找到emulator.exe文件并执行它。这将启动一个Android服务器。运行Emulator也就是在您的PC上运行了一个虚拟的手机。您可以使用不同的工具与服务器交互,以完成诸如安装程序和调用一个Shell环境等事情。
为了将命令行方式产生的应用程序安装到Android服务器,您需要使用adb。abd是与Android服务器进行通信的工具。adb包括了很多有用的功能,允许您与Android服务器进行交互,其中一个就是安装程序。
表6-1列出了adb的命令集
打开一个Windows命令提示窗口,找到build.xml所在目录,用于安装程序的adb命令格式如下:
adb install <apk path>
如果安装正确,您可以看到adb返回程序包的大小。
切换回到Android Emulator,您现在应该可以在手机中看到安装的程序。
6.2.3.4 如果运行程序产生错误…
我第一次运行这个程序时,我在Android Emulator上看到了错误消息,它告诉我缺少了一class。
注:您可能不会遇到这个错误,或者遇到不同的错误,这决议于本书出版时可用的Android SDK。您应该遵循这里给出的解决问题的步骤,在后面的项目中,这会很有帮助。
这个错误看起来是我的Class莫名其妙的从HelloWorldCommandLine.apk文件中丢失了,我可以简单的解决这个问题,而不必使用任何Android SDK命令行工具。
事实上,.apk文件就是.zip文件。这就是说,您可以使用一个.zip解压缩工具打开并且查看其中的文件。我使用WinRAR打开了HelloWorldCommandLine.apk文件。
文件中缺少部分是classes.dex,这是已编译的Dalvik执行程序。在我的Android项目中找到bin目录,我可以看到ANT已经成功编译并创建了classes.dex文件。我将它在WinRAR中拖入HelloWorldCommandLine.apk,这样classes.dex便加入了我的.apk文件,我保存并关闭了这个文件。
6.2.3.5 卸载一个Activity的旧版本
当将这个文件增加到运行中的Android server以前,您将先卸载HelloWorldCommandLine之前的版本。.这一步倒不是必须的,只是这可以让我们了解与Android server交互的更多过程。
保存Android Emulator的运行状态,回到命令行环境并运行adb shell,它会打开一个Android server的交互环境。如果您完成了,您的命令行提示的形式应该从a >变为 a #,现在您就有了一个与Android server通信的Shell了。有许多的功能可以在这里运行,现在我们关注的是如何移除旧的HelloWorldCommandLine.apk文件。
提示:注意Android是一个操作环境,您在这个shell中可以运行命令是标准的POSIX命令。
在Android服务器上,用户安装的程序位置/data/app目录。使用cd命令,找到app目录。
运行ls命令列出这个目录下的所有文件。您应该看见HelloWorldCommandLine.apk文件。您可以使用rm HelloWorldCommandLine.apk 来删除它。如果运行正确,不会有反馈输出。随后再使用ls可以看到文件已被删除。
注意:因为从技术上说,您是通过shell登录了一个Linux服务器,在shell中所有的命令都是对大小写敏感的。
程序删除以后,键入exit离开shell并返回到命令行提示。
6.2.3.6 重新安装并与运行程序
您现在可以使用adb install重新安装程序:
adb install HelloWorldCommandLine.apk
完成以后,切换回到Emulator,运行程序。它应该是可以正确运行,如下图所示。
现在我们已经完成了在Windows上创建和编辑文件的过程,让我们看一下在Linux上这个过程是如何进行的。即使您是一位铁板Windows 用户,您也可以关注下面这一节。我发现这于对使用开源工具来编程是有一定好处的。
译者注:在较新版本SDK中,运行ant工具并不能完成编译任务。而是要辅以一些参数才可以。
比如ant release 会生成apk文件,不过这个apk因为没有签名而不能被安装到任何设备即使是emulator上;使用ant install则完成编译后直接将apk安装到运行中的Emulator上。