ndk开发中,在c中调用java代码

原创 2013年12月03日 15:27:29

在ndk开发中,在c中调用java代码其实是通过反射技术来实现的。


代码的下载链接为:http://download.csdn.net/detail/caihongshijie6/6649995

1、main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="c代码呼叫java的空方法"
        android:onClick="click1"
         />
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="c代码呼叫java的两个int参数的方法"
        android:onClick="click2"
         />
        <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="c代码呼叫java的string参数方法"
        android:onClick="click3"
         />
                <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="c代码呼叫java的静态string参数方法"
        android:onClick="click4"
         />
                                <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="在mainactivity里面调用空方法"
        android:onClick="click5"
         />
</LinearLayout>


2、DataProvider

package com.njupt.ndk_callback;

public class DataProvider {

	//C调用java空方法
	public void helloFromJava(){
		System.out.println("hello from java");
	}
	
	//C调用java中的带两个int参数的方法
	public int Add(int x,int y){
		int result = x+y;
		System.out.println("java result: " + result);
		return result;
	}
	
	//C调用java中参数为string的方法
	public void printString(String s){
		System.out.println("java " + s);
	}
	
	public static void printStaticStr(String s){
		System.out.println("java static " + s);
	}
	
	
	//让c代码调用对应的java代码
	public native void callmethod1();
	public native void callmethod2();
	public native void callmethod3();
	
	//调用一个静态的c代码
	public native void callmethod4();
	
}


3、MainActivity

package com.njupt.ndk_callback;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;

public class MainActivity extends Activity {

	static{
		System.loadLibrary("Hello");
	}
	
	private DataProvider dp;
	
	//用语言是native方法和所调用的java代码不在同一个类中...它所调用的是DataProvider中的一个printString()方法..
	public native void call_dp_method1();
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		
		dp = new DataProvider();
	}
	
	public void click1(View v){
		dp.callmethod1();
	}
	
	
	public void click2(View v){
		dp.callmethod2();
	}
	
	public void click3(View v){
		dp.callmethod3();
	}
	
	
	public void click4(View v){
		dp.callmethod4();
	}
	
	public void click5(View v){
		call_dp_method1();
	}
	
	

	@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;
	}

}


4、Hello.c

#include <stdio.h>
#include <jni.h>
#include "com_njupt_ndk_callback_DataProvider.h"
#include "com_njupt_ndk_callback_MainActivity.h"

#include <android/log.h>//include  D:\android-ndk-r7b\platforms\android-8\arch-arm\usr\include\android下的log.h这个目录
#define LOG_TAG "System.out"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

JNIEXPORT void JNICALL Java_com_njupt_ndk_1callback_DataProvider_callmethod1
  (JNIEnv * env, jobject obj){

	//在c代码里面调用java代码里面的方法
		// java 反射
	    //1 . 找到java代码的 class文件
		//    jclass      (*FindClass)(JNIEnv*, const char*);
	jclass dpclazz = (*env)->FindClass(env,"com/njupt/ndk_callback/DataProvider");
	if(dpclazz == 0){
		LOGI("find class error");return ;
	}

	LOGI("find class ...");

//2 寻找class里面的方法
//   jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*)
jmethodID method1 = (*env)->GetMethodID(env,dpclazz,"helloFromJava","()V");
	if(method1 == 0){
		LOGI("find method1 error..");return ;
	}

	LOGI("find method1 ...");

//3 .调用这个方法
//    void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
(*env)->CallVoidMethod(env,obj,method1);
}

JNIEXPORT void JNICALL Java_com_njupt_ndk_1callback_DataProvider_callmethod2
  (JNIEnv * env , jobject obj){

	jclass dpclazz = (*env)->FindClass(env,"com/njupt/ndk_callback/DataProvider");
		if(dpclazz == 0){
			LOGI("find class error");return ;
		}

		LOGI("find class ...");

jmethodID method2 = (*env)->GetMethodID(env,dpclazz,"Add","(II)I");
		if(method2 == 0){
			LOGI("find method2 error..");return ;
		}

		LOGI("find method2 ...");

// 3 调用这个方法
//    jint        (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);
int result = (*env)->CallIntMethod(env,obj,method2,3,5);
		LOGI("c code Result = %d", result);

}

JNIEXPORT void JNICALL Java_com_njupt_ndk_1callback_DataProvider_callmethod3
  (JNIEnv * env, jobject obj){
	jclass dpclazz = (*env)->FindClass(env,"com/njupt/ndk_callback/DataProvider");
			if(dpclazz == 0){
				LOGI("find class error");return ;
			}

			LOGI("find class ...");

jmethodID method3 = (*env)->GetMethodID(env,dpclazz,"printString","(Ljava/lang/String;)V");
			if(method3 == 0){
				LOGI("find method3 error..");return ;
			}

			LOGI("find method3 ...");

(*env)->CallVoidMethod(env,obj,method3,(*env)->NewStringUTF(env,"hello in c"));
}

JNIEXPORT void JNICALL Java_com_njupt_ndk_1callback_DataProvider_callmethod4
  (JNIEnv * env, jobject obj){

	jclass dpclazz = (*env)->FindClass(env,"com/njupt/ndk_callback/DataProvider");
				if(dpclazz == 0){
					LOGI("find class error");return ;
				}

				LOGI("find class ...");

//2 寻找class里面的方法
//   jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
// 注意 :如果要寻找的方法是静态的方法 那就不能直接去获取methodid
//jmethodID method4 = (*env)->GetMethodID(env,dpclazz,"printStaticStr","(Ljava/lang/String;)V");
//    jmethodID   (*GetStaticMethodID)(JNIEnv*, jclass, const char*, const char*);
jmethodID method4 = (*env)->GetStaticMethodID(env,dpclazz,"printStaticStr","(Ljava/lang/String;)V");
				if(method4 == 0){
					LOGI("find method4 error..");return ;
				}

				LOGI("find method4 ...");

//3.调用一个静态的java方法
//    void        (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...);
(*env)->CallStaticVoidMethod(env,dpclazz,method4,(*env)->NewStringUTF(env,"static haha in c"));
}

JNIEXPORT void JNICALL Java_com_njupt_ndk_1callback_MainActivity_call_1dp_1method1
(JNIEnv * env, jobject obj) {

jclass dpclazz = (*env)->FindClass(env,"com/njupt/ndk_callback/DataProvider");
if(dpclazz == 0) {
	LOGI("find class error");
	return;
}

LOGI("find class ...");

jmethodID method5 = (*env)->GetStaticMethodID(env,dpclazz,"printString","(Ljava/lang/String;)V");
if(method5 == 0) {
	LOGI("find method5 error..");
	return;
}

LOGI("find method5 ...");

//3 .调用这个方法(用于解决native方法和所调用的java代码不在同一个类中的情况..)
//    void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
//    jobject     (*NewObject)(JNIEnv*, jclass, jmethodID, ...);
//  jobject     (*AllocObject)(JNIEnv*, jclass);
jobject dpobject = (*env)->AllocObject(env,dpclazz);
(*env)->CallStaticVoidMethod(env,dpobject,method5,(*env)->NewStringUTF(env,"not int a class ,static hello jni"));
}


5、Android.mk

 LOCAL_PATH := $(call my-dir)

   include $(CLEAR_VARS)

   LOCAL_MODULE    := Hello   
   LOCAL_SRC_FILES := Hello.c
   LOCAL_LDLIBS += -llog
   
   include $(BUILD_SHARED_LIBRARY)

------------------------------------------------------以下介绍在这个过程中需要用到的命令-------------------------------

1、javah命令

用于生成.h文件。

使用场景:cmd下进入到src目录后 javah  包名+类名


2、javap命令

用于生成某一个类中的所有方法的方法签名

使用场景:cmd下进入到bin/classes目录后javap  包名+类名


3、ndk-build命令

用于生成.so文件

使用场景:在cygwin下进入到工程目录后,直接输入ndk-build




版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Android NDK开发(五)——C代码回调Java代码

在上篇博客里了解了Java层是怎样传递数据到C层代码,并且熟悉了大部分的实际开发知识,基本上掌握这些就可以做一个基本的NDK开发了,但是光是了解Java回调C层的数据是不是还不够啊,考虑问题要考虑可逆...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

NDK数组操作-在C中直接操作java的数组

/** * jni对数组运算 * 在C中没有创建新的数组副本,直接在原来的java数组上面修改。然后返回了jintArray类型数据 */ JNIEXPORT jintArray JNICALL...
  • JQ_AK47
  • JQ_AK47
  • 2016年12月01日 23:11
  • 351

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

Android NDK c调用java代码

一、首先是几个重要的方法: //全局的变量,用来记录java中的类/对象/方法ID jclass m_class; jobject m_object; jmethodID m_mid_static,m...

Android NDK学习记录(二):C/C++调用Java代码

Android NDK学习记录 C/C++调用Java代码 undefined reference to `_JNI_CreateJavaVM’ cannot find -ljvm...

NDK开发so层与java代码相互调用

  • 2017年06月14日 21:36
  • 32.15MB
  • 下载

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

1  案例场景,通过C语言回调Java的代码,案例的最终界面:2  案例的代码结构如下:3 编写DataProvider的代码: package com.example.ndkcallba...

NDK探究之旅《十一》—C代码调用Java代码之项目实战

C代码调用Java代码步骤及其注意事项今天我们来探究一下C语言是如何调用Java代码的我们先来看一下Java代码是如何调用C代码的那C代码是如何调用Java代码的呢?C调用Java中的方法 其实就...

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

本文不涉及android-ndk开发环境搭。步骤一:新建一个APP,名称为HelloJNI,然后定义一个类(将会在native代码中调用和访问该类):/* * mynative.cpp * * ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:ndk开发中,在c中调用java代码
举报原因:
原因补充:

(最多只允许输入30个字)