NDK是SDK的辅助工具,用它将Android的一部分或全部用本地代码实现。字节码需要由虚拟机解释,而本地代码由设备处理器直接执行,执行速度更快。Dalvik的JIT编译器可以将字节码编译为本地代码,减少字节码的解释次数,而直接使用自己生成的本地代码可以让应用运行的更快。
使用步骤:
1)在Java代码中声明本地方法
2)实现JNI粘合层
3)创建Android makefile文件
4)用C/C++实现本地方法
5)编译本地库
6)加载本地库
1、示例展示NDK用法
1)Fibonacci.java
package com.example.sometest;
public class Fibonacci {
public static native long recursiveNative(int n);
}
2)打开命令行,切换到应用目录,创建jni目录执行
javah -classpath bin/classes -jni -d jni com.example.sometest.Fibonacci
自动生成头文件:com_example_sometest_Fibonacci.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_sometest_Fibonacci */
#ifndef _Included_com_example_sometest_Fibonacci
#define _Included_com_example_sometest_Fibonacci
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_sometest_Fibonacci
* Method: recursiveNative
* Signature: (I)J
*/
JNIEXPORT jlong JNICALL Java_com_example_sometest_Fibonacci_recursiveNative
(JNIEnv *, jclass, jint);
#ifdef __cplusplus
}
#endif
#endif
创建com_example_sometest_Fibonacci.c
#include "com_example_sometest_Fibonacci.h"
#include "fibonacci.h"
/*
* 类:com_example_sometest_Fibonacci
* 方法:recursiveNative
* 签名:(I)J
*/
jlong JNICALL
Java_com_example_sometest_Fibonacci_recursiveNative
(JNIEnv *env, jclass clazz, jint n){
return recursive(n);
}
3)创建makefile
Application.mk,指定了构建一个版本的库(EABI: embeded application binary interface)
APP_ABI := armeabi
Android.mk,LOCAL_SRC_FILES列出了所有需要编译的文件,LOCAL_MODULE定义了模块的名称。
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := fibonacci
LOCAL_SRC_FILES := com_example_sometest_Fibonacci.c fibonacci.c
include $(BUILD_SHARED_LIBRARY)
4)实现本地函数
新建fibonacci.h
#ifndef _FIBONACCI_H_
#define _FIBONACCI_H_
#include <stdint.h>
extern uint64_t recursive (unsigned int n);
#endif
新建fibonacci.c
#include "fibonacci.h"
uint64_t recursive (unsigned int n){
if(n>1) return recursive(n-2)+recursive(n-1);
return n;
}
从粘合层调用该函数
5)编译本地库下载并解压NDK,将NDK目录加到PATH环境变量,从而方便使用ndk-build命令构建共享库。
将命令行当前路径切换至jni目录,执行ndk-build,最终在libs/armeabi生成libfibonacci.so共享库。
6)加载库
public class Fibonacci {
static{
System.loadLibrary("fibonacci");
}
public static native long recursiveNative(int n);
}
7)然后本地方法就可以使用了,不再报异常UnsatisfiedLinkError
MainActivity.java
public class MainActivity extends Activity{
private static final String TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onClick(View v){
switch(v.getId()){
case R.id.btn_getValue:
Toast.makeText(this, "fibonacci="+Fibonacci.recursiveNative(4), Toast.LENGTH_SHORT).show();
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<Button
android:id="@+id/btn_getValue"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="getValue"
android:onClick="onClick"/>
</LinearLayout>