程序员人生 网站导航

NDK浅尝(1)

栏目:综合技术时间:2016-03-29 09:16:36

First JNI Project

这篇博客主要针对Android NDK开发做入门级论述,所触及到的主要有以下几点:

  • Android NDK开发简介
  • JNI简介
  • 工具介绍
  • 构建HelloJNI项目

1.Android NDK开发简介
Android NDK 是在SDK前面又加上了“原生”2字,即Native Development Kit,因此又被Google称为“NDK”。尽人皆知,Android程序运行在Dalvik虚拟机中,NDK允许用户使用类似C / C++之类的原生代码语言履行部份程序。NDK包括了:

  1. 从C / C++生成原生代码库所需要的工具和build files
  2. 将1致的原生库嵌入可以在Android装备上部署的利用程序包文件
  3. 将1致的原生库嵌入可以在Android装备上部署的利用程序包文件(application packages files ,即.apk文件)中。
  4. 支持所有未来Android平台的1些列原生系统头文件和库

2.JNI简介
JNI是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通讯(主要是C&C++)。从Java1.1开始,JNI标准成为java平台的1部份,它允许Java代码和其他语言写的代码进行交互。JNI1开始是为了本地已编译语言,特别是C和C++而设计的,但是它其实不妨碍你使用其他编程语言,只要调用约定受支持就能够了。使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,乃至是必须的。例如,使用1些旧的库,与硬件、操作系统进行交互,或为了提高程序的性能。JNI标准最少要保证本地代码能工作在任何Java 虚拟机环境下。更多相干细节参见百度百科


3.工具介绍

  1. NDK
  2. SDK
  3. Android Studio 1.4
    稍后将会用专页同享各项软件的下载链接及安装。

4.构建HelloJNI项目

等不到我开发环境构建的兄弟们可以先根据其他博客自己搭建环境,相对而言环境相干的教程是比较多的,本篇博客的主要目的在于引导大家在最新环境上入手JNI开发:
第1步: 新建Android项目
新建的Android项目路径以下图所示:
这里写图片描述
第2步:
添加JNI文件荚
右键->new->Folder->JNI Folder,添加后文件目录如图所示:
这里写图片描述
第3步:
在jni文件夹上右键new ->file,命名为Android.mk,同上再新建1个hello-jni.cpp文件。Android.mk文件内容以下:

#1个Android.mk 文件首先必须定义好LOCAL_PATH变量。它用于在开发树中查找源文件。在这个例子中,宏函数’my-dir’, 由编译系统提供,用于返回当前路径(即包括Android.mk file文件的目录) #CLEAR_VARS由编译系统提供,指定让GNU MAKEFILE为你清除许多LOCAL_XXX变量(例如 LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES, 等等...), #除LOCAL_PATH 。这是必要的,由于所有的编译控制文件都在同1个GNU MAKE履行环境中,所有的变量都是全局的。 #编译的目标对象,LOCAL_MODULE变量必须定义,以标识你在Android.mk文件中描写的每一个模块。名称必须是唯1的,而且不包括任何空格。 #编译系统会自动产生适合的前缀和后缀,换句话说,1个被命名为hello-jni的同享库模块,将会生成libhello-jni.so文件。 #如果你把库命名为‘libhello-jni’,编译系统将不会添加任何的lib前缀,也会生成 libhello-jni.so,这是为了支持来源于Android平台的源代码的Android.mk文件,如果你确切需要这么做的话。 #LOCAL_SRC_FILES变量必须包括将要编译打包进模块中的C或C++源代码文件。注意,你不用在这里列出头文件和包括文件,由于编译系统将会自动为你找出依赖型的文件;仅仅列出直接传递给编译器的源代码文件就好。 #默许的C++源码文件的扩大名是’.cpp’. 指定1个不同的扩大名也是可能的,只要定义LOCAL_DEFAULT_CPP_EXTENSION变量,不要忘记开始的小圆点(也就是’.cxx’,而不是’cxx’) #BUILD_SHARED_LIBRARY表示编译生成同享库,是编译系统提供的变量,指向1个GNU Makefile脚本,负责搜集自从上次调用include $(CLEAR_VARS)以来,定义在LOCAL_XXX变量中的所有信息,并且决定编译甚么,如何正确地去做。还有 BUILD_STATIC_LIBRARY变量表示生成静态库:lib$(LOCAL_MODULE).a, BUILD_EXECUTABLE 表示生成可履行文件。 # LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hello-jni LOCAL_SRC_FILES := hello-jni.cpp include $(BUILD_SHARED_LIBRARY)

hello-jni.cpp文件内容以下所示:

#include #include //extern "C" 标记该函数为C,由于JNI linker不能遵照从C++的命名规则,如果不加这1句,JNI linker会把它当作c++函数,在真机或摹拟器运行时报Unsatisfied Linker的毛病 extern "C" JNIEXPORT jstring JNICALL Java_com_tt_hellojni_MainActivity_NDKTestFromJNI( JNIEnv* env, jobject thiz ) { return env->NewStringUTF( "Hello from JNI !"); }

完成后,项目目录以下:
这里写图片描述
接着打开MainActivity.java文件,修改其内容以下:

import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.widget.TextView; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView tv = new TextView(this); tv.setText(NDKTestFromJNI()); setContentView(tv); } public native String NDKTestFromJNI();// native声明,表示这个方法来自Native层。实现进程已在native层实现了 static { System.loadLibrary("hello-jni");// 加载库,前面的lib和后缀名不用写 } }

第4步: 打开terminal,顺次按图中输入命令操作
这里写图片描述
此时,我们就能够看到生成的.so文件了哈,以下图所示:
这里写图片描述
第5步: 履行项目,运行在真机上,界面上会显示

Hello from JNI !



------分隔线----------------------------
------分隔线----------------------------

最新技术推荐