Chinaunix首页 | 论坛 | 博客
  • 博客访问: 454695
  • 博文数量: 89
  • 博客积分: 1126
  • 博客等级: 少尉
  • 技术积分: 1432
  • 用 户 组: 普通用户
  • 注册时间: 2011-04-11 23:37
文章分类

全部博文(89)

文章存档

2016年(6)

2015年(2)

2014年(1)

2013年(3)

2012年(23)

2011年(54)

分类: 嵌入式

2012-10-06 18:42:38

使用ndk开发需要编写jni.jni函数注册有两种方法。第一种静态注册,第二种动态注册。在NDK开发中使用第一种方法比较多,第二种方法在framework开发中使用的比较多,但是依赖android的一些特定的函数库。在ndk中不能使用。jni的静态注册需要生成对应的native头问题件,我们以ndk中hell-jni 为例进行说明:
按照网上的攻略
root@ubuntu12:/work/android-ndk-r8b/samples/hello-jni# javah -classpath bin -d jni com.example.hellojni.HelloJni
错误:无法访问 com.example.hellojni.HelloJni
未找到 com.example.hellojni.HelloJni 的类文件
javadoc: 错误 - 找不到类 com.example.hellojni.HelloJni。
Error: 未在命令行中指定任何类。请尝试使用 -help。

搜索一下javah 的用法:wanghuan@ubuntu:~/android-ndk-r8b/samples/hello-jni/src/com/example/hellojni$ javah
Usage: javah [options]

where [options] include:

-help Print this help message and exit
-classpath Path from which to load classes
-bootclasspath Path from which to load bootstrap classes
-d
Output directory
-o Output file (only one of -d or -o may be used)
-jni Generate JNI-style header file (default)
-version Print version information
-verbose Enable verbose output
-force Always write output files

are specified with their fully qualified names (for
instance, java.lang.Object).

-classpath Path from which to load classes
-bootclasspath Path from which to load bootstrap classes
这两个选项就是javah的操作对象的路径,现在项目里没有class文件,出错。但是如果javac 编译HelloJni.java 的话,编译报错,不识别Android的特有类。把重新改写HelloJni.java。全部标准java实现:public class HelloJni
{
/* A native method that is implemented by the
* 'hello-jni' native library, which is packaged
* with this application.
*/
public native String stringFromJNI();

/* This is another native method declaration that is *not*
* implemented by 'hello-jni'. This is simply to show that
* you can declare as many native methods in your Java code
* as you want, their implementation is searched in the
* currently loaded native libraries only the first time
* you call them.
*
* Trying to call this function will result in a
* java.lang.UnsatisfiedLinkError exception !
*/
public native String unimplementedStringFromJNI();

/* this is used to load the 'hello-jni' library on application
* startup. The library has already been unpacked into
* /data/data/com.example.hellojni/lib/libhello-jni.so at
* installation time by the package manager.
*/
static {
System.loadLibrary("hello-jni");
}
}

root@ubuntu12:/work/android-ndk-r8b/samples/hello-jni/src/example/hellojni# ls
HelloJni.class  HelloJni.java

这次生成了class文件。但是javah 始终找不到这个类,加入调试选项:
root@ubuntu12:/work/android-ndk-r8b/samples/hello-jni# javah -verbose -classpath bin -d jni com.example.hellojni.HelloJni
错误:无法访问 com.example.hellojni.HelloJni
未找到 com.example.hellojni.HelloJni 的类文件
javadoc: 错误 - 找不到类 com.example.hellojni.HelloJni。
[ Search Path: /usr/lib/jvm/java-6-sun-1.6.0.30/jre/lib/resources.jar:/usr/lib/jvm/java-6-sun-1.6.0.30/jre/lib/rt.jar:/usr/lib/jvm/java-6-sun-1.6.0.30/jre/lib/sunrsasign.jar:/usr/lib/jvm/java-6-sun-1.6.0.30/jre/lib/jsse.jar:/usr/lib/jvm/java-6-sun-1.6.0.30/jre/lib/jce.jar:/usr/lib/jvm/java-6-sun-1.6.0.30/jre/lib/charsets.jar:/usr/lib/jvm/java-6-sun-1.6.0.30/jre/lib/modules/jdk.boot.jar:/usr/lib/jvm/java-6-sun-1.6.0.30/jre/classes/bin ]
Error: 未在命令行中指定任何类。请尝试使用 -help。

显示CLASSPATH路径不对。配置CLASSPATHexport JAVA_HOME=/usr/lib/jvm/java-6-sun-1.6.0.30/bin
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:./
export PATH=$JAVA_HOME/bin:$PATH


换一种思路,在windows eclipse 下面:首先在一个工程中加入HelloJni.java或者新建一个工程 . HelloJni.java 为ndk自带的java文件。生成HelloJni.class 文件。然后进入bin\classes 在环境变量中配置CLASS_PATH为:.;

D:\workspace\SPlayer\bin\classes>javah -d . com.example.hellojni.HelloJni

D:\workspace\SPlayer\bin\classes>ls
com com_example_hellojni_HelloJni.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class com_example_hellojni_HelloJni */

#ifndef _Included_com_example_hellojni_HelloJni
#define _Included_com_example_hellojni_HelloJni
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_hellojni_HelloJni
* Method: stringFromJNI
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_stringFromJNI
(JNIEnv *, jobject);

/*
* Class: com_example_hellojni_HelloJni
* Method: unimplementedStringFromJNI
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_unimplementedStringFromJNI
(JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

总结一下:1.javah 生成native头文件依赖于对应的class文件 。因此应该先生成class 文件,不然巧妇难为无米之炊。2. javah 寻找类路径的时候 依赖于CLASSPATH环境变量,要正确的配置CLASSPATH。3.javc 编译class文件只支持java标准的API,不支持android API 。如果java文件中有androidAPI 应该使用android的编译环境或者EClipse生成class文件。javah 生成头文文件只是根据class文件中的native 方法,和是否是标准的java 标准无关
阅读(4044) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~