小技巧:自动生成 java本地方法对应的c代码的方法名 javah 指令 +全类名

java1.6版本 class
C:\workspace\HelloWorldFromC2\bin\classes

java1.7以上 src
C:\workspace\HelloWorldFromC2\src

获得方法的签名的方法

javap -s 打印方法的签名 注意要cd到 C:\workspace\HelloWorldFromC2\bin\classes 传全类名

Android.mk文件的书写

Anroid.mk 文件
LOCAL_PATH := $(call my-dir) // 返回当前c代码目录
include $(CLEAR_VARS) // 清楚了所有 已local 开头的配置文件 唯独不清楚LOCAL_PATH LOCAL_MODULE := hello // 库函数的名字 严格遵守makefile 格式 lib .so 如果前面加lib 不会自动生成了
LOCAL_SRC_FILES := Hello.c
include $(BUILD_SHARED_LIBRARY) // 加入库函数

java调用C方法,并且传递参数

/**
* 计算x和y的加法 apktools
* 315
* @param x
* @param y
* @return
*/
public native int add(int x ,int y); // char String short kiss keep it simple and stupid String[] "123:234"
/**
* 给字符串后面拼装字符 加密运算 web url
* @param s
* @return
*/
public native String sayHelloInC(String s);
//
/**
* 给c代码传递int数组 让c代码给这个数组进行操作
* 图形 声音的处理
* @param iNum
* @return
*/
public native int[] intMethod(int[] iNum);

C代码输出到控制台上LOG

#define LOG_TAG "clog"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

传递两个int实现

JNIEXPORT jint JNICALL Java_com_example_ndkpassdata_DataProvider_add
(JNIEnv * env, jobject jobject, jint x, jint y){
// 想在logcat控制台上 打印日志
LOGD("x=%d",x);
LOGI("y=%d",y);
// log.i(TAG,"sss");
return x+y; }

字符串拼接实现

JNIEXPORT jstring JNICALL Java_com_example_ndkpassdata_DataProvider_sayHelloInC
(JNIEnv * env, jobject jobject, jstring str){ char* c="hello";
// 在C语言中不能直接操作java中的字符串
// 把java中的字符串转换成c语言中 char数组
char* cstr=Jstring2CStr(env,str); strcat(cstr,c);
LOGD("%s",cstr);
return (*env)->NewStringUTF(env,cstr);
}

传递数组实现

JNIEXPORT jintArray JNICALL Java_com_example_ndkpassdata_DataProvider_intMethod
(JNIEnv * env, jobject jobject, jintArray jarray){
// jArray 遍历数组 jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*);
// 数组的长度 jsize (*GetArrayLength)(JNIEnv*, jarray);
// 对数组中每个元素 +5
int length=(*env)->GetArrayLength(env,jarray);
int* array=(*env)->GetIntArrayElements(env,jarray,0);
int i=0;
for(;i<length;i++){
*(array+i)+=5;
}
return jarray;
}

C语言利用反射回调java方法

java的反射

Class<?> forName = Class.forName("com.example.ndkcallback.DataProvider");
Method declaredMethod = forName.getDeclaredMethod("helloFromJava", new Class[]{});
declaredMethod.invoke(forName.newInstance(), new Object[]{});

java中的方法的声明

public class DataProvider {
//C调用java空方法
public void helloFromJava(){
System.out.println("哈哈哈 我被调用了");
}
//C调用java中的带两个int参数的方法
public int Add(int x,int y){
int result=x+y;
System.out.println("result:"+result);
return result;
}
//C调用java中参数为string的方法
public void printString(String s){
System.out.println(s);
} public static void demo(){
System.out.println("哈哈哈,我是静态方法"); } public native void callMethod1();
public native void callMethod2();
public native void callMethod3();
public native void callMethod4();
public native void callMethod5();
}

实现

实现调用java空方法

JNIEXPORT void JNICALL Java_com_example_ndkcallback_DataProvider_callMethod1
(JNIEnv * env, jobject jobject){ /*
*
Class<?> forName = Class.forName("com.example.ndkcallback.DataProvider");
Method declaredMethod = forName.getDeclaredMethod("helloFromJava", new Class[]{});
declaredMethod.invoke(forName.newInstance(), new Object[]{});
*
*
*/
///jclass (*FindClass)(JNIEnv*, const char*);
jclass clazz=(*env)->FindClass(env,"com/example/ndkcallback/DataProvider");
// jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
// 方法签名 参数和返回值
jmethodID methodId=(*env)->GetMethodID(env,clazz,"helloFromJava","()V");
// void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
(*env)->CallVoidMethod(env,jobject,methodId);
}

实现调用int参数的方法

JNIEXPORT void JNICALL Java_com_example_ndkcallback_DataProvider_callMethod2
(JNIEnv * env, jobject jobject){
jclass clazz=(*env)->FindClass(env,"com/example/ndkcallback/DataProvider");
jmethodID methodId=(*env)->GetMethodID(env,clazz,"Add","(II)I");
// jint (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);
(*env)->CallIntMethod(env,jobject,methodId,3,5);
}

实现调用String参数的方法

JNIEXPORT void JNICALL Java_com_example_ndkcallback_DataProvider_callMethod3
(JNIEnv * env, jobject jobject){ // 参数 object 就是native方法所在的类
jclass clazz=(*env)->FindClass(env,"com/example/ndkcallback/DataProvider");
jmethodID methodId=(*env)->GetMethodID(env,clazz,"printString","(Ljava/lang/String;)V");
// jint (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);
jstring str=(*env)->NewStringUTF(env,"hello"); (*env)->CallVoidMethod(env,jobject,methodId,str); }

实现调用其他类中的方法,注意此时的object为该类的对象

JNIEXPORT void JNICALL Java_com_example_ndkcallback_DataProvider_callMethod4
(JNIEnv * env, jobject j){
jclass clazz=(*env)->FindClass(env,"com/example/ndkcallback/MainActivity");
// jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
// 方法签名 参数和返回值
jmethodID methodId=(*env)->GetMethodID(env,clazz,"helloFromJava","()V");
// void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
// 需要创建DataProvider的 对象
// jobject (*AllocObject)(JNIEnv*, jclass);
jobject obj=(*env)->AllocObject(env,clazz); // new MainActivity();
(*env)->CallVoidMethod(env,obj,methodId); }

实现调用静态方法

JNIEXPORT void JNICALL Java_com_example_ndkcallback_DataProvider_callMethod5
(JNIEnv * env, jobject j){
jclass clazz=(*env)->FindClass(env,"com/example/ndkcallback/DataProvider");
// jmethodID (*GetStaticMethodID)(JNIEnv*, jclass, const char*, const char*);
jmethodID methodid=(*env)->GetStaticMethodID(env,clazz,"demo","()V");
//void (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...);
(*env)->CallStaticVoidMethod(env,clazz,methodid);
}

完成

Android之jni深入的更多相关文章

  1. Android 通过JNI实现守护进程,使得Service服务不被杀死

    来自: http://finalshares.com/read-7306 转载请注明出处: http://blog.csdn.net/yyh352091626/article/details/5054 ...

  2. android的JNI 、 NDK 学习!

    转载的! Java Native Interface (JNI)标准是java平台的一部分,它允许Java代码和其他语言写的代码进行交互.JNI 是本地编程接口,它使得在 Java 虚拟机 (VM) ...

  3. Android 中JNI创建实例

    参考文档: http://blog.sina.com.cn/s/blog_a11f64590101924l.html http://www.cnblogs.com/hoys/archive/2010/ ...

  4. 【转】Android中JNI的使用方法

    Android中JNI的使用方法 首先看一下Android平台的框架图:(网上盗用) 可以看到Android上层的Application和ApplicationFramework都是使用Java编写, ...

  5. Android使用JNI(从java调用本地函数)

    当编写一个混合有本地C代码和Java的应用程序时,需要使用Java本地接口(JNI)作为连接桥梁.JNI作为一个软件层和API,允许使用本地代码调用Java对象的方法,同时也允许在Java方法中调用本 ...

  6. I.MX6 android BatteryService jni hacking

    /**************************************************************************** * I.MX6 android Batter ...

  7. Android中JNI编程的那些事儿(1)

    转:Android中JNI编程的那些事儿(1)http://mobile.51cto.com/android-267538.htm Android系统不允许一个纯粹使用C/C++的程序出现,它要求必须 ...

  8. 【转】Android与JNI(二) -- 不错

    原文网址:http://www.cnblogs.com/eddy-he/archive/2012/08/09/2629974.html 软件版本: ubuntu10.04 java version & ...

  9. (原)android的JNI中使用C++的类

    android的JNI代码中可以调用C++的类,但是不能直接调用,要加上一个类似于接口的java类,这个类内部调用C++的类.实际上和接口类直接调用C++中的函数差不多,只是稍微复杂了一点. 1. 写 ...

  10. [置顶] android利用jni调用第三方库——第三篇——编写库android程序整合第三方库libhello.so到自己的库libhelloword.so

    0:前言: 在第二篇中,我们主要介绍了丙方android公司利用乙方C++公司给的动态库,直接调用库中的方法,但是这样方式受限于: 乙方C++公司开发的动态库是否符合jni的规范,如果不规范,则不能直 ...

随机推荐

  1. 通过HTTP协议实现多线程下载

    1. 基本原理,每条线程从文件不同的位置开始下载,最后合并出完整的数据. 2. 使用多线程下载的好处     下载速度快.为什么呢?很好理解,以往我是一条线程在服务器上下载.也就是说,对应在服务器上, ...

  2. C语言学习-01第一个C语言程序

    一 C语言的历史 C语言是一门通用计算机编程语言,应用广泛.C语言的设计目标是提供一种能以简易的方式编译.处理低级存储器.产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言. 尽管C语言提供 ...

  3. Apple的App Analytics统计平台你必须知道的Q&A整理与翻译

    Apple的App Analytics统计平台你必须知道的Q&A整理与翻译 Apple最近在iTunesConnect里最新发布了App Analytics统计平台,提供了现有友盟统计平台和自 ...

  4. PHP时间比较和时间差如何计算

    1.<?php 2. $zero1=date(“y-m-d h:i:s”); 3. $zero2=”2010-11-29 21:07:00′; 4. echo “zero1的时间为:”.$zer ...

  5. vector与set区别(基础知识)

    首先,vector是序列式容器而set是关联式容器.set包含0个或多个不重复不排序的元素.也就是说set能够保证它里面所有的元素都是不重复的.另外对set容器进行插入时可以指定插入位置或者不指定插入 ...

  6. spring AOP面向切面编程学习笔记

    一.面向切面编程简介: 在调用某些类的方法时,要在方法执行前或后进行预处理或后处理:预处理或后处理的操作被封装在另一个类中.如图中,UserService类在执行addUser()或updateUse ...

  7. NoClassDefFoundError: org/slf4j/LoggerFactory解决

    缺少slf4j-api-1.5.2,slf4j-log4j12-1.5.2,log4j-1.2.8这几个包,导入即可

  8. Yacc 与 Lex 快速入门

    Yacc 与 Lex 快速入门 Lex 与 Yacc 介绍 Lex 和 Yacc 是 UNIX 两个非常重要的.功能强大的工具.事实上,如果你熟练掌握 Lex 和 Yacc 的话,它们的强大功能使创建 ...

  9. CentOS创建免密码SSH(密钥)

    1.输入以下命令:ssh-keygen -t rsa 2.输入命令ls:产生两个文件:id_rsa id_rsa.pub 3.复制id_rsa.pub,并命名为authorized_key cp ~/ ...

  10. Intent的Flag

    小段代码: Intent it=new Intent(); it.setClass(Setting.this,Main.class);//从Setting跳转到Main it.addFlags(Int ...