一、NDK开发介绍。
分析Android框架不难发现,Android是基于Linux的开源操作系统。也就是说Android的底层是基于C实现的,但是Android SDK是基于Java实现的。这就意味着Android应用程序在运行时,Android虚拟机会实现Java与C语言之间的调用(Java调C我们称之为JNI)。 其实自Android平台从诞生起,就已经支持C、C++开发。虽说基于Android SDK进行开发的第三方应用都必须使用Java语言。但这并不等同于“第三方应用只能使用Java”。在Android SDK首次发布时,Google就宣称其虚拟机Dalvik支持JNI编程方式,也就是第三方应用完全可以通过JNI调用自己的C动态库,即在Android平台上,“Java+C”的编程方式是一直都可以实现的。
不过,Google也表示,使用原生SDK编程相比Dalvik虚拟机也有一些劣势,Android SDK文档里,找不到任何JNI方面的帮助。即使第三方应用开发者使用JNI完成了自己的C动态链接库(so)开发,但是so如何和应用程序一起打包成apk并发布?这里面也存在技术障碍。比如程序更加复杂,兼容性难以保障,无法访问Framework API,Debug难度更大等。开发者需要自行斟酌使用。
于是NDK就应运而生了。。。
NDK的发布,使“Java+C”的开发方式终于转正,成为官方支持的开发方式。NDK将是Android平台支持C开发的开端。
使用NDK开发的好处:
1.代码的保护:由于apk的java层代码很容易被反编译,而C/C++库反汇难度较大,所以可以起到保护核心代码的作用。
2.可以方便地使用现存的开源库。大部分现存的开源库都是用C/C++代码编写的。
3.提高程序的执行效率。将要求高性能的应用逻辑使用C开发,从而提高应用程序的执行效率。
4.便于移植。用C/C++写得库可以方便在其他的嵌入式平台上再次使用。
二、NDK开发环境搭建
1.创建普通的Android项目工程。
2.在项目的根目录中创建jni目录,该目录用来存放编译so文件所需要的源文件(C/C++ mk文件)
2. 创建Builder,Project->Properties->Builders->New->Program
2.1创建Builder
2.2 设置Main标签
2.3 设置Refresh标签
2.4 设置Build标签,设置完成之后点击OK即可设置完毕。
3.在工程中创建java文件(src目录下),声明native方法。
package com.example.day_34_ndk_helloworld;
public class NDKBridge {
public static native String helloWorld();
}
4.使用javah工具将声明了native方法的class文件转换成(.h)文件。javah工具在jdk的安装目录bin目录下。需要时可以直接配置javah的环境变量。
添加完环境变量后,在DOS命令行进入工程文件夹中包的上一级目录。
执行下列命令就可以生成头文件:
javah -jni com.ex ample.day_34_ndk_helloworld.NDKBridge
注意:1.javah 使用的命令
2.javah 使用的命令的选项 (生成JNI样式的头文件)
3.com.example.day_34_ndk_helloworld.NDKBridge 本地方法源文件的包名和类名(我的电脑上是这样的)。
5.执行javah命令后会在包的同一级目录生成一个H文件。直接将其拷贝到工程文件中的jni目录下。
6.根据H文件中的函数声明,在jni目录下创建C文件(注意文件名除了后缀不一样,其他都是一样的)。
#include "com_example_day_34_ndk_helloworld_NDKBridge.h"
#include
#include
#ifdef __cplusplus
extern "C"
{
#endif
JNIEXPORT jstring JNICALL Java_com_example_day_134_1ndk_1helloworld_NDKBridge_helloWorld (JNIEnv *env, jclass arg)
{
return (*env)->NewStringUTF(env, "hello world from jni");
}
#ifdef __cplusplus
}
#endif
7.在jni目录创建Android.mk文件,制作编译清单。NDK会根据Android.mk中的清单编译成so文件。
#include "com_example_day_34_ndk_helloworld_NDKBridge.h"
#include
#include
#ifdef __cplusplus
extern "C"
{
#endif
JNIEXPORT jstring JNICALL Java_com_example_day_134_1ndk_1helloworld_NDKBridge_helloWorld (JNIEnv *env, jclass arg)
{
return (*env)->NewStringUTF(env, "hello world from jni");
}
#ifdef __cplusplus
}
#endif
8.在java层中,加载so文件,并调用native方法。
package com.example.day_34_ndk_helloworld;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
private Button btn;
private TextView tv;
static{
System.loadLibrary("MyNDKDemo");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.bt_get_str_from_jni);
tv = (TextView) findViewById(R.id.tv);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
tv.setText(NDKBridge.helloWorld());
}
});
}
}
效果图:
至此NDK的开发环境就已经搭建完毕,关于Android中NDK开发的一些细节我们会在后续的讲解中跟大家介绍。