android jni和ndk (一 ) eclipse版本实现

一下是用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




猜你喜欢

转载自blog.csdn.net/qq_37610155/article/details/80136591