精通Android游戏开发(将本地PC游戏轻松移植到Android的秘技)ch02
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
public static void writeToStream(InputStream in, OutputStream out) throws IOException {
byte[] bytes = new byte[2048];
for (int c = in.read(bytes); c != -1; c = in.read(bytes)) { out.write(bytes, 0, c);
建 Android 项目)对话框。
2
(2) 在这个对话框中,输入一个项目名(此例中为 ch02.Project)。.
(3) 输入一个应用名(此例中应用名为 Chapter2 )。
(4) 输入一个包名(此例中包名为 ch02.project)。
3
(5) 输入一个活动名(此例中的活动名为 MainActivity)。
2
图 2-5 显示了这个项目的文件系统布局。
提示 将项目的源文件(ch02.Project)导入到工作区会很有帮助,这样你能更顺利地完成本章 3
的学习。
这个项目由以下 Java 文件描述。
ch02.project.MainActivity.java :这是向导工具创建的一个文
4
件,应该已经包含在这个项目中。
警告 在Android 1.5及以后版本中,AVD并不包括Google Maps API。如果要构建一个支持地图 的应用,一定要记住这一点。地图应用在Android 1.5 AVD中将无法启动。
下面为示例应用创建一个针对 SDK 1.5 版本的 AVD。 (1) 在 Eclipse Galileo 中,点击 Android 工具条上的黑色电话图标(见图 2-1)。这会打开 Android 虚拟设备管理器(Android Virtual Devices Manager)对话框。 (2) 在这个对话框中,为 AVD 输入一个名字(这个例子中 AVD 名为 droid1.5)。
import jni.Natives;
import android.app.Activity;
5
import android.os.Bundle;
public class MainActivity extends Activity { private static final String LIB = "libch02.so"; private static final String LIB_PATH = "/data/data/ch02.project/files/" + LIB;
(6) 指定一个最小 SDK 版本(此例中为 3)。图 2-4 显示了这个例子完整的 New Android Project
4
对话框。
(7) 点击 Finish(完成)按钮。
5
6
7
28 第 2 章 在 Android 中编译本地代码
图 2-4 本章示例的 New Android Project 对话框
// 加载库 System.load(LIB_PATH);
// 运行 String[] argv = { "MyLib", "arg1", "arg2" };
Natives.LibMain(argv);
} catch (Exception e) { e.printStackTrace();
} }
/** * 写入一个流 * * @param in * @param out * @throws IOException */
器对话框。 (5) 点击 Create AVD(创建 AVD)。
2.1 第一个本地 Android 应用 25
1
2
3
4
5
图 2-2 针对 SDK 1.5 的 Android 虚拟设备管理器对话框设置
提示 应当为AVD创建一个SD卡。对于后面各章的例子,可以用SD卡存储那些庞大的游戏文件
6
(Doom 和 Wolfenstein 3D)。游戏文件不应保存在设备主文件系统中,否则安装一个游戏 之后就会用尽全部空间。
到文件系统中的某个位置。显然最合适的位置就是应用的 files 文件夹(位于/data/data/Package_ Name/files),不过只要允许,完全可以把本地库保存到文件系统的任何其他位置。
警告 不要把共享库存储在SD卡上,因为Android不允许从SD卡运行可执行代码。如果共享库 很大,开发人员往往希望通过把它存储在SD卡上来节省一些空间。不过为了避免麻烦, 最好不要这么做。
2.1 第一个本地 Android 应用 4
要运行本地应用,需要有一个 Android 项目,不过在创建这样一个项目之前,首先必须创建
一个 AVD(Android Virtual Device,Android 虚拟设备)。
2.1.1 创建 AVD
5
在 SDK 1.5 版本中,Google 引入了 AVD 的概念。AVD 就是应用到模拟器映像(emulator image)
/** 活动第一次创建时调用这个方法。 */
6
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
Android 为这个文件指定私有权限(这说明,它只能由应用本身读取)。
代码清单 2-1 本章示例的主活动
4
package ch02.project;
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream;
2.1.3 应用体系结构
下面来考虑希望这个应用完成哪些工作。 我们想要创建一个基本的 Android 应用。在模拟器中运行时,这个应用会创建一个默认视
图,其中显示文本"Hello Chapter2!"。 在这个项目中,我们将创建一个本地文件夹,其中包含相关文件来完成以下任务:
2.1 第一个本地 Android 应用 29
构建静态wk.baidu.com试程序;
7
图 2-5 项目布局
30 第 2 章 在 Android 中编译本地代码 将文件部署到设备来完成测试。 下面将会更详细地分析这些文件,了解它们的具体工作。首先从 Java 层开始讨论。 1. 主活动 ch02.project.MainActivity.java 文件由向导工具创建,是这个应用的入口点。代码清单 2-1 显
// 安装库
System.out.println("Installing LIB: " + LIB);
7
32 第 2 章 在 Android 中编译本地代码
// 将库从 assests 文件夹复制到 files 文件夹:/data/data/PKG_NAME/files writeToStream(getAssets().open(LIB), openFileOutput(LIB, 0));
2.1 第一个本地 Android 应用 31
注意如何安装这个本地库:
1
writeToStream( getAssets().open(LIB), openFileOutput(LIB, 0) );
getAssets().open() 方法会从应用包的 assets 文件夹(存储本地库的位置)打开一个流。 2
7
26 第 2 章 在 Android 中编译本地代码 注意在 Android 1.6 及以后版本中,GUI 稍有改变,如图 2-3 所示。要创建一个 AVD,需要
点击 New(新建)按钮,打开 Create New AVD(创建新 AVD)对话框,输入一个名字,选择一 个固件目标以及 SD 卡大小,然后点击 Create AVD 按钮来创建 AVD。
创建一个本地库,我们将使用 JNI 从 Android 主活动调用这个本地库的主例程;
1
本地库的主例程会调用 Android 项目中的一个 Java 方法(使用 JNI),向 Android Java
层发回一个文本消息。
运行时阶段将在 Java 中使用一个 System.load(path)加载这个库。
然后 writeToStream 方法使用 openFileOutput(LIB, 0)写入这个流,这会打开对应默认应用
文件夹(/data/data/ch02.project/files)的一个输出流。getAssets 和 openFileOutput 都是 Android
系统调用,LIB 是共享库名(libch02.so)。openFileOutput 的第二个参数(0)的作用是命令 3
2.1 第一个本地 Android 应用 23
1
2 第 2 章 在Android中编译本地代码
2
本章中,我们将探讨在 Android 设备中运行的简单本地程序(也称为静态二进制文件)
3
的基础知识。另外你会了解如何构建共享库(动态二进制文件),最后还会学习如何在简单的
Android 项目中调用这个共享库。下面开始本章的学习。
图 2-1 Eclipse 中的 Android 工具条 (3) 选择一个目标 SDK(此例中为 Android 1.5)。 (4) 作为可选步骤,还可以输入一个 SD 卡绝对路径(如果已经有一个 SD 卡),如/home/user/ sdcard.iso,也可以输入一个大小值,如 128 MB。图 2-2 显示了这个例子的 Android 虚拟设备管理
jni.Natives.java:这是一个新文件,包含本地库中将调用的本
地方法,以及 C 库将在 Java 中完成的回调。
必须在本地文件夹中创建以下文件(见图 2-5)。
lib.c:这是本地库的主代码,其中包含所有必要的 JNI 系统调
5
用,从而可以在 Android 与 C 之间来回级联传递信息。
图 2-3 在 Android SDK 1.6 中创建一个新的 AVD
2.1 第一个本地 Android 应用 27
2.1.2 创建 Android 项目
1
有了 AVD,下一个任务就是为本章创建一个项目,步骤如下。
(1) 在主工具条上点击新建 Android 项目图标(见图 2-1)。这会打开 New Android Project(新
示了这个文件的代码。对于这个文件,有几个重要问题需要说明。 你应该知道,应用启动时,会由 Android 调用方法 onCreate(Bundle savedInstance
State)。这个方法完成以下 3 个重要步骤。 把本地库(libch02.so)从应用包的 assets 文件夹安装(其实就是复制)到项目的 files 文 件夹中(位于/data/data/PACKAGE_NAME/files,这里的包名是 ch02.project)。这是 JNI 加载库之前必不可少的一个步骤。 使用 System.load(path)加载本地库。 最后,通过调用本地方法 Natives.LibMain(String[] argv)运行本地库的子例程。 不能直接加载应用包中的本地库,因此,在调用 System.load()之前,必须把本地库复制
testlib.c:这是本地库的一个测试程序。其主函数的目的是确
保本地库不缺少任何符号。
main.c:这是一个静态程序,用来展示如何编译可在 Android
设备中运行的静态本地程序。
6
Makefile:这是这个项目的本地构建文件。它有以下目标:
构建本地库;
构建本地库测试程序;
生成在 Java 和 C 之间来回级联传递信息所需的 JNI 头文件;
的一个配置属性集,使开发人员可以针对 SDK 的特定版本进行开发。AVD 的目标 SDK 版本主要
包括以下几种。
6
Android 1.1:这个目标映射到 Android SDK 1.1 R2 版本。
Android 1.5:这个目标映射到 Android SDK 1.5 R2 版本。
7
24 第 2 章 在 Android 中编译本地代码 Android 1.6:这个目标映射到 Android SDK 1.6 和 2.0 版本。 Google API-1.5 或 1.6:如果构建使用 Google API 的应用(如 Maps 和 Search),就必须使 用这个目标。
byte[] bytes = new byte[2048];
for (int c = in.read(bytes); c != -1; c = in.read(bytes)) { out.write(bytes, 0, c);
建 Android 项目)对话框。
2
(2) 在这个对话框中,输入一个项目名(此例中为 ch02.Project)。.
(3) 输入一个应用名(此例中应用名为 Chapter2 )。
(4) 输入一个包名(此例中包名为 ch02.project)。
3
(5) 输入一个活动名(此例中的活动名为 MainActivity)。
2
图 2-5 显示了这个项目的文件系统布局。
提示 将项目的源文件(ch02.Project)导入到工作区会很有帮助,这样你能更顺利地完成本章 3
的学习。
这个项目由以下 Java 文件描述。
ch02.project.MainActivity.java :这是向导工具创建的一个文
4
件,应该已经包含在这个项目中。
警告 在Android 1.5及以后版本中,AVD并不包括Google Maps API。如果要构建一个支持地图 的应用,一定要记住这一点。地图应用在Android 1.5 AVD中将无法启动。
下面为示例应用创建一个针对 SDK 1.5 版本的 AVD。 (1) 在 Eclipse Galileo 中,点击 Android 工具条上的黑色电话图标(见图 2-1)。这会打开 Android 虚拟设备管理器(Android Virtual Devices Manager)对话框。 (2) 在这个对话框中,为 AVD 输入一个名字(这个例子中 AVD 名为 droid1.5)。
import jni.Natives;
import android.app.Activity;
5
import android.os.Bundle;
public class MainActivity extends Activity { private static final String LIB = "libch02.so"; private static final String LIB_PATH = "/data/data/ch02.project/files/" + LIB;
(6) 指定一个最小 SDK 版本(此例中为 3)。图 2-4 显示了这个例子完整的 New Android Project
4
对话框。
(7) 点击 Finish(完成)按钮。
5
6
7
28 第 2 章 在 Android 中编译本地代码
图 2-4 本章示例的 New Android Project 对话框
// 加载库 System.load(LIB_PATH);
// 运行 String[] argv = { "MyLib", "arg1", "arg2" };
Natives.LibMain(argv);
} catch (Exception e) { e.printStackTrace();
} }
/** * 写入一个流 * * @param in * @param out * @throws IOException */
器对话框。 (5) 点击 Create AVD(创建 AVD)。
2.1 第一个本地 Android 应用 25
1
2
3
4
5
图 2-2 针对 SDK 1.5 的 Android 虚拟设备管理器对话框设置
提示 应当为AVD创建一个SD卡。对于后面各章的例子,可以用SD卡存储那些庞大的游戏文件
6
(Doom 和 Wolfenstein 3D)。游戏文件不应保存在设备主文件系统中,否则安装一个游戏 之后就会用尽全部空间。
到文件系统中的某个位置。显然最合适的位置就是应用的 files 文件夹(位于/data/data/Package_ Name/files),不过只要允许,完全可以把本地库保存到文件系统的任何其他位置。
警告 不要把共享库存储在SD卡上,因为Android不允许从SD卡运行可执行代码。如果共享库 很大,开发人员往往希望通过把它存储在SD卡上来节省一些空间。不过为了避免麻烦, 最好不要这么做。
2.1 第一个本地 Android 应用 4
要运行本地应用,需要有一个 Android 项目,不过在创建这样一个项目之前,首先必须创建
一个 AVD(Android Virtual Device,Android 虚拟设备)。
2.1.1 创建 AVD
5
在 SDK 1.5 版本中,Google 引入了 AVD 的概念。AVD 就是应用到模拟器映像(emulator image)
/** 活动第一次创建时调用这个方法。 */
6
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
Android 为这个文件指定私有权限(这说明,它只能由应用本身读取)。
代码清单 2-1 本章示例的主活动
4
package ch02.project;
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream;
2.1.3 应用体系结构
下面来考虑希望这个应用完成哪些工作。 我们想要创建一个基本的 Android 应用。在模拟器中运行时,这个应用会创建一个默认视
图,其中显示文本"Hello Chapter2!"。 在这个项目中,我们将创建一个本地文件夹,其中包含相关文件来完成以下任务:
2.1 第一个本地 Android 应用 29
构建静态wk.baidu.com试程序;
7
图 2-5 项目布局
30 第 2 章 在 Android 中编译本地代码 将文件部署到设备来完成测试。 下面将会更详细地分析这些文件,了解它们的具体工作。首先从 Java 层开始讨论。 1. 主活动 ch02.project.MainActivity.java 文件由向导工具创建,是这个应用的入口点。代码清单 2-1 显
// 安装库
System.out.println("Installing LIB: " + LIB);
7
32 第 2 章 在 Android 中编译本地代码
// 将库从 assests 文件夹复制到 files 文件夹:/data/data/PKG_NAME/files writeToStream(getAssets().open(LIB), openFileOutput(LIB, 0));
2.1 第一个本地 Android 应用 31
注意如何安装这个本地库:
1
writeToStream( getAssets().open(LIB), openFileOutput(LIB, 0) );
getAssets().open() 方法会从应用包的 assets 文件夹(存储本地库的位置)打开一个流。 2
7
26 第 2 章 在 Android 中编译本地代码 注意在 Android 1.6 及以后版本中,GUI 稍有改变,如图 2-3 所示。要创建一个 AVD,需要
点击 New(新建)按钮,打开 Create New AVD(创建新 AVD)对话框,输入一个名字,选择一 个固件目标以及 SD 卡大小,然后点击 Create AVD 按钮来创建 AVD。
创建一个本地库,我们将使用 JNI 从 Android 主活动调用这个本地库的主例程;
1
本地库的主例程会调用 Android 项目中的一个 Java 方法(使用 JNI),向 Android Java
层发回一个文本消息。
运行时阶段将在 Java 中使用一个 System.load(path)加载这个库。
然后 writeToStream 方法使用 openFileOutput(LIB, 0)写入这个流,这会打开对应默认应用
文件夹(/data/data/ch02.project/files)的一个输出流。getAssets 和 openFileOutput 都是 Android
系统调用,LIB 是共享库名(libch02.so)。openFileOutput 的第二个参数(0)的作用是命令 3
2.1 第一个本地 Android 应用 23
1
2 第 2 章 在Android中编译本地代码
2
本章中,我们将探讨在 Android 设备中运行的简单本地程序(也称为静态二进制文件)
3
的基础知识。另外你会了解如何构建共享库(动态二进制文件),最后还会学习如何在简单的
Android 项目中调用这个共享库。下面开始本章的学习。
图 2-1 Eclipse 中的 Android 工具条 (3) 选择一个目标 SDK(此例中为 Android 1.5)。 (4) 作为可选步骤,还可以输入一个 SD 卡绝对路径(如果已经有一个 SD 卡),如/home/user/ sdcard.iso,也可以输入一个大小值,如 128 MB。图 2-2 显示了这个例子的 Android 虚拟设备管理
jni.Natives.java:这是一个新文件,包含本地库中将调用的本
地方法,以及 C 库将在 Java 中完成的回调。
必须在本地文件夹中创建以下文件(见图 2-5)。
lib.c:这是本地库的主代码,其中包含所有必要的 JNI 系统调
5
用,从而可以在 Android 与 C 之间来回级联传递信息。
图 2-3 在 Android SDK 1.6 中创建一个新的 AVD
2.1 第一个本地 Android 应用 27
2.1.2 创建 Android 项目
1
有了 AVD,下一个任务就是为本章创建一个项目,步骤如下。
(1) 在主工具条上点击新建 Android 项目图标(见图 2-1)。这会打开 New Android Project(新
示了这个文件的代码。对于这个文件,有几个重要问题需要说明。 你应该知道,应用启动时,会由 Android 调用方法 onCreate(Bundle savedInstance
State)。这个方法完成以下 3 个重要步骤。 把本地库(libch02.so)从应用包的 assets 文件夹安装(其实就是复制)到项目的 files 文 件夹中(位于/data/data/PACKAGE_NAME/files,这里的包名是 ch02.project)。这是 JNI 加载库之前必不可少的一个步骤。 使用 System.load(path)加载本地库。 最后,通过调用本地方法 Natives.LibMain(String[] argv)运行本地库的子例程。 不能直接加载应用包中的本地库,因此,在调用 System.load()之前,必须把本地库复制
testlib.c:这是本地库的一个测试程序。其主函数的目的是确
保本地库不缺少任何符号。
main.c:这是一个静态程序,用来展示如何编译可在 Android
设备中运行的静态本地程序。
6
Makefile:这是这个项目的本地构建文件。它有以下目标:
构建本地库;
构建本地库测试程序;
生成在 Java 和 C 之间来回级联传递信息所需的 JNI 头文件;
的一个配置属性集,使开发人员可以针对 SDK 的特定版本进行开发。AVD 的目标 SDK 版本主要
包括以下几种。
6
Android 1.1:这个目标映射到 Android SDK 1.1 R2 版本。
Android 1.5:这个目标映射到 Android SDK 1.5 R2 版本。
7
24 第 2 章 在 Android 中编译本地代码 Android 1.6:这个目标映射到 Android SDK 1.6 和 2.0 版本。 Google API-1.5 或 1.6:如果构建使用 Google API 的应用(如 Maps 和 Search),就必须使 用这个目标。