关于 android 的JNI的java 调用 C和 C 调用JAVA(2)
2014-09-22 15:01
501 查看
本文主要讲两个实例一个是java调用native 函数的JNI。另一个是JNI调用java中的函数即java反调用
首先建立好android app端的java的全部代码
MainActivity:
private native String GetReply(); 可知这是一个本地函数。具体实现在jni中。
private native void callJNIString(String s);也是一个本地函数。不过这个函数在jni实现过程中会调用我们java端的callbackString();
strings.xml
main.xml
因为我是直接搭建的android 系统源码的编译环境所以我没有使用ndk工具。
进入到我们工程工作文件夹下的bin文件夹的class文件夹。拷贝到Ubuntu随便一个目录下面。我的是在home下。
这是我 class内文件
接着命令 javah org.tonny.jni.jnitest.MainActivity
在class下生成两个文件 org_tonny_jni_jnitest_MainActivity.h和org_tonny_jni_jnitest_MainActivity_ClickListener.h 其中org_tonny_jni_jnitest_MainActivity.h是我们想要的。
使我们的jni的头文件。
我是在android源码目录下的 hardware/jni文件夹。然后将org_tonny_jni_jnitest_MainActivity.h拷贝到文件夹下。然后新建 org_tonny_jni_jnitest_MainActivity.c
其中org_tonny_jni_jnitest_MainActivity.h内容:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_tonny_jni_jnitest_MainActivity */
#ifndef _Included_org_tonny_jni_jnitest_MainActivity
#define _Included_org_tonny_jni_jnitest_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_tonny_jni_jnitest_MainActivity
* Method: GetReply
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_tonny_jni_jnitest_MainActivity_GetReply
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
org_tonny_jni_jnitest_MainActivity.c
#include<jni.h>
#include<string.h>
#include <android/log.h>
#include"org_tonny_jni_jnitest_MainActivity.h"
//#define ALOGE printf
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))
JNIEXPORT jstring JNICALL Java_org_tonny_jni_jnitest_MainActivity_GetReply
(JNIEnv *env, jobject obj){
return(*env)->NewStringUTF(env,(char*)"Hello,JNITest");
}
JNIEXPORT void JNICALL Java_org_tonny_jni_jnitest_MainActivity_callJNIString
( JNIEnv* env, jobject obj , jstring s)
{
jclass cls = (*env)->FindClass(env, "org/tonny/jni/jnitest/MainActivity");
jmethodID mid = (*env)->GetMethodID(env, cls, "callbackString", "(Ljava/lang/String;)V");
if (mid == NULL)
{
LOGE("string error");
return;
}
const char *ch;
ch = (*env)->GetStringUTFChars(env, s, NULL);
LOGE("from java string: %s",ch);
(*env)->ReleaseStringUTFChars(env, s, ch);
(*env)->CallVoidMethod(env, obj, mid ,(*env)->NewStringUTF(env,"你好haha"));
}
可以看到
GetReply()真正的实现就是上面这个函数。只是返回一个hello
JNIEXPORT void JNICALL Java_org_tonny_jni_jnitest_MainActivity_callJNIString函数中首先
jclass cls = (*env)->FindClass(env, "org/tonny/jni/jnitest/MainActivity");找到java的mainactivity类在jni的实例,因为我们我们要调用callbackstring函数。只有先找到这个函数属于哪个类才能找到这个函数。
jmethodID mid = (*env)->GetMethodID(env, cls, "callbackString", "(Ljava/lang/String;)V");找到这个函数的 jmethodID。
(*env)->CallVoidMethod(env, obj, mid ,(*env)->NewStringUTF(env,"你好haha"));执行java端的callbackstring函数。
到这里主要代码已经完成。我们还需要简历一个mk文件
Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= libJNITest
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_SRC_FILES:= \
org_tonny_jni_jnitest_MainActivity.c
LOCAL_SHARED_LIBRARIES := \
libcutils libhardware libc
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw这是我们生成文件输出目录
这是我jni文件夹下的文件
Android.mk org_tonny_jni_jnitest_MainActivity.c org_tonny_jni_jnitest_MainActivity.h
若是你已经source和lunch过你的环境变量你可以直接mm编译我们这个jni文件。没有的话进入android源码根目录。执行下面两个命令后再回到jni目录
. build/envsetup.sh
lunch 14 这个lunch后数字跟你的编译rom有关不重要。你可以随便选一个你。
执行mm后发现生成的在out/target/product/g18ref/system/lib/hw/下。
在我们app的libs下新建armeabi文件夹然后将libJNITest.so拷贝进去
这样生成的apk就包含我们这个so文件。
打开我们的app
界面如图所示。
点击show按钮 对话框显示Hello,JNITest
点击下面按钮显示你好haha
跟我们预想一样。。。。
首先建立好android app端的java的全部代码
MainActivity:
package org.tonny.jni.jnitest; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.app.Activity; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; public class MainActivity extends Activity { static{ System.loadLibrary("JNITest"); } private native String GetReply(); private native void callJNIString(String s); private EditText edtName; private Button btnShow; private Button stringButton = null; private TextView stringTextView = null; String reply; private Handler mHandler = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); reply= GetReply(); Log.d("jnitest","========================"); edtName= (EditText)this.findViewById(R.id.ed_name); stringTextView = (TextView)this.findViewById(R.id.stringtextview); btnShow= (Button)this.findViewById(R.id.btn_show); btnShow.setOnClickListener(new ClickListener()); stringButton = (Button)this.findViewById(R.id.stringbutton); Log.e("jnitest","oooooooooooooooo"); stringButton.setOnClickListener(new ClickListener()); mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch(msg.what) { //整型 case 0: { edtName.setText(reply); break; } //字符串 case 1: { Log.d("jnitest","pptv======="); stringTextView.setText(msg.obj.toString()); break; } } } }; /* btnShow.setOnClickListener(new OnClickListener() { public void onClick(View arg0) { edtName.setText(reply); } }); */ } public class ClickListener implements View.OnClickListener { @Override public void onClick(View v) { // TODO Auto-generated method stub switch(v.getId()) { case R.id.stringbutton: { //调用JNI中的函数 Log.e("jnitest","======---------"); callJNIString("你好A"); break; } case R.id.btn_show: { //调用JNI中的函数 Log.e("jnitest","babdbdbdbdbdbdb b"); edtName.setText(reply); Log.e("jnitest","babdbdbdbdbdbdb b"); break; } } } } private void callbackString(String s) { Message msg = new Message(); //消息类型 msg.what = 1; //消息内容 msg.obj = s; //发送消息 mHandler.sendMessage(msg); } }
private native String GetReply(); 可知这是一个本地函数。具体实现在jni中。
private native void callJNIString(String s);也是一个本地函数。不过这个函数在jni实现过程中会调用我们java端的callbackString();
strings.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">JNITest</string> <string name="action_settings">Settings</string> <string name="hello_world">HelloWorld, JNITestActivity!</string> <string name="btn_show">Show</string> <string name="recvstr">接收到的整数</string> <string name="btnstr">传给JNI一个字符A</string> </resources>
main.xml
<LinearLayout 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" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> <EditText android:id="@+id/ed_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginLeft="5dp" android:inputType="text" android:layout_marginRight="5dp"/> <Button android:id="@+id/btn_show" android:layout_width="109dp" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="@string/btn_show"/> <TextView android:id="@+id/stringtextview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/recvstr" /> <Button android:id="@+id/stringbutton" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/btnstr"/> </LinearLayout>
因为我是直接搭建的android 系统源码的编译环境所以我没有使用ndk工具。
进入到我们工程工作文件夹下的bin文件夹的class文件夹。拷贝到Ubuntu随便一个目录下面。我的是在home下。
这是我 class内文件
接着命令 javah org.tonny.jni.jnitest.MainActivity
在class下生成两个文件 org_tonny_jni_jnitest_MainActivity.h和org_tonny_jni_jnitest_MainActivity_ClickListener.h 其中org_tonny_jni_jnitest_MainActivity.h是我们想要的。
使我们的jni的头文件。
我是在android源码目录下的 hardware/jni文件夹。然后将org_tonny_jni_jnitest_MainActivity.h拷贝到文件夹下。然后新建 org_tonny_jni_jnitest_MainActivity.c
其中org_tonny_jni_jnitest_MainActivity.h内容:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_tonny_jni_jnitest_MainActivity */
#ifndef _Included_org_tonny_jni_jnitest_MainActivity
#define _Included_org_tonny_jni_jnitest_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_tonny_jni_jnitest_MainActivity
* Method: GetReply
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_tonny_jni_jnitest_MainActivity_GetReply
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
org_tonny_jni_jnitest_MainActivity.c
#include<jni.h>
#include<string.h>
#include <android/log.h>
#include"org_tonny_jni_jnitest_MainActivity.h"
//#define ALOGE printf
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))
JNIEXPORT jstring JNICALL Java_org_tonny_jni_jnitest_MainActivity_GetReply
(JNIEnv *env, jobject obj){
return(*env)->NewStringUTF(env,(char*)"Hello,JNITest");
}
JNIEXPORT void JNICALL Java_org_tonny_jni_jnitest_MainActivity_callJNIString
( JNIEnv* env, jobject obj , jstring s)
{
jclass cls = (*env)->FindClass(env, "org/tonny/jni/jnitest/MainActivity");
jmethodID mid = (*env)->GetMethodID(env, cls, "callbackString", "(Ljava/lang/String;)V");
if (mid == NULL)
{
LOGE("string error");
return;
}
const char *ch;
ch = (*env)->GetStringUTFChars(env, s, NULL);
LOGE("from java string: %s",ch);
(*env)->ReleaseStringUTFChars(env, s, ch);
(*env)->CallVoidMethod(env, obj, mid ,(*env)->NewStringUTF(env,"你好haha"));
}
可以看到
JNIEXPORT jstring JNICALL Java_org_tonny_jni_jnitest_MainActivity_GetReply
GetReply()真正的实现就是上面这个函数。只是返回一个hello
JNIEXPORT void JNICALL Java_org_tonny_jni_jnitest_MainActivity_callJNIString函数中首先
jclass cls = (*env)->FindClass(env, "org/tonny/jni/jnitest/MainActivity");找到java的mainactivity类在jni的实例,因为我们我们要调用callbackstring函数。只有先找到这个函数属于哪个类才能找到这个函数。
jmethodID mid = (*env)->GetMethodID(env, cls, "callbackString", "(Ljava/lang/String;)V");找到这个函数的 jmethodID。
(*env)->CallVoidMethod(env, obj, mid ,(*env)->NewStringUTF(env,"你好haha"));执行java端的callbackstring函数。
到这里主要代码已经完成。我们还需要简历一个mk文件
Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= libJNITest
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_SRC_FILES:= \
org_tonny_jni_jnitest_MainActivity.c
LOCAL_SHARED_LIBRARIES := \
libcutils libhardware libc
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw这是我们生成文件输出目录
这是我jni文件夹下的文件
Android.mk org_tonny_jni_jnitest_MainActivity.c org_tonny_jni_jnitest_MainActivity.h
若是你已经source和lunch过你的环境变量你可以直接mm编译我们这个jni文件。没有的话进入android源码根目录。执行下面两个命令后再回到jni目录
. build/envsetup.sh
lunch 14 这个lunch后数字跟你的编译rom有关不重要。你可以随便选一个你。
执行mm后发现生成的在out/target/product/g18ref/system/lib/hw/下。
在我们app的libs下新建armeabi文件夹然后将libJNITest.so拷贝进去
这样生成的apk就包含我们这个so文件。
打开我们的app
界面如图所示。
点击show按钮 对话框显示Hello,JNITest
点击下面按钮显示你好haha
跟我们预想一样。。。。
相关文章推荐
- android中关于jni调用java层方法的一些误导和见解
- 关于Android调用JNI出现的 java.lang.UnsatisfiedLinkError
- 关于 android 的JNI的java 调用 C和 C 调用JAVA(1)
- Android调用jni时出现java.lang.UnsatisfiedLinkError
- Android 基于NDK的JNI开发 C调用java和java调用C的进阶教程
- 【iOS-cocos2d-X 游戏开发之十三】cocos2dx通过Jni调用Android的Java层代码(上)
- 【学习Android NDK开发】Java通过JNI调用native方法
- 转战Android之NDK(jni, c/c++调用java)
- 关于JNI的使用(实战linux平台下java调用本地c语言方法)
- Android-NDK开发之基础--Android JNI实例代码(一)-- 在JNI中执行Java方法--C/C++调用Java
- 【iOS-cocos2d-X 游戏开发之十三】cocos2dx通过Jni调用Android的Java层代码(下)
- 关于java用jni调用 dll动态库Can't find dependent libraries错误的解决
- android-JNI学习之java和c++相互调用
- Android下用JNI让Java调用C函数
- AndroidJNI 通过C++调用JAVA
- Android-NDK开发之基础--Android JNI实例代码(一)-- 在JNI中执行Java方法--C/C++调用Java
- Android调用jni时出现java.lang.UnsatisfiedLinkError
- Android-NDK开发之基础--Android JNI实例代码(一)-- 在JNI中执行Java方法--C/C++调用Java
- 关于Android 添加系统级(java)服务和调用的编写实现说明
- Android JNI 使用的数据结构JNINativeMethod详解 ||建立Android SDK下的JNI、JAVA应用完整步骤---Android JAVA调用C++代码