在Android 系统中直接调用 SO 文件

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
图1
Java 编写接口文件(Device.java) Device.java 的代码实现如下:
public class Device { static { System.loadLibrary("device"); } public native String deviceTestString(String test);
if (!pStr)
{
return NULL;
}
memcpy(pStr, jBuf, strLen);
pStr[strLen] = 0;
}
(*env)->ReleaseByteArrayElements(env, byteArray, jBuf, 0);
return pStr;
}
jstring Java_com_jack_Device_deviceTestString(JNIEnv* env,jclass clazz,jstring path){
注意,最后在 AndroidManifest.xml 文件中要加入文件控制权限,代码如下:
<!-- 文件权限 --> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
jmethodID methodId = (*env)->GetMethodID(env, jstrObj, "getBytes",
"(Ljava/lang/String;)[B");
jbyteArray byteArray = (jbyteArray)(*env)->CallObjectMethod(env, jstr, methodId,
//system("echo devices.so test > /sdcard/log/log.txt"); char * test = jstringTostrM(env,path); return (*env)->NewStringUTF(env, test); }
注意 C 的函数命名规则,Java 的 jni 标准必须有,com_jack_Device 是 Device.java 文件的 全 名 , 再 下 来 才 是 C 函 数 名 , jstringTostrM 函 数 必 须 写 在 Java_com_jack_Device_deviceTestString 函数前,如果不是,必须要在 C 文件头进行声明,声 明代码为:
encode);
jsize
strLen = (*env)->GetArrayLength(env, byteArray);
jbyte
*jBuf = (*env)->GetByteArrayElements(env, byteArray, JNI_FALSE);
if (jBuf > 0)
{
pStr = (char*)malloc(strLen + 1);
}
方法名必须使用 native 关键字声明,并且必须使用 system.loadLibrary("SO 文件名")承载 C 类库。
编写 C 文件(devices.c) 这里编写的 C 代码属于 Linux C 范畴,实现代码如下:
#include <string.执行文件,还需包含代码 include $(BUILD_EXECUTABLE),之后按照图 2 所示编译即可。
图2
编写 Java 代码进行 C 函数调用
Device device = new Device(); String test = device.deviceTestString("你好~!!!"); Toast toast = Toast.makeText(Jack_ndk_jstringActivity.this, test, Toast.LENGTH_LONG); toast.setGravity(Gravity.TOP,0,150); toast.show(); TextView text = (TextView) findViewById(R.id.text1); text.setText(test);
char* jstringTostrM(JNIEnv* env, jstring jstr);
编写 Android.mk 和编译 android.mk Android.mk 的代码如下:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := device LOCAL_SRC_FILES := device.c include $(BUILD_SHARED_LIBRARY)
在在android系统系统中中直接直接调用调用so文件文件文图mangel用c语言或c编写完成利用ndk进行编译直接运行在linux内核中按jni调用so时基本类型可以直接交互
在 Android 系统中直接调用 SO 文件
文/图 mangel Android 虚拟机不能直接调用底层设备,如果要对底层设备进行调用,就需要用到 so 使 用 C 语言或 C++编写完成,利用 NDK 进行编译,直接运行在 Linux 内核中,按 jni 调用 so 时, 基本类型可以直接交互。 在 apk 里打包进.so 文件的方法有两种,一 是在 Android.mk 文件里增加 “LOCAL_JNI_SHARED_LIBRARIES := libxxx”,这样在编译的时候,NDK 自动会把这个 libxxx 打 包进 apk,放在 xxx/lib/目录下;二是在应用的目录下手工建 libs/armeabi 目录,然后把 libxxx.so 拷贝到这个目录下,NDK 也会自动把这个 libxxx.so 打包进 apk,位置还是在 xxx/lib/目录下。 在代码里,使用 System.loadLibrary("xxx");就可以加载这个动态库了。这里要注意,参数 只写 xxx 就可以了,不需要写 libxxx,也不需要写 libxxx.so。 还有一点要说明,System.loadLibrary 这个函数会在如下路径搜索 libxxx.so 文件: /system/lib /data/data/xxx apk package/lib 如果 libxxx.so 还依赖其它.so 文件,比如 libyyy.so,则 System.loadLibrary 只会在/system/lib 目录下查找,如果没找到,不会自动到/data/data/xxx apk package/lib 下去找,这个时候就会 报动态库没找到的错误。解决方法是在 load libxxx.so 之前,先 load libyyy.so,具体如下: System.loadLibrary("yyy"); System.loadLibrary("xxx"); 本文结合使用实例进行说明。 创建 jni 目录.libs 目录 在工程根目录下创建 jni 目录,libs 目录不用手动建立,如图 1 所示。注意,这里使用 的是 ndk_R7,所以不需要用 jdk 去生成 C 文件。
char* jstringTostrM(JNIEnv* env, jstring jstr)
{
char* pStr = NULL;
jclass jstrObj = (*env)->FindClass(env, "java/lang/String");
jstring encode = (*env)->NewStringUTF(env, "utf-8");
相关文档
最新文档