快速学习androidNDK编程之hello world教程

    作者:课课家教育更新于: 2019-02-28 14:48:58

         cygwin是一个在Windows平台上运行的unix模拟环境,主要目的是通过重新编译,将POSIX系统(例如Linux、BSD,以及其他Unix系统)上的软件移植到Windows上。那么对于学习unix/linux操作环境,或者从linux到windows的应用程序移植,或者进行某些特殊的开发工作,尤其是使用gnu工具集在windows上进行嵌入式系统开发,是非常有帮助的。

          在学习《学习AndroidNDK编程之搭建cygwine的开发环境》这篇文章后,已经搭建好了windows下的linux环境(cygwine),这次我们试着写一个hello world。首先需要去android的官网下载android-ndk压缩包,之后解压,进入解压后的目录,我们发现有一个ndk-build的脚本文件,这个脚本文件就是我们用交叉编译的文件。我们通过 "./ndk-build" 来运行该命令,如下图:

    快速学习androidNDK编程之hello world教程_android ndk_学习android_ndk_课课家

      因为目前我们没有编译任何c代码,所以会提示"could not find application project directory"这样的错误,这说明我们的ndk的环境,已经是ok的。但是如果我们每次执行该命令"ndk-build",难道都必须进入ndk的解压缩目录下来运行吗?答案是"no",我们可以配置ndk的环境变量,就像配置java环境变量一样。

      我们打开cygwine的安装目录,我的是在c盘下的cygwine目录下,也是默认的目录,在该目录下有一个etc文件夹,在etc文件夹下有一个profile的文件,我们打开它

      将PATH原先的路径:"PATH="/usr/local/bin:/usr/bin:" ,我们在"bin:"之后添加ndk的解压缩的目录,我的是在f:盘下,如下图:红色标注的就是我新添加的ndk的路径:

      完成之后,保存,然后重新打开cygwine,在任意目录输入"ndk-build" ,查看是否配置好了“ndk-build”的环境变量。

      接下来,我们来写一个hello world,首先在eclipse下新建一个android工程,这里我取名为"helloworld",创建好工程以后,我们需要在java代码中申明一个native方法,如下:

      这里注意,括号后边不能添加大括号,因为我们只是声明而并未实现该方法,native关键字,表明该方法的实现是在C语言层面实现的。

      接下来我们呢需要在helloworld工程下创建一个jni目录。在该目录下新建一个hello.c文件,在编写hello.c文件之前,我们需要用javah生成public native String helloWorldNdk(); 方法对应的头文件,由于我们在MainActivity中声明该方法,当我们用javac编译的时候,由于用到了R文件,导致生成字节码失败,由于我们只是需要.h头文件,所以我们可以新建一个java工程,来生成.h文件,如下图:

      其中JavahTest.java中的内容,就是我们在Mainactivty中声明的native方法,如下:

      接下来,我们生成.h文件,首先运行javac生成.class字节码。

      javac JavahTest.java

      运行以上命令,会生成.class字节码,接下来生成.h文件,如下图:

      此时,会生成一个com_test_example_JavahTest.h文件,该文件内容如下:

      其中jstring JNICALL Java_com_test_example_JavahTest_helloWorldNdk (JNIEnv *, jobject);

      就是我们需要在hello.c中声明的方法,这里需要注意,由于我们的native方法是在MainActivity中声明的,所以,我们需要将jstring JNICALL Java_com_test_example_JavahTest_helloWorldNdk (JNIEnv *, jobject);中的JavahTest替换成MainActivity,如下:

      jstring Java_com_example_helloworld_MainActivity_helloWorldNdk(JNIEnv* env ,jobject obj)

      接下来就是完整实现hello.c的代码,如下:

      可以看到这里我们返回"hello world"字符串。

      记住,需要编译该android工程中的c文件,我们还需要编写Android.mk文件,同样在jni目录下,新建一个Android.mk文件,内容如下:

      其中LOCAL_MODULE是我们需要编译的模块名称,这个名称随便命名的,LOCAL_SRC_FILES是我们需要编译的源文件

      当hello.c和Android.mk文件都创建好了以后,我们就可以编译该hello.c文件了,打开cygwine,进入该android工程,运行"ndk-build"命令,即可生成libhello.so文件,如下图:

      同时,我们发现在helloworld的android工程中,生成了以下文件:

      在libs目录下生成的libhello.so文件就是一个可以执行的二进制文件。下面我们就要在java代码中使用该二进制文件。我们通过静态代码块经该二进制文件加载进来。如下:

      这里需要注意的是:这里的"hello",就是我们在Android.mk文件中的 LOCAL_MODULE的值

      接下来就是,调运之前生成的二进制文件,我们只需要在MainActivity.java中这样写即可

      此时,当运行我们的helloworld工程,即会弹出toast,显示我们在hello.c中返回的字符串。

      到这里,一个最基本的ndk实现就完成了,现在我在加上一个声明的方法:

      那么,我们的hello.c中的方法应该怎么写呢?参照之前的写法:

      jstring Java_com_example_helloworld_MainActivity_hello_World_Ndk

      这里需要注意,这种写法是错误的,ndk会以为我们是在MainActivity中的内部类hello,以及hello中的内部类World中的方法Ndk,这样显然是不对的,ndk为这种情况提供了一个标准,我们需要在方法中的每一个下划线之后加上数字1即可,如下:

      这一点,我们可以通过javah来生成,我在d:盘下新建一个MainActivity.java,内容如下:

      然后,我们进入d:盘运行如下命令,生成.h文件,如下图:

      此时在d:盘下生成了一个MainActivity.h文件,内容如下:

      可以看到是以这样命名的。

      这里有一点需要注意的是,如果我们的类是有包名的话,此时运用javah来生成.h文件的时候,首先要将生成的.class文件拷贝到对应的包地下,然后运行如下命令:

      javah 包名.类名 这样才可以生成.h文件。

      那么现在呢,有了以上这些基础之后呢,就可以为MainActivity.java中声明的native方法直接生成.h头文件了,cmd进入命令行,首先进入helloworld工程的bin/classes目录下,执行如下命令即可:

      javah com.example.helloworld.MainActivity

      此时,会在bin/classes文件夹下新生成一个com_example_helloworld_MainActivity.h文件,我们将该文件拷贝到jni目录下,如下图:

      这个时候,我们的hello.c就可以这样写了:

      此时运行helloworld工程,toast会一次弹出"hello world two"和"i am from china two"

      总结一下:

      1.首先需要声明native方法:

      2.然后运用javah生成对应的.h头文件

      3.根据.h头文件,编写hello.c代码

      4.编写Android.mk文件

      5.在java中通过静态快引入二进制文件:

          主要是通过5个知识点来学习androidNDK编程中编写hello world的小教程,在学习的编程的过程中有几点是需要注意的,注意看上文加粗黑体字样,若有兴趣深入学习,后续我们还会有相关知识更新,或者自己在网上搜罗来学习,深入研究。

课课家教育

未登录

1