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
  1. public class Device {  
  2.      static {  
  3.             System.loadLibrary("device");  
  4.         }  
  5.      public native String deviceTestString(String test);  
  6. }  
方法名必须使用native关键字声明,并且必须使用system.loadLibrary("SO文件名")承载c类库;

第三部:

编写C文件(devices.c)

这里编写的c代码属于linux C范畴.

[cpp]  view plain copy
  1. #include   
  2. #include   
  3.   
  4. char* jstringTostrM(JNIEnv* env, jstring jstr)  
  5. {         
  6.     char* pStr = NULL;  
  7.   
  8.     jclass     jstrObj   = (*env)->FindClass(env, "java/lang/String");  
  9.     jstring    encode    = (*env)->NewStringUTF(env, "utf-8");  
  10.     jmethodID  methodId  = (*env)->GetMethodID(env, jstrObj, "getBytes""(Ljava/lang/String;)[B");  
  11.     jbyteArray byteArray = (jbyteArray)(*env)->CallObjectMethod(env, jstr, methodId, encode);  
  12.     jsize      strLen    = (*env)->GetArrayLength(env, byteArray);  
  13.     jbyte      *jBuf     = (*env)->GetByteArrayElements(env, byteArray, JNI_FALSE);  
  14.   
  15.     if (jBuf > 0)  
  16.     {  
  17.         pStr = (char*)malloc(strLen + 1);  
  18.   
  19.         if (!pStr)  
  20.         {  
  21.             return NULL;  
  22.         }  
  23.   
  24.         memcpy(pStr, jBuf, strLen);  
  25.   
  26.         pStr[strLen] = 0;  
  27.     }  
  28.   
  29.     (*env)->ReleaseByteArrayElements(env, byteArray, jBuf, 0);  
  30.   
  31.     return pStr;  
  32. }  
  33. jstring Java_com_jack_Device_deviceTestString(JNIEnv* env,jclass clazz,jstring path){  
  34.     //system("echo devices.so test > /sdcard/log/log.txt");  
  35.     char * test = jstringTostrM(env,path);  
  36.     return (*env)->NewStringUTF(env, test);  
  37. }  

注意:C的函数命名规则:Java是jni标准必须有,com_jack_Device是Device.java文件的全名,再下来才是C函数名

jstringTostrM函数必须写在Java_com_jack_Device_deviceTestString函数前,如果不是必须要C文件开头进行声明.

声明代码:

[cpp]  view plain copy
  1. char* jstringTostrM(JNIEnv* env, jstring jstr);  
第四步:编写Android.mk和编译

android.mk文件如下:

[plain]  view plain copy
  1. LOCAL_PATH := $(call my-dir)  
  2.   
  3. include $(CLEAR_VARS)  
  4.   
  5. LOCAL_MODULE    := device  
  6. LOCAL_SRC_FILES := device.c  
  7.   
  8. include $(BUILD_SHARED_LIBRARY)  
如果要编译成可执行文件 [plain]  view plain copy
  1. include $(BUILD_EXECUTABLE)  

编译:


第五步:编写java代码进行C函数调用:

[java]  view plain copy
  1. Device device = new Device();  
  2.        String test = device.deviceTestString("你好~!!!");  
  3.        Toast toast = Toast.makeText(Jack_ndk_jstringActivity.this, test, Toast.LENGTH_LONG);  
  4.        toast.setGravity(Gravity.TOP,0,150);  
  5.        toast.show();  
  6.        TextView text = (TextView) findViewById(R.id.text1);  
  7.        text.setText(test);  
注意:最好在AndroidManifest.xml文件中加入文件控制控制权限.

[html]  view plain copy
  1.     
  2. <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>  
  3. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  

更多相关文章

  1. 一款常用的 Squid 日志分析工具
  2. GitHub 标星 8K+!一款开源替代 ls 的工具你值得拥有!
  3. RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
  4. Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
  5. Android项目如果要将自己写的类写成要单独打成jar包?
  6. Android(安卓)JNI作用及其详解
  7. 修改Android中hosts文件的步骤详解
  8. Android获取手机中外置内存卡、内置内存卡、手机内存路径
  9. [Android(安卓)API学习]AppWidget

随机推荐

  1. Android:让手机成为你的移动生活助手
  2. Android api 22升级到api28 遇到的问题汇
  3. Android中的进程简介(可见进程,前台进程,后
  4. Handler Message 消息机制和AsyncTask异
  5. Android Studio多个用户界面的程序设计(一
  6. 还在羡慕微信/微博的图片处理?-android酷炫
  7. Android安全警告:新Android短信木马:Droid
  8. Android Bitmap 缓存策略
  9. Android耗电优化
  10. android listView的开启滑块及最小页数解