1、第第七七章章 Android NDK Android NDK1主要内容主要内容 7.1 Android NDK7.1 Android NDK简介简介 7.2 7.2 构建构建NDKNDK系统系统 7.3 NDK7.3 NDK开发过程详解开发过程详解2Android NDK 是在SDK前面又加上了“原生”二字,即Native Development Kit,因此又被Google称为“NDK”。Android NDK是Android SDK的伴随工具,可以让用户用诸如C/C+原生编程语言开发Android应用程序。原生SDK的公布可以让开发者更加直接的接触Android系统资源,并极大地提高了An
2、droid应用程序开发的灵活性。Android NDK需要安装全部Android SDK1.5或以上版本,到目前为止Android NDK已经修订了9版本。Android NDK集成了交叉编译器,支持ARM、x86及MIPS处理器指令集、JNI接口和一些稳定的库文件。7.1 Android NDK7.1 Android NDK简介简介3nAndroid NDK具体包括如下:ARM、x86和MIPS交叉编译器构建系统Java原生接口头文件C库Math库POSIX线程最小的C+库ZLib压缩库动态链接库Android NDKAndroid NDK简介简介Android日志库Android像素缓冲区
3、库Android原生应用APIsOpenGL ES 3D图形库Open ES原生音频库OpenMAX AL最小支持4 7.2.1 Android NDK7.2.1 Android NDK开发环境构建开发环境构建 7.2.2 7.2.2 解析解析hello-jnihello-jni例程例程5Android NDK的构建系统是基于GNU Make的,提供了头文件、库和交叉编译器工具链,可以在Microsoft Windows、Apple Mac OS X和Linux三种操作系统平台上运行。在安装前要确保已经最新版的Android SDK和升级应用程序和环境。本书仅介绍Microsoft Windo
4、ws系统的NDK系统构建,请按照下列步骤操作:7.2.1 Android NDK开发环境构建开发环境构建6n第一步,在安装完成SDK工具后,下载并安装Cygwin。n安装完成后,要把Cygwin二进制路径添加到系统可执行搜索路径中。操作如下:在“系统属性”界面打开环境变量对话框;在系统变量部分单击New按钮定义一个新的环境变量,将变量名设置成CYGWIN_HOME,将变量值设置成前面记下的Cygwin安装目录;单击OK按键保存新环境变量;在环境变量对话框中的系统变量列表中,双击PATH变量,并将;%CYGWIN_HOME%bin追加到变量值后面。7.2.1 Android NDK7.2.1 A
5、ndroid NDK开发环境构建开发环境构建7n第二步,下载最新版Android NDK开发包,目前本书编写时,最新版本是R9,请根据需要到Google的官方网站下载Android NDK。http:/ NDK的二进制路径加到系统可执行搜索路径中,具体方法同上。n第三步是配置Cygwin的NDK开发环境。修改在用户目录下的.bash_profile文件,在该文件的末尾处添加如下代码:ANDROID_NDK_ROOT=/cygdrive/d/android/android-nkd-r9dExport ANDROID_NDK_ROOTp上述代码说明Android NDK安装的目录,即d盘的andr
6、oid/android-nkd-r9d目录下。7.2.1 Android NDK7.2.1 Android NDK开发环境构建开发环境构建87.2.1 Android NDK7.2.1 Android NDK开发环境构建开发环境构建所有的Android NDK组件都被安装在目标目录下,下面介绍一些重要文件和子目录。nndk-build:该shell脚本是Android NDK构建系统的起始点。nndk-gdb:该shell脚本允许用GNU调试器调试原生组件。nndk-stack:该shell脚本可以帮助分析原生组件崩溃时的堆栈追踪。nbuild:该目录包含可Android NDK构建系统的所有
7、模块。nplatforms:该目录包含了支持不同Android目标版本的头文件和库文件。Android NDK构建系统会根据具体的Android版本自动引用这些文档。97.2.1 Android NDK7.2.1 Android NDK开发环境构建开发环境构建nsamples:该目录包含了一些示例应用程序,这些程序可以体现Android NDK的性能。示例项目对于学习使用Android NDK的特性很有帮助。nsources:该目录包含了可供开发人员导入到现有的Android NDK项目的一些共享模块。ntoolchains:该目录包含目前Android NDK支持的不同目标机体系结构的交叉编
8、译器。Android NDK目前支持ARM、X86和MIPS体系结构。Android NDK构建系统根据选定的体系结构使用不同的交叉编译器。10n最后测试开发环境是否可以正常工作,首先双击Cygwin图标,出现Cygwin后运行ndk-build出现如图所示的运行结果,说明Android NDK的开发环境已经可以正常工作了。7.2.1 Android NDK7.2.1 Android NDK开发环境构建开发环境构建117.2.2 7.2.2 解析解析hello-jnihello-jni例程例程n首先使用import向Eclipse中导入工程,本机目录为F:android-ndk-r9dsamp
9、leshello-jni。n导入工程之后我们会在项目目录下发现两个比较重要的文件一个是src/com.example.hellojni/HelloJni.java文件,一个是jni/hello-jni.c文件。nhello-jni.c文件定义了输出字符串Hello from JNI!Compiled with ABI ABI.的方法,而HelloJni.java文件则通过调用上述hello.c的动态链接库来获取输出的字符串,并显示到模拟器上。12其中c文件内容如下:10 10 Java_com_example_hellojni_HelloJni_stringFromJNIJava_com_ex
10、ample_hellojni_HelloJni_stringFromJNI(JNIEnvJNIEnv*env,jobjectthizenv,jobjectthiz)11 11 12#if defined(_arm_)12#if defined(_arm_)13#if defined(_ARM_ARCH_7A_)13#if defined(_ARM_ARCH_7A_)14#if defined(_ARM_NEON_)14#if defined(_ARM_NEON_)15#define ABI armeabi-v7a/NEON“15#define ABI armeabi-v7a/NEON“16#e
11、lse16#else17#define ABI armeabi-v7a17#define ABI armeabi-v7a18#endif18#endif19#else19#else20#define ABI 20#define ABI armeabiarmeabi 21#endif21#endif22#elifdefined(_i386_)22#elifdefined(_i386_)23#define ABI x8623#define ABI x8624#elifdefined(_24#elifdefined(_mipsmips_)_)25#define ABI 25#define ABI m
12、ipsmips 26#else26#else27#define ABI unknown27#define ABI unknown28#endif28#endif29 return(29 return(*envenv)-)-NewStringUTFNewStringUTF(envenv,“Hello from JNI!Compiled with ABI”ABI,“Hello from JNI!Compiled with ABI”ABI“.”);“.”);这里主要的是这里主要的是定义了输出字定义了输出字符串符串Hello from JNI!Compiled with ABI ABI.的方法的方法1
13、37.2.2 7.2.2 解析解析hello-jnihello-jni例程例程其中其中javajava文件内容如下文件内容如下:5 public class 5 public class HelloJniHelloJni extends Activity extends Activity6 public void 6 public void onCreateonCreate(Bundle(Bundle savedInstanceStatesavedInstanceState)7 7 super.onCreatesuper.onCreate(savedInstanceStatesavedInst
14、anceState););8 8 TextViewtvTextViewtv=new =new TextViewTextView(this);(this);9 9 tv.setTexttv.setText(stringFromJNIstringFromJNI();();10 10 setContentViewsetContentView(tv tv););11 public native String 11 public native String stringFromJNIstringFromJNI();();12 public native String 12 public native S
15、tring unimplementedStringFromJNIunimplementedStringFromJNI();();13 static 13 static 1414 System.loadLibrarySystem.loadLibrary(hello-(hello-jnijni););15 15 16 16 通过调用上述hello.c的动态链接库来获取输出的字符串,并显示到模拟器上。n 147.2.2 7.2.2 解析解析hello-jnihello-jni例程例程n接 着 启 动 C y g w i n 命 令 行 输 入 c d f:/a n d r o i d-n d k-r
16、9d/samples/hello-jni进入到NDK 主目录,然后编译C代码,其命令如下:././ndk-build,在Cygwin中显示如图所示。157.2.2 7.2.2 解析解析hello-jnihello-jni例程例程n此时表明已生成所需的动态链接库,接下来我们要对其进行加载。n在Eclipse的Project Explorer 视图中右击HelloJni,依次选择Android tools、Add Native Support在弹出的对话框中显示信息如图所示。由于该项目已经包含了一个原生项目,所以库名可以保持不变,点击finish即可完成加载。n在Android模拟器上运行该项目,
17、其运行效果如下:16 7.3.1 7.3.1 中间件概念中间件概念 7.3.2 Android7.3.2 Android系统的中间件系统的中间件 7.3.3 7.3.3 使用使用C/C+C/C+实现本地方法实现本地方法 7.3.4 7.3.4 依赖关系建立依赖关系建立 7.3.5 NDK7.3.5 NDK程序的链接与运行程序的链接与运行17nAndroid NDKAndroid NDK构建系统所提供的不同功能,例如构建系统所提供的不同功能,例如n建立一个共享库建立一个共享库n建立多种共享库建立多种共享库n建立静态库建立静态库n利用共享库通用模块利用共享库通用模块n在多种在多种NDKNDK项目间
18、共享模块项目间共享模块n使用预建库使用预建库n建立独立的可执行文件建立独立的可执行文件n其他构建系统变量和宏其他构建系统变量和宏n定义新变量和条件操作定义新变量和条件操作18n在进行NDK开发时,一般需要同时建立Android工程和C/C+工程,然后使用NDK编译C/C+工程,形成可以被调用的共享库,最后共享库文件会被拷贝到Android工程中,并被打包到apk文件中。其开发过程可分为以下几步:设计JNI接口用C/C+实现本地的方法编译文件的实现生成动态连接库。19中间件(Middleware)是处于操作系统和应用程序之间的软件,它包括一组服务,以便于运行在一台或多台机器上的多个软件通过网络进
19、行交互。该架构通常用于支持分布式应用程序并简化其复杂度,它包括web服务器、事务监控器和消息队列软件。中间件能够屏蔽操作系统和网络协议的差异,为应用程序提供多种通讯机制;并提供相应的平台以满足不同领域的需要。中间件带给应用系统的,不只是开发的简便、开发周期的缩短,也减少了系统的维护、运行和管理的工作量,还减少了计算机总体费用的投入。7.3.1 7.3.1 中间件概念中间件概念20u中间件是操作系统与应用程序的沟通桥梁,并分为两层:函数层(Library)和虚拟机(Virtual Machine)。应用程序用Java语言开发,操作系统代码则是C代码,它们之间的通信需要用JNI来实现。JNI一般有
20、以下一些应用场景:高性能,在一些情况下因为处理运算量非常大,为了获取高性能,直接高性能,在一些情况下因为处理运算量非常大,为了获取高性能,直接使用使用javajava是不能胜任的,如:一些图形的处理;是不能胜任的,如:一些图形的处理;调用一些硬件的驱动或者一些软件的驱动,比如调用一些外部系统接口调用一些硬件的驱动或者一些软件的驱动,比如调用一些外部系统接口的驱动,如:读卡器的驱动,的驱动,如:读卡器的驱动,OCIOCI驱动;驱动;需要使用大内存,远远超过需要使用大内存,远远超过VMVM所能分配的内存,如:进程内所能分配的内存,如:进程内CacheCache;调用调用C C或者操作系统提供的服务
21、,如:或者操作系统提供的服务,如:javajava调用搜索服务,搜索是由调用搜索服务,搜索是由C/C+C/C+实现的。实现的。7.3.2 Android7.3.2 Android系统的中间件系统的中间件21u通常JNI的使用自上至下有4层,本地库,JNI库,声明本地接口的Java类,Java调用者,JNI在Android层次结构中的作用如图所示。7.3.2 Android7.3.2 Android系统的中间件系统的中间件22u实现JNI需要在C+代码中实现JNI的各种方法,并注册到系统中,另外还要在Java源代码中声明。u例7-2 实例实现JNI接口的设计。n在此之前我们需要将将NDK与Cyg
22、win关联起来,即打开homeAdministrator.bash_profile文件(本文F:cygwinhomemwy.bash_profile,在文件中加入如下代码:1NDK_ROOT=/cygdrive/f/android-ndk-r9d/2export NDK_ROOT 3PATH+=:$NDK_ROOT 4export PATH7.3.2 Android7.3.2 Android系统的中间件系统的中间件23u接口设计过程如下:在NDK安装目录下新建文件夹apps,在apps下新建目录san-angeles(这个名字可以自己任意取),并Eclipse中新建工程SanAngeles。建
23、立工程之后需要创建并编写JNI类代码,用来声明要调用的本地方法,关键字native。此时在Eclipse中新建名为JNITest的类。7.3.2 Android7.3.2 Android系统的中间件系统的中间件24n其代码如下:其代码如下:1 1 packagecom.example.SanAngeles;packagecom.example.SanAngeles;2 2 public class JNITest public class JNITest 3 3 private static native void nativeInit();private static native void
24、 nativeInit();4 4 private static native void nativeResize(int w,int h);private static native void nativeResize(int w,int h);5 5 private static native void nativeRender();private static native void nativeRender();6 private static native void nativeDone();6 private static native void nativeDone();7 7
25、7.3.2 Android7.3.2 Android系统的中间件系统的中间件25为调用内核代码提供的接口编译编译JavaJava文件,并生成相应的头文件文件,并生成相应的头文件我们需要将新建的JNItest.java文件复制到工程目录的bin目录下并用命令行编译。首先进入NDK主目录,接着输入 javac JNITest.java即可生成JNItest.class文件。将此文件复制到F:android-ndk-r9dappssan-angelesprojectbinclassescomexampleSanAngeles中替换原有文件;从命令行进入bin/classes目录,输入 javahjn
26、icom_example_angles_JNITest生成com_example_angles_JNITest.h的C头文件,最后在此工程目录下(即project目录下)创建jni文件夹,并将生成的头文件复制到此处。这个头文件主要是来处理C/C+和Java中一些定义的差别。而其中的JNIEXPORT和JNICALL都是JNI的关键字,表示函数式要被JNI调用的。7.3.2 Android7.3.2 Android系统的中间件系统的中间件26编译编译JavaJava文件,并生成相应的头文件文件,并生成相应的头文件其内容如下:其内容如下:7.3.2 Android7.3.2 Android系统的中
27、间件系统的中间件1#include 2/*Header for class com_example_angles_JNITest*/3#ifndef _Included_com_example_angles_JNITest4#define _Included_com_example_angles_JNITest5#ifdef _cplusplus6extern C 7#endif8/*9*Class:com_example_angles_JNITest10*Method:nativeInit11*Signature:()V12*/13JNIEXPORT void JNICALL Java_co
28、m_example_angles_JNITest_nativeInit (JNIEnv*,jclass);14/*15*Class:com_example_angles_JNITest16*Method:nativeResize17*Signature:(II)V277.3.2 Android系统的中间件系统的中间件18*/19JNIEXPORT void JNICALL Java_com_example_angles_JNITest_nativeResize (JNIEnv*,jclass,jint,jint);20/*21*Class:com_example_angles_JNITest2
29、2*Method:nativeRender23*Signature:()V24*/25JNIEXPORT void JNICALL Java_com_example_angles_JNITest_nativeRender (JNIEnv*,jclass);26/*27*Class:com_example_angles_JNITest28*Method:nativeDone29*Signature:()V30*/31JNIEXPORT void JNICALL Java_com_example_angles_JNITest_nativeDone (JNIEnv*,jclass);32#ifdef
30、 _cplusplus3334#endif35#endif这个头文件主要是来处理C/C+和Java中一些定义的差别。而其中的JNIEXPORT和JNICALL都是JNI的关键字,表示函数式要被JNI调用的28u在jni目录下新建app-android.c文件并编写其代码,这里我们重点介绍这几个原生方法的实现:uJava_com_example_angles_JNITest_nativeInit这个命名必须遵循“函数名=Java_开头+包名和类名+接口名”这一规律。这个名字要是错了就无法被调用到。7.3.3 7.3.3 使用使用C/C+C/C+实现本地方法实现本地方法1 void Java_co
31、m_example_angles_JNITest_nativeInit(JNIEnv*env)2ImportGLInit();3appInit();4gAppAlive=1;5sDemoStopped=0;6sTimeOffsetInit=0;29u在上述方法中有两个常见的参数,其中一个参数JNIEnv是指向可用JNI函数表的接口指针;另一个参数jobject是Java引用。下面将对这两个参数做详细介绍。pJNIEnv接口指针示意图如下:7.3.3 7.3.3 使用使用C/C+C/C+实现本地方法实现本地方法30pJNIEnv接口指针JNIEnv接口指针,指向一个函数表,函数表中的每一个入口指
32、向一个JNI函数。JNIEnv是一个与线程相关的变量,不同线程的JNIEnv彼此独立。在C与C+中使用JNIEnv*env分别如下:C:(*env)-方法名(env,参数列表)C+:env-方法名(参数列表)p参数jobject代表的是一个原生实例的方法,它与类实例相关,它们只能在类实例中调用,通过第二个参数获取实例引用。在原生代码不仅可以通过实例方法实现开可以通过静态方法实现,与实例方法不同的是第二参数为jclass值类型的,而且它没有与实例绑定,可以在静态上下文直接引用。7.3.3 7.3.3 使用使用C/C+C/C+实现本地方法实现本地方法31n通过C语言来实现OpenGL编程,来说明依
33、赖关系的建立。具体可参见工程中其余的代码。7.3.4 7.3.4 依赖关系建立依赖关系建立32nAndroid NDK构建系统依赖另外二个文件:Android.mk和Application.mk,这两个文件应该作为NDK项目的一部分由开发人员提供,下面我们将重点介绍。pAndroid.mk文件:Android.mk是向Android NDK系统项目中GUN Makefile文件,用于描述实现嵌入的必备信息,因此也是每个NDK项目的必备组件。p针对上述的工程,需添加的Android.mk的文件内容如下。7.3.4 7.3.4 依赖关系建立依赖关系建立1.LOCAL_PATH:=$(call my
34、-dir)2.include$(CLEAR_VARS)3.LOCAL_MODULE :=hello-jni4.LOCAL_SRC_FILES:=hello-jni.c5.include$(BUILD_SHARED_LIBRARY)337.3.4 7.3.4 依赖关系建立依赖关系建立1.LOCAL_PATH:=$(call my-dir)2.include$(CLEAR_VARS)3.LOCAL_MODULE :=hello-jni4.LOCAL_SRC_FILES:=hello-jni.c5.include$(BUILD_SHARED_LIBRARY)Android系统用LOCAL_PATH来
35、表示需要编译的C/C+代码所在目录,my-dir是Android NDK编译系统提供的宏功能,通过调用该宏功能返回当前目录的位置。Android系统将CLEAR_VARS变量设置为脚本文件clear-vars.mk的位置,$(C L E A R _ VA R S)表 示 清 除LOCAL_PATH以外所有LOCAL_开始的变量,例如LOCAL_MODULE与LOCAL_SRC_FILES等变量。因为所有的脚本都将在同一个GNU Make的执行上下文中,而且所有变量都是全局变量,因此必须在每次使用前清空所有以前用过的变量。34LOCAL_MODILE用来声明模块名称,模块名称必须唯一,而且中间不
36、能存在空格。因为模块名称也被用于给NDK编译系统生成的共享库文件命名,所以系统自动在模块名称前添加lib前缀,然后生成.so文件。LOCAL_SRC_FILES表示编译模块时使用的C/C+文件列表。include$(BUILD_SHARED_LIBRARY)表示NDK系统构建的共享库,Android NDK编译系统将BUILD_SHARED_LIBRARY变量设置成build-shared-library.mk文件的保存位置。Application.mk文件:在进行NDK开发时,在应用程序目录中一定要有Application.mk文件,用来声明Android工程需要调用的共享库或静态库模块。A
37、pplication.mk文件通常被放置在$PROJECT/jni/Application.mk下,$PROJECT指的是项目。另一种方法是将其放在顶层的子目录下:$NDK/apps目录下$NDK/apps/Application.mk,是一个简称,用于描述你的NDK编译系统的应用程序(这个名字不会生成共享库或者最终的包)。7.3.4 7.3.4 依赖关系建立依赖关系建立35针对上述工程需添加的Application.mk文件内容如下:1APP_MODULES:=JNITest 2APP_PROJECT_PATH:=$(call my-dir)/projectApplication.mk其实是
38、一个小型GNU Makefile片段,它必须定义一些这样的变量:7.3.4 7.3.4 依赖关系建立依赖关系建立36APP_PROJECT_PATH:这个变量是强制性的,并且会给出应用程序工程的根目录的一个绝对路径。APP_MODULES:这个变量是可选的,如果没有定义,NDK将由在Android.mk中声明的默认的模块编译,并且包含所有的子文件(makefile文件)。APP_OPTIM:这个变量是可选的,用来定义“release”或debug。7.3.4 7.3.4 依赖关系建立依赖关系建立37APP_CFLAGS:当编译模块中有任何C文件或者C+文件的时候,C编译器的信号就会被发出。AP
39、P_CPPFLAGS:C+代码的编译选项。APP_ABI:默认情况下,Android NDK编译系统会产生“armeabi”ABI二进制文件。APP_STL:在默认情况下,NDK通过Androoid自带的最小化的C+运行库(system/lib/libstdc+.so)来提供标准C+头文件.然而,NDK提供了可供选择的C+实现,你可以通过此变量来选择使用哪个或链接到你的程序。7.3.4 7.3.4 依赖关系建立依赖关系建立38APP_GNUSTL_FORCE_CPP_FEATURES:在先前的NDK版本中,当使用GNU libstdc+runtime运行库(通过设置APP_STL变量为gnus
40、tl_static或gnustl_shared)都会强制支持异常和RTTI,在有些极少情况下可能会出现问题,同时会使生成的机器码包含不必须的内容。APP_BUILD_SCRIPT:在默认情况下,NDK会在jni目录下查找Android.mk文件并使用它,如果你想修改它,那么在此变量中你可以指定一个你自己的脚本来执行,路径还是以工程顶层目录为相对路径。7.3.4 7.3.4 依赖关系建立依赖关系建立39n例7-3通过NDK手法显示一个OpenGL视图。7.3.5 NDK7.3.5 NDK程序的链接与运行程序的链接与运行40u首先打开Cygwin输入“cd NDK_ROOT”进入ndk安装目录,输
41、入“cd apps/mwy”进入到配置文件目录,然后输入“ndk-build”使其生成.so文件,具体如下图7.3.5 NDK7.3.5 NDK程序的链接与运行程序的链接与运行41u其运行成功后将生成的libs文件夹复制到工程中(与src同级),接下来便可以调用本地原生方法加载C/C+中的数据。uAndroid NDK生成的共享库名为libJNITest.so,但是loadLibrary方法只采用JNITest这个库名,再按照所使用的具体操作系统的要求加上必要的前缀和后缀。u库名与Android.mk文件中使用的LOCAL_MODULE构建系统变量定义的模块名相同。loadLibrary的参数
42、也不包含共享库的位置。Java库路径,也就是系统属性Java.library.path保存loadLibrary方法在共享库搜索的目录列表,Android上的Java库路径包含/vendor/lib和/system/lib7.3.5 NDK7.3.5 NDK程序的链接与运行程序的链接与运行42本 书 例程如下:部分代码如下:部分代码如下:1 public 1 public class class DemoActivityDemoActivity extends Activity extends Activity 2 2 OverrideOverride3 protected 3 protect
43、ed void void onCreateonCreate(Bundle(Bundle savedInstanceStatesavedInstanceState)4 4 super.onCreatesuper.onCreate(savedInstanceStatesavedInstanceState););5 5 mGLViewmGLView =new=new DemoGLSurfaceViewDemoGLSurfaceView(this);(this);6 6 setContentViewsetContentView(mGLViewmGLView););7 7 8 8 OverrideOve
44、rride9 protected 9 protected void void onPauseonPause()()1010 super.onPausesuper.onPause();();1111 mGLView.onPausemGLView.onPause();();1212 13 13 OverrideOverride1414 protected protected void void onResumeonResume()()1515 super.onResumesuper.onResume();();1616 mGLView.onResumemGLView.onResume();();1
45、717 18 private 18 private GLSurfaceViewmGLViewGLSurfaceViewmGLView;19 /19 /装在动态链接库装在动态链接库2020 static static 2121 System.loadLibrarySystem.loadLibrary(JNITestJNITest););2222 23 23 24 24 classDemoGLSurfaceViewclassDemoGLSurfaceView extends extends GLSurfaceViewGLSurfaceView 25 public 25 public DemoGLS
46、urfaceViewDemoGLSurfaceView(Context context)(Context context)432626super(context);super(context);2727mRenderermRenderer=new =new DemoRendererDemoRenderer();();2828setRenderersetRenderer(mRenderermRenderer););2929 3030 public public booleanonTouchEventbooleanonTouchEvent(final(final MotionEventMotion
47、Event event)event)31 if 31 if(event.getActionevent.getAction()=()=MotionEvent.ACTION_DOWNMotionEvent.ACTION_DOWN)32 32 nativePausenativePause();();3333 34 34 return return true;true;3535 36 36 DemoRenderermRendererDemoRenderermRenderer;37 37 private private static native void static native void nati
48、vePausenativePause();();38 38 39 class 39 class DemoRendererDemoRenderer implements implements GLSurfaceView.RendererGLSurfaceView.Renderer 40 public 40 public void void onSurfaceCreatedonSurfaceCreated(GL10(GL10 gl gl,EGLConfigconfigEGLConfigconfig)41 41 nativeInitnativeInit();();43 public 43 publi
49、c void void onSurfaceChangedonSurfaceChanged(GL10(GL10 gl gl,intint w,w,intint h)h)44 44 nativeResizenativeResize(w(w,h);,h);46 public 46 public void void onDrawFrameonDrawFrame(GL10(GL10 gl gl)47 47 nativeRendernativeRender();();48 48 /声明原生方法声明原生方法50 private 50 private static native void static nat
50、ive void nativeInitnativeInit();();51 private 51 private static native void static native void nativeResizenativeResize(intint w,w,intint h);h);52 private 52 private static native void static native void nativeRendernativeRender();();53 private 53 private static native void static native void native