lin20080410的专栏

从站在巨人的肩上,向成为巨人迈进... 互相学习!

android jni的使用,java中代码在native层实现

这里主要是依据jni规范来实现java跟native的交互,在android环境下过程是类似的,只是native方法的名字要简洁很多,可以参见:http://blog.csdn.net/lin20044140410/article/details/50629836

android应用层几乎都是java语言写的,application framework层多数也都是java代码,一些底层的系统库是用C,C++写的,所以上层的java代码要使用底层的lib库就要使用jni来实现,下面以HelloNativeDemo为例,来学习如何通过jni让java调用C、C++的代码,完成jni的大致有这几步:

       1)写一个jave类,用来声明带有native的方法,同时也要加载动态库
      2)获得这个jave类的.class文件,可以使用javac命令,也可以从app的bin目录获取
      3)依据上一步的.class文件,使用javah -jni java类名,生成扩展名为h的头文件,其实这一步不是必须的,生成这个.h的头文件,多半是为了书写native函数方便,因为这个函数名字可以直接从.h文件复制,在C文件中写的native函数,一定要符合jni的规范
      4)编写实现natvie方法的C 或者C++文件
      5)把C/C++编写的文件生成动态连接库
      
1,首先通过eclipse新建一个app,取名:HelloNativeDemo,其中包含2个类文件:
一个是app的显示类MainActivity :
package com.nativedemo.hellonativedemo;


import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.util.Log;


public class MainActivity extends Activity {


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

JniDemo mJniDemo =new JniDemo();
mJniDemo.displayHelloJniStr();
Log.d("Hellojni","hello jni" +mJniDemo.getHelloJniStr());
}
。。。。。。
}


一个是负责声明本地方法的java类:
package com.nativedemo.hellonativedemo;
public class JniDemo{
//加载库文件 
    static {
System.loadLibrary("helloworldjni");
    }
    //声明要在native层实现的函数
public native void displayHelloJniStr();
public native String getHelloJniStr();
public native void noNativeFun();
}




2,然后到app的根目录,我是把app的代码放在linux的服务器上执行的。

首先进到code\LINUX\android\packages\apps\HelloNativeDemo\src\com\nativedemo\hellonativedemo这个目录,执行 javac JniDemo.java 生成JniDemo.class,然后退到目录code\LINUX\android\packages\apps\HelloNativeDemo\src这里,执行javah -jni com.nativedemo.hellonativedemo.JniDemo,生成com_nativedemo_hellonativedemo_JniDemo.h,这里执行javah命令一定要在源码的根目录,在JniDemo.java的同级目录执行javah会报错。
com_nativedemo_hellonativedemo_JniDemo.h内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_nativedemo_hellonativedemo_JniDemo */


#ifndef _Included_com_nativedemo_hellonativedemo_JniDemo
#define _Included_com_nativedemo_hellonativedemo_JniDemo
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_nativedemo_hellonativedemo_JniDemo
 * Method:    displayHelloJniStr
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_nativedemo_hellonativedemo_JniDemo_displayHelloJniStr
  (JNIEnv *, jobject);


/*
 * Class:     com_nativedemo_hellonativedemo_JniDemo
 * Method:    getHelloJniStr
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_nativedemo_hellonativedemo_JniDemo_getHelloJniStr
  (JNIEnv *, jobject);


/*
 * Class:     com_nativedemo_hellonativedemo_JniDemo
 * Method:    noNativeFun
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_nativedemo_hellonativedemo_JniDemo_noNativeFun
  (JNIEnv *, jobject);


#ifdef __cplusplus
}
#endif
#endif




3,在app所在根目录新建一个helloWorldJni的文件夹,即是目录:\code\LINUX\android\packages\apps\HelloNativeDemo\helloWorldJni在这里放置文件前面步骤提到的文件:JniDemo.java,JniDemo.class,com_nativedemo_hellonativedemo_JniDemo.h,然后编写本地实现的JniDemoImpl.c文件,这个文件就是去实现com_nativedemo_hellonativedemo_JniDemo.h里面声明的方法,JniDemoImpl.c内容如下:
include <jni.h>
include "JNIHelp.h"
include <com_nativedemo_hellonativedemo_JniDemo.h>
include <android/log.h>


#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "JniDemo", __VA_ARGS__)
/*
 * Class:     HelloJniDemo
 * Method:    displayHelloJniStr
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_nativedemo_hellonativedemo_JniDemo_displayHelloJniStr
  (JNIEnv* jniEnv, jobject obj){
LOGD("helloJniDemo display string \n");
}


/*
 * Class:     HelloJniDemo
 * Method:    getHelloJniStr
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_nativedemo_hellonativedemo_JniDemo_getHelloJniStr
  (JNIEnv* jniEnv, jobject obj){
   //const char* str= "from jin string";
   char str[32]="from jin string";
   /*获取string类型,要借助于这个函数:NewStringUTF,并且这个函数的使用在c和c++里面是不一样的,这里是c语言的实现方式,如果是c++文件,要这么写:jstring jStr = jniEnv->NewStringUTF(str);
   */
   jstring jStr = (*jniEnv)->NewStringUTF(jniEnv,str);
return jStr;
}


/*
 * Class:     HelloJniDemo
 * Method:    noNativeFun
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_nativedemo_hellonativedemo_JniDemo_noNativeFun
  (JNIEnv* jniEnv, jobject obj){
LOGD("Hello jni demo LIB,no native !/n");
}


4,编写Android.mk文件,生成动态连接库,
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)


LOCAL_LDLIBS := -llog


LOCAL_SRC_FILES := \
JniDemoImpl.c \
        JniCppDemoImple.cpp


LOCAL_C_INCLUDES := \
    $(JNI_H_INCLUDE)


LOCAL_SHARED_LIBRARIES := \
    libutils \
    libcutils


LOCAL_PRELINK_MODULE := false


#LOCAL_MULTILIB := 64
LOCAL_MODULE:= libhelloworldjni


include $(BUILD_SHARED_LIBRARY) 


该文件的一些全局变量的含义:
LOCAL_PATH的定义必须要放到所有的include $(CLEAR_VARS)之前,
LOCAL_PATH通过调用my-dir函数来获取当前的路径,
LOCAL_SRC_FILES  编译的源文件
LOCAL_C_INCLUDES  需要包含的头文件目录
LOCAL_SHARED_LIBRARIES  链接时需要的外部库
LOCAL_PRELINK_MODULE  是否需要 prelink 处理
LOCAL_MODULE  编译的目标对象
BUILD_SHARED_LIBRARY  指明要编译成动态库


5,添加应用app的Android.mk 内容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional


#LOCAL_STATIC_JAVA_LIBRARIES := libarity android-support-v4 guava ejml \
#        android-support-v7-recyclerview
LOCAL_JNI_SHARED_LIBRARIES := libhelloworldjni


LOCAL_SRC_FILES := $(call all-java-files-under, src)


LOCAL_SDK_VERSION := current


LOCAL_PACKAGE_NAME := HelloNativeDemo


#LOCAL_PROGUARD_ENABLED := full
#LOCAL_PROGUARD_FLAG_FILES := proguard.flags


include $(BUILD_PACKAGE)


# Use the following include to make our test apk.
include $(call all-makefiles-under,$(LOCAL_PATH))


主要是添加 LOCAL_JNI_SHARED_LIBRARIES := libhelloworldjni 这句


6,执行./make mmma ./packages/apps/HelloNativeDemo 这个编译命令是在高通项目中的方式,其他平台可能会有差异。编译完成生成了:
\system\app\HelloNativeDemo\HelloNativeDemo.apk
\system\lib\libhelloworldjni.so
分别push到手机中的对应目录即可。
阅读更多
版权声明:笔记记录,互相学习,不足之处,欢迎指正! https://blog.csdn.net/lin20044140410/article/details/50605663
文章标签: jni native android
个人分类: android开发
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭