Android(安卓)调用.so文件 jni
16lz
2021-01-25
android调用so
android虚拟机不能直接调用底层设备,我们如果要对底层设备进行调用就需要用到so.
so使用C语言或C++编写完成,使用ndk进行编译,直接运行在linux内核中.
按jni调用so时基本类型可以直接交互,jstring使用时有点麻烦,所以我做一个jstring和char*进行转换的例子.
第一步:
工程根目录下创建jni目录.libs目录不用手动建立.
注意:这里使用ndk_R7所以不需要用jdk去生成C文件头.
第二部:
java编写接口文件(Device.java)
[java] view plain copy
- public class Device {
- static {
- System.loadLibrary("device");
- }
- public native String deviceTestString(String test);
- }
第三部:
编写C文件(devices.c)
这里编写的c代码属于linux C范畴.
[cpp] view plain copy
- #include
- #include
- char* jstringTostrM(JNIEnv* env, jstring jstr)
- {
- char* pStr = NULL;
- jclass jstrObj = (*env)->FindClass(env, "java/lang/String");
- jstring encode = (*env)->NewStringUTF(env, "utf-8");
- jmethodID methodId = (*env)->GetMethodID(env, jstrObj, "getBytes", "(Ljava/lang/String;)[B");
- jbyteArray byteArray = (jbyteArray)(*env)->CallObjectMethod(env, jstr, methodId, encode);
- jsize strLen = (*env)->GetArrayLength(env, byteArray);
- jbyte *jBuf = (*env)->GetByteArrayElements(env, byteArray, JNI_FALSE);
- if (jBuf > 0)
- {
- pStr = (char*)malloc(strLen + 1);
- 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){
- //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文件开头进行声明.
声明代码:
[cpp] view plain copy
- char* jstringTostrM(JNIEnv* env, jstring jstr);
android.mk文件如下:
[plain] view plain copy
- LOCAL_PATH := $(call my-dir)
- include $(CLEAR_VARS)
- LOCAL_MODULE := device
- LOCAL_SRC_FILES := device.c
- include $(BUILD_SHARED_LIBRARY)
- include $(BUILD_EXECUTABLE)
编译:
第五步:编写java代码进行C函数调用:
[java] view plain copy
- 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);
[html] view plain copy
- <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
更多相关文章
- 一款常用的 Squid 日志分析工具
- GitHub 标星 8K+!一款开源替代 ls 的工具你值得拥有!
- RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
- Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
- Android项目如果要将自己写的类写成要单独打成jar包?
- Android(安卓)JNI作用及其详解
- 修改Android中hosts文件的步骤详解
- Android获取手机中外置内存卡、内置内存卡、手机内存路径
- [Android(安卓)API学习]AppWidget