关闭

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

标签: jni native android
961人阅读 评论(0) 收藏 举报
分类:
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到手机中的对应目录即可。
0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

android Java与JNI层互相调用

Java层调用JNI中的函数首先在TextJNI.java层创建一个类TextJNI,类中使用一些native方法package com.example.androidjni; import andr...
  • luckywang1103
  • luckywang1103
  • 2015-08-28 14:25
  • 1882

Android平台Native代码的崩溃捕获机制及实现

原文:http://blog.httrack.com/blog/2013/08/23/catching-posix-signals-on-android/ 这篇文章主要讲述如何捕获jni crash,...
  • mba16c35
  • mba16c35
  • 2017-01-07 21:19
  • 3586

如何查找native方法

在看framework层代码时,经常会看到native方法,这是往往需要查看所对应的C++方法在哪个文件,对应哪个方法?下面从一个实例出发带大家如何查看java层方法所对应的native方法位置。实例...
  • hp910315
  • hp910315
  • 2016-06-22 12:24
  • 2339

Android NDK(JNI)学习总结一:Java代码中申明native函数-Java调用C函数,并在C函数中访问java类和方法、属性

本文不涉及android-ndk开发环境搭。步骤一:新建一个APP,名称为HelloJNI,然后定义一个类(将会在native代码中调用和访问该类):/* * mynative.cpp * * ...
  • daizhongyin
  • daizhongyin
  • 2015-07-14 17:31
  • 1240

Android Java_JNI_Native

  • 2011-07-02 11:06
  • 171KB
  • 下载

JNI native层、C++异步回调JAVA代码。JNI数据类型转换

  • luoyuehao
  • luoyuehao
  • 2014-08-04 15:42
  • 362

java通过jni native method 调用非java语言的代码,例:c++

jni调用非java代码过程的详细步骤整个过程基本是正确的, 唯一个问题是自己遇到的: 就是用vs2015新建项目生成dll文件的时候不知道怎么区分是32位的还是64位的,我做java的,对vs工具不...
  • wuruijie321
  • wuruijie321
  • 2017-12-22 11:27
  • 38

Android JNI学习笔记(四)-数据类型映射以及native调用java

1. 前言前几篇学习了jni开发的基本流程、动态注册native函数以及相关编译文件的编写,咱们也算是知道了jni开发,但是还不够,今天咱们来学习下,java和jni的数据类型映射(说白了就是对应关系...
  • qq_21430549
  • qq_21430549
  • 2016-11-30 00:03
  • 3115

【学习Android NDK开发】native code通过JNI调用Java方法

转载自:http://www.cnblogs.com/xitang/p/4174619.html 转载自:http://www.cnblogs.com/dyingbleed/archive/2012...
  • qq_35904259
  • qq_35904259
  • 2017-04-10 15:16
  • 665

#菜鸟之旅#Android Studio开发JNI工程——Native调用Java方法获取IMEI

Android Studio,JNI,IMEI
  • JeanneYan
  • JeanneYan
  • 2016-10-31 17:30
  • 226
    个人资料
    • 访问:35838次
    • 积分:1724
    • 等级:
    • 排名:千里之外
    • 原创:133篇
    • 转载:38篇
    • 译文:0篇
    • 评论:9条
    最新评论