一下是用eclipe ide实现的ndk开发的jni的例子。
目录结构如下:
E:.
├─.settings
├─assets
├─bin
│ ├─classes
│ │ ├─android
│ │ │ └─support
│ │ │ └─v7
│ │ │ └─appcompat
│ │ └─com
│ │ └─example
│ │ └─jnitest
│ ├─dexedLibs
│ └─res
│ └─crunch
│ ├─drawable-hdpi
│ ├─drawable-mdpi
│ ├─drawable-xhdpi
│ └─drawable-xxhdpi
├─gen
│ ├─android
│ │ └─support
│ │ └─v7
│ │ └─appcompat
│ └─com
│ └─example
│ └─jnitest
├─jni
├─libs
│ └─armeabi
├─obj
│ └─local
│ └─armeabi
│ └─objs
│ └─StringJni
├─res
│ ├─drawable-hdpi
│ ├─drawable-ldpi
│ ├─drawable-mdpi
│ ├─drawable-xhdpi
│ ├─drawable-xxhdpi
│ ├─layout
│ ├─menu
│ ├─values
│ ├─values-v11
│ ├─values-v14
│ └─values-w820dp
└─src
└─com
└─example
└─jnitest
目录简单说明下,assets res都是资源文件,obj libs gen bin都是生成的,src是我们需要的java源代码目录,jni是c/c++源代码目录。
我先以最简单从native cpp返回一个字符串的用例讲下ndk jni开发的完整结构.
首先写两个类,一个是有用显示的MainActivity类,另一个用于专门jni的StringJni java类。
MaianActivity.java
package com.example.jnitest;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity {
private TextView Stirngformjni;
private String str;
private TextView sum;
private int tmp;
private String sumStr;
private TextView init2DArray;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 1. jni native string to java string
Stirngformjni = (TextView) findViewById(R.id.stirngformjni);
StringJni stringJni = new StringJni();
str = stringJni.stringjni();
str = "1. " + str ;
Stirngformjni.setText(str);
//2.jni string to native
stringJni.stringTojni("hello");
//3.jni native int to java int
sum = (TextView) findViewById(R.id.sum);
JniAdd jniAdd = new JniAdd();
tmp = jniAdd.Add(2, 8);
sumStr = tmp +" ";
sum.setText(sumStr);
//4. jintArray int[]
int sum =0;
IntArray intArray = new IntArray();
int[] int_array = {1,2,3,4,5} ;
sum = intArray.SumIntArray(int_array);
Toast.makeText(this, "this is intArray sum from jni: "+sum, Toast.LENGTH_SHORT).show();
//5. int[][] from native
init2DArray = (TextView) findViewById(R.id.init2DArray);
Int2DArray init2DArry = new Int2DArray();
int[][]i2dArray = init2DArry.initInt2DArray(10);
StringBuilder strd = new StringBuilder();
for(int i=0; i<i2dArray.length;i++){
for(int j=0; j<i2dArray[i].length;j++){
strd.append(i2dArray[i][j]+" ");
}
}
init2DArray.setText(strd );
//6. c++ access java class data and method
JavaClassAccess jclassAccess = new JavaClassAccess();
jclassAccess.nativeMethod();
Log.d("MainActivity", "wanlihua debug JavaClassAccess num value before: " + jclassAccess.num);
//ClassC classC = new ClassC(0.007);
ClassC.nativeMethodC();
Log.d("MainActivity", "wanlihua debug ClassC.nativeMethodC num value after: " + ClassC.getD());
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
StringJni.java
package com.example.jnitest;
public class StringJni {
static {
System.loadLibrary("StringJni");
}
public native String stringjni();
public native void stringTojni(String str);
}
然后把StringJni.java用javah生成c/c++调用的.h文件
在eclipse开发环境下,进到HelloJni\bin\classes 目录下,
输入 javah -d ../../jni com.example.jnitest.JavaClassAccess
则在代码根目录生成jni目录,并生成com_example_jnitest_StringJni.h
如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_jnitest_StringJni */
#ifndef _Included_com_example_jnitest_StringJni
#define _Included_com_example_jnitest_StringJni
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_jnitest_StringJni
* Method: stringjni
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_jnitest_StringJni_stringjni
(JNIEnv *, jobject);
/*
* Class: com_example_jnitest_StringJni
* Method: stringTojni
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_example_jnitest_StringJni_stringTojni
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
然后这样就编写c/cpp代码并include该头文件。
#include <jni.h>
#include "com_example_jnitest_StringJni.h"
#include <android/log.h>
#include <stdio.h>
//#include <utils/Log.h>
//#include "cutils/log.h"
#define TAG "StringJni"
#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__))
JNIEXPORT jstring JNICALL Java_com_example_jnitest_StringJni_stringjni
(JNIEnv *env, jobject obj){
//LOG_PRI (ANDROID_LOG_WARN, NXPLOG_ITEM_EXTNS, __VA_ARGS__);
LOGD("XXX debug Java_com_example_jnitest_StringJni_stringjni!!!");
__android_log_print(ANDROID_LOG_DEBUG,"StringJni","XXX debug Java_com_example_jnitest_StringJni_stringjni __android_log_print");
return env->NewStringUTF("i'm from stringjni");
}
然后在写上对这个jni目录的源码写上android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := StringJni
LOCAL_SRC_FILES := StringJni.cpp
LOCAL_LDLIBS := -llog
#LOCAL_SHARED_LIBRARIES := liblog
LOCAL_PROGUARD_ENABLED:= disabled
include $(BUILD_SHARED_LIBRARY)
然后在MainActivity中加入
// 1. jni native string to java string
Stirngformjni = (TextView) findViewById(R.id.stirngformjni);
StringJni stringJni = new StringJni();
str = stringJni.stringjni();
str = "1. " + str ;
Stirngformjni.setText(str);
调用native 本地方法。
然后而eclipse设置过ndk环境,这时候就可以直接编译app了。大功告成。
然后把别的 在natvie实现加法,数组传递,c++调用java的属性等等都贴出来。
JniAdd.java :cpp实现算法(加法)
package com.example.jnitest;
public class JniAdd {
static {
System.loadLibrary("StringJni");
}
public native int Add(int a,int b);
}
JniTest/jni/com_example_jnitest_JniAdd.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_jnitest_JniAdd */
#ifndef _Included_com_example_jnitest_JniAdd
#define _Included_com_example_jnitest_JniAdd
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_jnitest_JniAdd
* Method: Add
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_example_jnitest_JniAdd_Add
(JNIEnv *, jobject, jint, jint);
#ifdef __cplusplus
}
#endif
#endif
IntArray.java :传递一维整型数组
package com.example.jnitest;
public class IntArray {
static {
System.loadLibrary("StringJni");
}
public native int SumIntArray (int[]arr);
}
JniTest/jni/com_example_jnitest_IntArray.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_jnitest_IntArray */
#ifndef _Included_com_example_jnitest_IntArray
#define _Included_com_example_jnitest_IntArray
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_jnitest_IntArray
* Method: Add
* Signature: ([I)I
*/
JNIEXPORT jint JNICALL Java_com_example_jnitest_IntArray_SumIntArray
(JNIEnv *, jobject, jintArray);
#ifdef __cplusplus
}
#endif
#endif
Int2DArray.java : 传递二维数组,二维数组会作为一个object处理
package com.example.jnitest;
public class Int2DArray {
static {
System.loadLibrary("StringJni");
}
public native int[][] initInt2DArray (int size);
}
JniTest/jni/com_example_jnitest_Int2DArray.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_jnitest_Int2DArray */
#ifndef _Included_com_example_jnitest_Int2DArray
#define _Included_com_example_jnitest_Int2DArray
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_jnitest_Int2DArray
* Method: initInt2DArray
* Signature: (I)[[I
*/
JNIEXPORT jobjectArray JNICALL Java_com_example_jnitest_Int2DArray_initInt2DArray
(JNIEnv *, jobject, jint);
#ifdef __cplusplus
}
#endif
#endif
JavaClassAccess.java : c/c++访问java成员和成员函数。
package com.example.jnitest;
import android.util.Log;
public class JavaClassAccess {
String str = "smj";
int num = 8;
public native void nativeMethod();
private void javaMethod(){
System.out.println("call java method sucessful!");
Log.d("JavaClassAccess", "wanlihua debug start from native callback!!!");
}
static{
System.loadLibrary("StringJni");
}
}
JniTest/jni/com_example_jnitest_JavaClassAccess.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_jnitest_JavaClassAccess */
#ifndef _Included_com_example_jnitest_JavaClassAccess
#define _Included_com_example_jnitest_JavaClassAccess
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_jnitest_JavaClassAccess
* Method: nativeMethod
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_example_jnitest_JavaClassAccess_nativeMethod
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif