1  案例场景,通过C语言回调Java的代码,案例的最终界面:

2  案例的代码结构如下:

3 编写DataProvider的代码:

package com.example.ndkcallback;

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();

}

4 通过DataProvider获得头文件

接着带有header的结构如下:

5 编写MainActivity代码:

package com.example.ndkcallback;

import android.os.Bundle;

import android.support.v7.app.ActionBarActivity;

import android.view.View;

public class MainActivity extends ActionBarActivity {

DataProvider dp;

static {

System.loadLibrary("hello");

}

public void helloFromJava() {

System.out.print("哈哈哈,我被调用了");

}

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

dp = new DataProvider();

}

public void click1(View view){

dp.callMethod1();

}

public void click2(View view){

dp.callMethod2();

}

public void click3(View view){

dp.callMethod3();

}

public void click4(View view){

dp.callMethod4();

}

public void click5(View view){

dp.callMethod5();

}

}

6 编写布局文件activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".MainActivity" >

<Button

android:onClick="click1"

android:id="@+id/button1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_alignParentTop="true"

android:text="回调javahelloFromJava" />

<Button

android:onClick="click2"

android:id="@+id/button2"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_below="@+id/button1"

android:text="回调javaAdd" />

<Button

android:onClick="click3"

android:id="@+id/button3"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_below="@+id/button2"

android:text="回调javaPrintString" />

<Button

android:onClick="click4"

android:id="@+id/button4"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_below="@+id/button3"

android:text="回调java中其它类的方法" />

<Button

android:onClick="click5"

android:id="@+id/button5"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_below="@+id/button4"

android:text="回调java中静态的方法" />

</RelativeLayout>

7 接下来,通过javap命令获得DataProvider的方法签名,在cygwin上进入/NdkCallBack/bin/classes.

命令如下:

toto@toto-PC /cygdrive/e/workspace/Android/NdkCallBack/bin/classes

$ javap -scom.example.ndkcallback.DataProvider

上面红框圈的分别是执行命令和方法签名。这个签名在hello.c中会用到。

7 接下来编写hello.c

#include "com_example_ndkcallback_DataProvider.h"

/**

* 调用:DataProvider中的 public void helloFromJava();

*/

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*)

//方法签名   参数和返回值

//GetMethodID中参数分别是env指针,class,方法名,方法签名

jmethodID methodId=(*env)->GetMethodID(env,clazz,"helloFromJava","()V");

//通过 void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);来调用Java的代码

(*env)->CallVoidMethod(env,jobject,methodId);

}

/**

* 调用:DataProvider中的 public int Add(int, int);

*/

JNIEXPORT void JNICALL Java_com_example_ndkcallback_DataProvider_callMethod2

(JNIEnv *env, jobject jobject) {

jclass clazz=(*env)->FindClass(env,"com/example/ndkcallback/DataProvider");

//这里的方法签名中有几个I表示有几个参数

jmethodID methodId=(*env)->GetMethodID(env,clazz,"Add","(II)I");

// jint        (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);

(*env)->CallIntMethod(env,jobject,methodId,3,5);

}

/**

* 调用:DataProvider中的 public void printString(java.lang.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);

}

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);

}

8 编写Android.mk文件,内容如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := libhello

LOCAL_SRC_FILES := Hello.c

include $(BUILD_SHARED_LIBRARY)

9 编写Android的清单文件,内容如下:

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="com.example.ndkcallback"

android:versionCode="1"

android:versionName="1.0" >

<uses-sdk

android:minSdkVersion="8"

android:targetSdkVersion="19" />

<application

android:allowBackup="true"

android:icon="@drawable/ic_launcher"

android:label="@string/app_name"

android:theme="@style/AppTheme" >

<activity

android:name="com.example.ndkcallback.MainActivity"

android:label="@string/app_name" >

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

</application>

</manifest>

10 交叉编译,生成.so文件

成功之后,查看Android控制台打印的结果

03_Android NDK中C语言调用Java代码,javah的使用,javap的使用以及生成签名,Android.mk的编写,C代码的编写的更多相关文章

  1. Android NDK开发之C调用Java及原生代码断点调试(二)

    上一篇中,我们主要学习了Java调用本地方法,并列举了两大特殊实例来例证我们的论据,还没学习的伙伴必须先去阅读下,本次的学习是直接在上一篇的基础上进行了.点击:Android NDK开发之从Java与 ...

  2. C++ 跨语言调用 Java

    C++ 跨语言调用 Java Java JDK 提供了 JNI 接口供 C/C++ 程序调用 Java 编译后的类与方法,主要依赖于头文件(jni.h) 和 动态库(jvm.so/jvm.dll),由 ...

  3. HAL中通过JNI调用java方法【转】

    转载请注明本文出处:http://www.cnblogs.com/xl19862005 作者:Xandy 由于工作的需要,最近一直在研究HAL.JNI.Java方法之间互调的问题,并做了如下一些记录和 ...

  4. JNI系列——C文件中的方法调用Java中方法

    1.创建xxx.jni包并在该包下实现一些Java的方法,和要调用的本地方法 2.实现MainActivity中的按钮点击事件-即点击按钮调用本地的方法 3.在C文件中的方法中回调Java的方法 3. ...

  5. Android NDK开发之Jni调用Java对象

    https://my.oschina.net/zhiweiofli/blog/114064 通过使用合适的JNI函数,你可以创建Java对象,get.set 静态(static)和 实例(instan ...

  6. Webview 中 Javascript 无法调用 Java 对象

    [问题产生] Webview 通过 addjavascriptInterface 传递对象给前端,一切正常.但是 Android官方已提醒此功能是有安全风险,改用 safe-java-js-webvi ...

  7. JNI NDK (AndroidStudio+CMake )实现C C++调用Java代码流程

    JNI/NDK Java调用C/C++前言  通过第三篇文章讲解在实际的开发过程中Java层调用C/C++层的处理流程.其实我们在很大的业务里也需要C/C+ +层去调用Java层,这两层之间的相互调用 ...

  8. NDK(19)简单示例:ndk调用java基本方法、数组;使用stl、访问设备

    一.ndk调用java类示例 1,调用基本方法 /* * Class: com_example_ndksample_MainActivity * Method: ndkFindJavaClass * ...

  9. Android NDK开发(1)----- Java与C互相调用实例详解

    链接地址:http://www.cnblogs.com/lknlfy/archive/2012/03/13/2394153.html 一.概述 对于大部分应用开发者来说可能都不怎么接触到NDK,但如果 ...

随机推荐

  1. Ubuntu 16.04 + ROS Kinetic 机器人操作系统学习镜像分享与使用安装说明

    Ubuntu 16.04 + ROS Kinetic 镜像分享与使用安装说明 内容概要:1 网盘文件介绍  2 镜像制作  3 系统使用与安装 ---- 祝ROS爱好者和开发者新年快乐:-) ---- ...

  2. Java经典设计模式之五大创建型模式(附实例和详解)

    一.概况 总体来说设计模式分为三大类: (1)创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. (2)结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥 ...

  3. Android中Sqlite数据库进行增删改查

    今天这篇文章写Sqlite数据库,通过一个小案例来完整讲一下数据库常见的CRUD操作. 先对知识点总结: SQLite数据库 轻量级关系型数据库 创建数据库需要使用的api:SQLiteOpenHel ...

  4. Android源码浅析(五)——关于定制系统,如何给你的Android应用系统签名

    Android源码浅析(五)--关于定制系统,如何给你的Android应用系统签名 今天来点简单的我相信很多定制系统的同学都会有一些特定功能的需求,比如 修改系统时间 静默安装 执行某shell命令 ...

  5. Android开发之Path类使用详解,自绘各种各样的图形!

    玩过自定义View的小伙伴都知道,在View的绘制过程中,有一个类叫做Path,Path可以帮助我们实现很多自定义形状的View,特别是配合xfermode属性来使用的时候.OK,那我们今天就来看看P ...

  6. 剑指Offer——CVTE校招笔试题+知识点总结(Java岗)

    剑指Offer(Java岗)--CVTE校招笔试题+知识点总结 2016.9.3 19:00参加CVTE笔试,笔试内容如下: 需要掌握的知识:Linux基本命令.网络协议.数据库.数据结构. 选择题 ...

  7. 15 ActionBar 总结

    ActionBar 一, 说明 是一个动作栏 是窗口特性 提供给用户动作 导航模式 可以适配不同的屏幕 二, ActionBar 提供的功能 1. 显示菜单项 always:总是展示到ActionBa ...

  8. 1.3、Android Studio创建一个Android Library

    一个Android Library结构上与Android app模块相同.它可以包含构建一个app需要的所有东西,包括圆满,资源文件和AndroidManifest.xml.然而,并非编译成运行在设备 ...

  9. TCP连接建立系列 — 客户端的端口选取和重用

    主要内容:connect()时的端口选取和端口重用. 内核版本:3.15.2 我的博客:http://blog.csdn.net/zhangskd 端口选取 connect()时本地端口是如何选取的呢 ...

  10. 【Netty源码学习】入门示例

    Netty是由JBOSS提供的一个java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序.        也就是说,Netty ...