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



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控制台打印的结果

 

 

时间: 2024-10-10 15:38:13

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

luaj lua调用java-lua中使用javaBridge调用java方法中的打印语句

问题描述 lua中使用javaBridge调用java方法中的打印语句 我用的是mac系统,ADT环境,最近在学习2dx游戏中植入百度SDK.luaj到底怎么用,有没有完整的代码.本人菜鸟,请大神指点 解决方案 不要总指望别人就给你现成的代码

javascript-Android 在webview中js怎么调用java里面的方法

问题描述 Android 在webview中js怎么调用java里面的方法 Android 在webview中js怎么调用java里面的方法 需要调用的是一个社会化分享的 解决方案 http://zhidao.baidu.com/link?url=8GQWxP5vy1Idkk3cVnU9YZpCHb4X5n37A9aeSdD3FaoPWIfXQzQ82D6nDpSJ6KBkfuqZsZ398EEcpXuIchcGiehjvrn1KqoWfVAAgNuWh2e 参考., 解决方案二: 1.布局文件

在Oracle中发布和调用Java functions

oracle 发布过程: 1.  编写.java文件 2.  成功编译.java文件,生成.class文件,此文件为导入到Oracle中的文件. 3.  (Toad工具方法导入),打开Java Manager指要导入的.class文件,执行导入. 注意,此时登录数据库要有足够的权限,可以将文件导入指定的Schema中. 导入完成后,可以在导入的schema中的java目录中找到该java类,其文件标识为J(c),即java class文件. 4.  发布文件,指定要发布的functions,内部

kettle中使用js调用java类的方法_java

1. 需要事先将jar包 放在kettle 的 libext 目录,kettle 在启动时会自动加载libext 目录下的所有 jar 包. 2. modified java script 步骤要选中 compatibility mode,并将 content 设置为输出的字段. 代码如下: 复制代码 代码如下:     var 变量 = new Packages.包名(参数 );

java 调用C语言,然后在 c中创建jvm(想在C中再调用Java)返回-1!

问题描述 java 调用C语言,然后在 c中创建jvm(想在C中再调用Java)返回-1! ,请教一个问题: 现在Java 调C 代码( C作为 .so 文件), 和C(C作为可执行程序)调用Java 代码都没问题. 但是我现在测试 Java 调用C代码时,在C中同时也 调用Java 代码出现了问题(创建JVM时 失败. 在一些场景下 需要C 主动调用Java),大家之前遇到过这类场景么? 怎么解决, 解决方案 使用JNI进行Java与C/C++语言混合编程(1)--在Java中调用C/C++本

详解安卓系统中的Android.mk文件_C 语言

概述    Android.mk文件用来向编译系统描述如何编译你的源代码.更确切地说,该文件其实就是一个小型的Makefile.由于该文件会被NDK的编译工具解析多次,因此应该尽量减少源码中声明变量,因为这些变量可能会被多次定义从而影响到后面的解析.这个文件的语法允许把源代码组织成模块,每个模块属于下列类型之一:     APK程序:一般的Android程序,编译打包生成apk文件.     JAVA库:java类库,编译打包生成jar包文件.     C\C++应用程序:可执行的C/C++应用

软件测试工具Loadrunner调用Java类

最近公司需要测试几个具有一定功能类的性能,虽然我觉得这已经是白盒测试的范畴了,但是领导要求这样做,我也就只好进行技术的研究.要求就是能够传参数给类,并且可以接收到类返回的参数,并且进行正确与否的判断. 第一步,总的思路. 以前我都是用loadrunner直接进行录制,但是有些协议的确不好弄不知道怎样进行录制,像vb,c++,java语言做的东西我觉最简单的方式就是直接调用相关的类文件,动态链接库,直接用代码的方式进行调用.在这种思想下,于是试着在loadrunner中写程序调用java类. 第二

Android NDK中socket的用法以及注意事项分析_Android

Android NDK中使用socket的整个过程分为以下几部分:第一部分: 创建socket并绑定IP和端口 复制代码 代码如下: #include <sys/select.h>#include <sys/socket.h>#include <arpa/inet.h>#define MAX_DATA_BUF_LEN 10240int sd = INVALID_SOCKET;sockaddr_in addr_org;  // 发送端地址sd = socket(AF_IN

Android NDK中socket的用法以及注意事项分析

Android NDK中使用socket的整个过程分为以下几部分: 第一部分: 创建socket并绑定IP和端口 复制代码 代码如下: #include <sys/select.h> #include <sys/socket.h> #include <arpa/inet.h> #define MAX_DATA_BUF_LEN 10240 int sd = INVALID_SOCKET; sockaddr_in addr_org;  // 发送端地址 sd = socke