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("The Native Add Result is " +
String.valueOf(cal.nadd(10, 19)));
}
}
Nadd.java
文件:
package com.hello.jnitest;
public class Nadd {
static {
System.loadLibrary("Nadd");
}
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 "C" {
#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 "com_hello_jnitest_Nadd.h"
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
"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.
#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := myjni
LOCAL_SRC_FILES := myjni.c
include $(BUILD_SHARED_LIBRARY)
myjni.c
文件:
#include
#include
jstring
Java_com_hello_NdkTest_NdkTest_stringFromJNI( JNIEnv*
env,
jobject thiz )
{
return (*env)->NewStringUTF(env, "Hello from
My-JNI !");
}
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("myjni");
}
}
对于二中生成的so
文件也可采用一中的方法push
到avd
中运行。