在 Android 系统中直接调用 SO文件(包含System.loadLibrary加载so的路径解释)

简介: Android虚拟机不能直接调用底层设备,如果要对底层设备进行调用,就需要用到so使用 C语言或C++编写完成,利用NDK进行编译,直接运行在Linux内核中,按jni调用 so时,基本类型可以直接交互。
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 文件。 
 
 
图1 
 Java编写接口文件(Device.java) 
 Device.java的代码实现如下:
 
public class Device { 
 static { 
 System.loadLibrary("device"); 
 } 
 public native String deviceTestString(String test); 

 
 方法名必须使用native关键字声明,并且必须使用system.loadLibrary("SO文件名")承载
C 类库。 
 
 
编写C文件(devices.c) 
 这里编写的C代码属于Linux C 范畴,实现代码如下: 
 
#include <string.h> 
#include <jni.h> 
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 文件头进行声明,声
明代码为: 
 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) 
 
 如果要编译成可执行文件,还需包含代码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); 
 
 注意,最后在AndroidManifest.xml文件中要加入文件控制权限,代码如下: 
 
<!-- 文件权限 --> 
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> 
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
目录
相关文章
|
14天前
|
缓存 Java Shell
Android 系统缓存扫描与清理方法分析
Android 系统缓存从原理探索到实现。
40 15
Android 系统缓存扫描与清理方法分析
|
6天前
|
算法 JavaScript Android开发
|
8天前
|
安全 搜索推荐 Android开发
揭秘安卓与iOS系统的差异:技术深度对比
【10月更文挑战第27天】 本文深入探讨了安卓(Android)与iOS两大移动操作系统的技术特点和用户体验差异。通过对比两者的系统架构、应用生态、用户界面、安全性等方面,揭示了为何这两种系统能够在市场中各占一席之地,并为用户提供不同的选择。文章旨在为读者提供一个全面的视角,理解两种系统的优势与局限,从而更好地根据自己的需求做出选择。
23 2
|
15天前
|
Android开发 UED
Android 中加载 Gif 动画
【10月更文挑战第20天】加载 Gif 动画是 Android 开发中的一项重要技能。通过使用第三方库或自定义实现,可以方便地在应用中展示生动的 Gif 动画。在实际应用中,需要根据具体情况进行合理选择和优化,以确保用户体验和性能的平衡。可以通过不断的实践和探索,进一步掌握在 Android 中加载 Gif 动画的技巧和方法,为开发高质量的 Android 应用提供支持。
|
7天前
|
安全 搜索推荐 程序员
深入探索Android系统的碎片化问题及其解决方案
在移动操作系统的世界中,Android以其开放性和灵活性赢得了广泛的市场份额。然而,这种开放性也带来了一个众所周知的问题——系统碎片化。本文旨在探讨Android系统碎片化的现状、成因以及可能的解决方案,为开发者和用户提供一种全新的视角来理解这一现象。通过分析不同版本的Android系统分布、硬件多样性以及更新机制的影响,我们提出了一系列针对性的策略,旨在减少碎片化带来的影响,提升用户体验。
|
7天前
|
安全 Android开发 iOS开发
深入探索iOS与Android系统的差异性及优化策略
在当今数字化时代,移动操作系统的竞争尤为激烈,其中iOS和Android作为市场上的两大巨头,各自拥有庞大的用户基础和独特的技术特点。本文旨在通过对比分析iOS与Android的核心差异,探讨各自的优势与局限,并提出针对性的优化策略,以期为用户提供更优质的使用体验和为开发者提供有价值的参考。
|
9天前
|
安全 Android开发 iOS开发
安卓系统与iOS系统的比较####
【10月更文挑战第26天】 本文将深入探讨安卓(Android)和iOS这两大主流移动操作系统的各自特点、优势与不足。通过对比分析,帮助读者更好地理解两者在用户体验、应用生态、系统安全等方面的差异,从而为消费者在选择智能手机时提供参考依据。无论你是技术爱好者还是普通用户,这篇文章都将为你揭示两大系统背后的故事和技术细节。 ####
24 0
|
1天前
|
XML 存储 Java
探索安卓开发之旅:从新手到专家
【10月更文挑战第35天】在数字化时代,安卓应用的开发成为了一个热门话题。本文旨在通过浅显易懂的语言,带领初学者了解安卓开发的基础知识,同时为有一定经验的开发者提供进阶技巧。我们将一起探讨如何从零开始构建第一个安卓应用,并逐步深入到性能优化和高级功能的实现。无论你是编程新手还是希望提升技能的开发者,这篇文章都将为你提供有价值的指导和灵感。
|
1天前
|
Android开发
布谷语音软件开发:android端语音软件搭建开发教程
语音软件搭建android端语音软件开发教程!
|
9天前
|
编解码 Java Android开发
通义灵码:在安卓开发中提升工作效率的真实应用案例
本文介绍了通义灵码在安卓开发中的应用。作为一名97年的聋人开发者,我在2024年Google Gemma竞赛中获得了冠军,拿下了很多项目竞赛奖励,通义灵码成为我的得力助手。文章详细展示了如何安装通义灵码插件,并通过多个实例说明其在适配国际语言、多种分辨率、业务逻辑开发和编程语言转换等方面的应用,显著提高了开发效率和准确性。
下一篇
无影云桌面