上面的都是基本类型。如果Java函数的参数是class,则以\开头,以\结尾,中间是用\隔开的包及类名。而其对应的C函数名的参数则为jobject. 一个例外是String类,其对应的类为jstring
Ljava/lang/String; String jstring Ljava/net/Socket; Socket jobject
如果JAVA函数位于一个嵌入类,则用$作为类名间的分隔符。 例如 \
Android JNI编程实践
一、直接使用java本身jni接口(windows/ubuntu)
1.在Eclipsh中新建一个android应用程序。两个类:一个继承于Activity,UI显示用。另一个包含native方法。编译生成所有类。 jnitest.java文件:
package com.hello.jnitest;
import android.app.Activity; import android.os.Bundle;
public class jnitest extends Activity {
/** Called when the activity is first created. */ @Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Nadd cal = new Nadd();
setTitle(\ } }
Nadd.java文件:
package com.hello.jnitest;
public class Nadd {
static {
System.loadLibrary(\ }
public native int nadd(int a, int b); }
以上在windows中完成。
2.使用javah命令生成C/C++的.h文件。注意类要包含包名,路径文件夹下要包含所有包中的类,否则会报找不到类的错误。classpath参数指定到包名前一级文件夹,文件夹层次结构要符合java类的组织层次结构。
javah -classpath ../jnitest/bin com.hello.jnitest.Nadd com_hello_jnitest_Nadd .h文件:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include
/* Header for class com_hello_jnitest_Nadd */
#ifndef _Included_com_hello_jnitest_Nadd #define _Included_com_hello_jnitest_Nadd #ifdef __cplusplus extern \#endif /*
* Class: com_hello_jnitest_Nadd * Method: nadd * Signature: (II)I */
JNIEXPORT jint JNICALL Java_com_hello_jnitest_Nadd_nadd (JNIEnv *, jobject, jint, jint);
#ifdef __cplusplus }
#endif #endif
3.编辑.c文件实现native方法。 com_hello_jnitest_Nadd.c文件: #include
#include \
JNIEXPORT jint JNICALL Java_com_hello_jnitest_Nadd_nadd(JNIEnv * env, jobject c, jint a, jint b) {
return (a+b); }
4.编译.c文件生存动态库。 arm-none-linux-gnueabi-gcc -I/home/a/work/android/jdk1.6.0_17/include -I/home/a/work/android/jdk1.6.0_17/include/linux -fpic -c com_hello_jnitest_Nadd.c arm-none-linux-gnueabi-ld
-T/home/a/CodeSourcery/Sourcery_G++_Lite/arm-none-linux-gnueabi/lib/ldscripts/armelf_linux_eabi.xsc -share -o libNadd.so com_hello_jnitest_Nadd.o 得到libNadd.so文件。 以上在ubuntu中完成。
5.将相应的动态库文件push到avd的system/lib中:adb push libNadd.so /system/lib。若提示Read-only file system错误,运行adb remount命令,即可。 Adb push libNadd.so /system/lib
6.在eclipsh中运行原应用程序即可。 以上在windows中完成。
对于一中生成的so文件也可采用二中的方法编译进apk包中。只需在工程文件夹中建libs\\armeabi文件夹(其他文件夹名无效,只建立libs文件夹也无效),然后将so文件拷入,编译工程即可。
二.使用NDK生成本地方法(ubuntu and windows)
1.安装NDK:解压,然后进入NDK解压后的目录,运行build/host-setup.sh(需要Make 3.81和awk)。若有错,修改host-setup.sh文件:将#!/bin/sh修改为#!/bin/bash,再次运行即可。 2.在apps文件夹下建立自己的工程文件夹,然后在该文件夹下建一文件Application.mk和项project文件夹。
Application.mk文件:
APP_PROJECT_PATH := $(call my-dir)/project APP_MODULES := myjni
3.在project文件夹下建一jni文件夹,然后新建Android.mk和myjni.c。这里不需要用javah生成相应的.h文件,但函数名要包含相应的完整的包、类名。 4.编辑相应文件内容。 Android.mk文件:
# Copyright (C) 2009 The Android Open Source Project #
# Licensed under the Apache License, Version 2.0 (the \# 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 \
# 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. #
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := myjni LOCAL_SRC_FILES := myjni.c
include $(BUILD_SHARED_LIBRARY)
myjni.c文件:
#include
jstring
Java_com_hello_NdkTest_NdkTest_stringFromJNI( JNIEnv* env,
jobject thiz ) {
return (*env)->NewStringUTF(env, \}
myjni文件组织:
a@ubuntu:~/work/android/ndk-1.6_r1/apps$ tree myjni myjni
|-- Application.mk `-- project |-- jni
| |-- Android.mk | `-- myjni.c `-- libs
`-- armeabi
`-- libmyjni.so
4 directories, 4 files
5.编译:make APP=myjni.
以上内容在ubuntu完成。以下内容在windows中完成。当然也可以在ubuntu中完成。 6.在eclipsh中创建android application。将myjni中自动生成的libs文件夹拷贝到当前工程文件夹中,编译运行即可。 NdkTest.java文件:
package com.hello.NdkTest;
import android.app.Activity; import android.os.Bundle;
import android.widget.TextView;
public class NdkTest extends Activity {
/** Called when the activity is first created. */ @Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView tv = new TextView(this); tv.setText( stringFromJNI() ); setContentView(tv); }
public native String stringFromJNI();
static {
System.loadLibrary(\ } }
对于二中生成的so文件也可采用一中的方法push到avd中运行。 序
这四种情况下你会用到本书:
1、 在Java程序中复用以前写过的C/C++代码。 2、 自己实现一个java虚拟机
3、 学习不同语言如何进行协作,尤其是如何实现垃圾回收和多线程。 4、 把一个虚拟机实现整合到用C/C++写的程序中。
本书是写给开发者的。JNI在1997年第一次发布,本书总结了SUN工程师和大量开发者两年来积累的经验。
本书介绍了JNI的设计思想,对这种思想的理解是使用JNI的各种特性的基础。 本书有一部分是JAVA2平台上面的JNI特征的规范说明。JNI程序员可以把这部分用作一个手册。JVM开发者在实现虚拟机的时候必须遵守这些规范。
JNI的部分设计思想来源于Netscape的Java Runtime Interface(JRI)。
第一章 简介
JNI是JAVA平台的一个重要特征,使用它我们可以重用以前用C/C++写的大量代码。本书既是一个编程指南也是一个JNI手册。本书共包括三部分:
1、 第二章通过一个简单的例子介绍了JNI。它的对象是对JNI不熟悉的初学者。
2、 3~10章对JNI的特征进行了系统的介绍。我们会举大量的例子来说明JNI的各个特征,
这些特征都是JNI中重要且常用的。
3、 11~13章是关于JNI的技术规范。可以把这两章当作一个手册。
本书尽量去满足各类读者的需要。指南面向初学者,手册面向有经验的人和自己实现JNI规范的人。大部分读者可能是用JNI来写程序的开发者。本书会假设你有JAVA,C/C++基础。
本章的剩余部分介绍了JNI的背景,扮演的角色和JNI的演化。
1.1 JAVA平台和系统环境(Host Environment)
系统环境代指本地操作系统环境,它有自己的本地库和CPU指令集。本地程序(Native Applications)使用C/C++这样的本地语言来编写,被编译成只能在本地系统环境下运行的二进制代码,并和本地库链接在一起。本地程序和本地库一般地会依赖于一个特定的本地系统环境。比如,一个系统下编译出来的C程序不能在另一个系统中运行。