首先通过NDK自带的例子来初步了解NDK的开发
1. Java类文件
HelloJni.class
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.hellojni;
import android.app.Activity;
import android.widget.TextView;
import android.os.Bundle;
public class HelloJni extends Activity
{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
/* Create a TextView and set its content.
* the text is retrieved by calling a native
* function.
*/
TextView tv = new TextView(this);
tv.setText( stringFromJNI() );
setContentView(tv);
}
/*
* 调用libhello-jni.so库中的stringFromJNI()方法
* 注意声明的时候需要包含"native",表示是本地方法
*/
public native String stringFromJNI();
/*
* 加载libhello-jni.so库,省略了头lib和尾.so
* static{}在程序加载的时候就调用
*/
static {
System.loadLibrary("hello-jni");
}
}
2. 本地C代码部分
hello-jni.c#include <string.h>
#include <jni.h>
/*
函数命名规则:
Java开头,接着是包名的每一段,然后是类名,最后是Java中调用的方法名,中间都用下划线隔开。
第一个参数JNIEnv* env和第二个参数jobject thiz都是必须的,后面的才是Java中传递进来的参数
*/
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
return (*env)->NewStringUTF(env, "Hello from JNI !");//字符串的操作见NDK概述
}
3. 在工程目录编译jni文件夹生成so文件,则可以通过Eclipse加载工程调试了。
第二部分:进阶
通过上面的例子分析,我们知道了怎么调用动态库,怎么引用动态库中的方法,以及动态库中方法的命名。下面我们了解怎么在本地C代码中添加一个方法,给java调用。
我们以添加一个add方法为例,方法原型为:int addFromJNI(int a,int b)
A. 在本地C代码中添加add方法,并实现。
hello-jni.c
#include <string.h>
#include <jni.h>
/*
函数的命名规则:
Java开头,接着是包名的每一段,然后是类名,最后是Java中调用的方法名,中间都用下划线隔开。
第一个参数JNIEnv* env和第二个参数jobject thiz都是必须的,后面的才是Java中传递进来的参数。
*/
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
return (*env)->NewStringUTF(env, "Hello from JNI !");
}
jint Java_com_example_hellojni_HelloJni_addFromJNI(
JNIEnv* env,jobject thiz,jint a,jint b)
{
return a + b;
}
B. 编译mk文件,生成so文件
$NDK/ndk-build //$NDK环境变量设置的NDK目录
C. java 源代码
HelloJni.java
package com.example.hellojni;
import android.app.Activity;
import android.widget.TextView;
import android.os.Bundle;
public class HelloJni extends Activity
{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
/* Create a TextView and set its content.
* the text is retrieved by calling a native
* function.
*/
TextView tv = new TextView(this);
tv.setText( stringFromJNI() +"****" + addFromJNI(3, 4));
setContentView(tv);
}
/*
* 调用libhello-jni.so库中的stringFromJNI()方法
* 注意声明的时候需要包含"native",表示是本地
*/
public native String stringFromJNI();
/*
* 调用新增加的addFromJNI方法
*/
public native int addFromJNI(int a,int b);
/*
* 加载libhello-jni.so库,省略了头lib和尾.so
* static{}在程序加载的时候就调用
*/
static {
System.loadLibrary("hello-jni");
}
}
D. 加载运行,则看到刚添加的函数生效了