Oct 23, 2010

Android通过JNI调用native code

0.  用Eclipse 创建 Android Project
1. 创建Java类,这个类的作用是描述native code中的函数, 比如DemoLib
2. 生成native code头文件, javah -jni ...
3. 实现native code
4. 编写jni/Android.mk
5. 编译native code, 生成动态库
6. 在Java程序中调用native code
7. 测试

0. 先通过 Eclipse 创建一个Android Project
Project name: LibDemoTest
Build Target: Android 2.2
Package name: org.ox0spy.libdemotest
Create Activity: LibDemoTest

1. 在src中添加一个新类 - DemoLib
Package: org.ox0spy.libdemotest
Name: DemoLib

DemoLib.java 内容如下:
package org.ox0spy.libdemotest;

public class DemoLib {
    static {
        System.loadLibrary("demo");
    }  
   
    public native int multiply(int a, int b);
   
    public native String greet();
}

注意: 编辑完了一定保存下.

2. 生成native code的头文件
$ cd ~/workspace/LibDemoTest/bin
$ javah -jni org.ox0spy.libdemotest.DemoLib

$ mkdir ../jni
$ mv org_ox0spy_libdemotest_DemoLib.h ../jni/

3. 实现native code, demo.c 内容如下:
#include "org_ox0spy_libdemotest_DemoLib.h"


JNIEXPORT jint JNICALL Java_org_ox0spy_libdemotest_DemoLib_multiply
  (JNIEnv * env, jobject obj, jint a, jint b)
{
    return a*b;
}

JNIEXPORT jstring JNICALL Java_org_ox0spy_libdemotest_DemoLib_greet
  (JNIEnv * env, jobject obj)
{
    return (*env)->NewStringUTF(env, "Hello Android!");
}

4. 编写jni/Android.mk
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES := demo.c
LOCAL_MODULE    := demo

include $(BUILD_SHARED_LIBRARY)

5. 编译native code
$ cd ~/workspace/LibDemoTest
$ ndk-build   # 先将android-ndk-r4b加入你的PATH中

6. Java程序中调用native code, 我在LibDemoTest.java中用到了native code
LibDemoTest内容如下:
package org.ox0spy.libdemotest;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class LibDemoTest extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        DemoLib demoLib = new DemoLib();

        int result = demoLib.multiply(100, 100);
        String str = demoLib.greet();

        TextView tv = new TextView(this);
        tv.setText(str + "\n" + Integer.toString(result));

        setContentView(tv);
    }
}

7. 测试, Eclipse, Run -> Run

我碰到的错误:
No implementation found for native

碰到这个错误时,我是用System.load("demo")加载动态库的,而且从logcat的输出发现libdemo.so已经成功加载了。
我是因为一开始没有用javah -jni 生成头文件,自己写的native code函数声明是:
jint multiply(jint a, jint b);

所以, 只要用javah -jni 生成头文件应该就不会碰到这个问题了.

No comments:

Post a Comment

您的评论将使我blog更有动力~