Android中生成调用本地so文件

本文介绍如何在Android项目中使用JNI技术实现Java与C++代码交互,包括生成并编译C++源文件、创建本地方法及访问Java类成员变量的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


    新建一个android项目,同样生成native方法,然后选择项目右键->AndroidTools->Add Native Supprot…..(前提是eclipse以安装ndk,并且要是ndkr7以上版本,不然就需要cygwin模仿linux环境,r7以后ndk封装了在linux环境,在windows能够使用)



执行后目录如下,产生了一个Android.mk文件和hellojni.cppc++文件



然后使用javah生成头文件,找到菜单栏的run->External Tools->External Tools Configurations 右键单击Program->New   定义一个名称,放入jdk下的javah路径 ,在工作空间选择本项目hellojni,加上-classpathsrc -d jni com.example.hellojni.MainActivity ,运行一下:

刷新项目目录在jni文件下就生成了相应的com_example_hellojni_MainActivity.hc++头文件:



jni文件夹的hellojni.cpp中加如一行日志:



jni->android.mk中添加:LOCAL_LDLIBS := -landroid -llog



然后Ctrl+B编译一下,回到java代码,在static中加载so文件,在oncreate()方法中调用obbnclick()方法,运行一下,在控制台打印出c++代码中的日志,ok


 


现在我们做一下改变,java端:声明两个String变量,让message显示setText()中



jni->jnitest.cpp中修改一下,加入


//通过获取当前对象的jclassenv->GetObjectClass(obj))放入jfieldId中取得message对象


   jfieldID fid_msg = env->GetFieldID(env->GetObjectClass(obj),"message","Ljava/lang/String;");


   //获取messge的值


   jstring j_msg = (jstring)env->GetObjectField(obj, fid_msg);


   constjchar *jstr = env->GetStringChars(j_msg, NULL);


 


   jfieldID fid_name = env->GetFieldID(env->GetObjectClass(obj),"name","Ljava/lang/String;");


   jstring j_name = (jstring)env->GetObjectField(obj, fid_name);


   constjchar *jstr_name=env->GetStringChars(j_name,NULL);


 


   jobject j_newe_str = env->NewString(jstr_name,2);


   //设置属性的值


   env->SetObjectField(obj,fid_msg, j_newe_str);



现在在ctrl+B编译一下c++文件,然后再运行一遍android app就得到了以下结果,而不是hello


Linux下生成so文件:

新建一个类,申明相应的native的类
package com.example.test;


public class test  {
 public native void  a();
 
 static{
  System.loadLibrary("test");
 }

}
保存终端到该项目的src目录下执行   javac com/example/test/test.java
将会在/src/com/example/test下生成相应的test.class文件

采用javah命令生成相应的头文件:javah com.example.test.test,这时候包是用.分隔且方法名没有后缀
将会生成com_example_test_test.h的头文件

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_test_test */

#ifndef _Included_com_example_test_test
#define _Included_com_example_test_test
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_test_test
 * Method:    a
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_example_test_test_a
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif


然后新建一个com_example_test_test.cpp
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#include <stdio.h>
#include <com_example_test_test.h>

/* Header for class com_example_test_test */


extern "C"

/*
 * Class:     com_example_test_test
 * Method:    a
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_example_test_test_a
  (JNIEnv * env, jobject obj*{
  
    printf("HelloWorld JNI!\n");
     
   }

 

这个时候对cpp文件用gcc动态编译成相应的so文件,此时采用的是linux的openJDK,导入相应的参数-I采用绝对路径:
 gcc -shared -I /usr/lib/jvm/jdk1.6.0_45/include -I /usr/lib/jvm/jdk1.6.0_45/include/linux com_example_test_test.cpp -o libtest.so
com_example_test_test.cpp:4:35: 致命错误: com_example_test_test.h:没有那个文件或目录
执行命令后发现出现了相应的错误,是没有安装g++,所以安装g++等一些依赖的东西
sudo apt-get install build-essential

sudo apt-get install g++
然后在次执行 gcc -shared -I /usr/lib/jvm/jdk1.6.0_45/include -I /usr/lib/jvm/jdk1.6.0_45/include/linux com_example_test_test.cpp -o libtest.so
便生成了相应的libtest.so文件

然后加入编译路径,在代码中掉用a()方法


 


 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值