android调试+及JNI相关
来源:互联网 发布:淘宝店铺客服链接获取 编辑:程序博客网 时间:2024/05/18 02:36
./adb remount //使得文件系统可读写
./adb push 8188eu.ko /system/lib/modules 传输文件
调试真机:
需要知道usb的厂商和产品ID,然后添加udev规则(否则,linux中可能识别不到真机的USB)。可以利用lsusb查看VID
- SUBSYSTEM=="usb", SYSFS{idVendor}=="04e8", MODE="0666"
- /etc/udev/rules.d/53-android.rules
1.1 查看设备(包括模拟设备和真实设备)
- adb devices
1.2 进入目标板的shell
- adb shell
如果存在多个设备,需要以下命令
- adb shell -s + 设备名
进入shell之后,可以使用dmesg查看内核打印信息。
这点在权限遇到问题时非常有用,内核打印可以直接看到gid和uid的问题。(笔者对内核底层比较熟悉,目前不清楚JAVA层会有什么相关提示)。例如:
- qtaguid: ctrl_counterset(s 1 10106): insufficient priv from pid=3318 tgid=3260 uid=1000
- <6>[16058.466766] qtaguid: ctrl_counterset(s 0 10085): insufficient priv from pid=3318 tgid=3260 uid=1000
2.Android Studio 调试
笔者使用的2.1.2,集成的编译环调试相当方便。
在Monitor中集成了logcat,而且直接过滤出调试app的LOG。
3.JNI相关配置
3.1 下载NDK
建议直接下载,然后在Android Studio中直接配置。
配置的方式为:在local.properties中添加NDK的路径
- ndk.dir=D\:\\Android\\android-sdk\\android-ndk-r11c-windows-x86_64\\android-ndk-r11c
3.2 build.gradle的defaultConfig配置添加
- ndk{
- moduleName "YanboberJniLibName"
- ldLibs "log", "z", "m"
- abiFilters "armeabi", "armeabi-v7a", "x86"
- }
moduleName是库文件的名字(不含.so或dll后缀)
jni的目录结构:
3.3 JNI接口的声明和定义
3.3.1 C 中的声明
- #ifdef __cplusplus
- extern "C" {
- #endif
- JNIEXPORT jboolean JNICALL native_sudo(JNIEnv *env, jobject obj, jstring xmd);
- JNIEXPORT jboolean JNICALL native_exit(JNIEnv *env, jobject obj);
- #ifdef __cplusplus
- }
- #endif
JNIEnv 从linux的本质上来讲是本地线程的环境,JNIEnv只在当前线程中有效。指针不能从一个线程进入另一个线程,但可以在不同的线程中调用本地方法(这时,所传递的env是不同的)
总结下:JNIEnv是与线程相关的变量,不同线程的JNIEnv彼此独立。而JavaVM是虚拟机的JNI层的代表,在虚拟机进程中只有一个JavaVM,所以该进程的所有线程都可以使用这个JavaVM。
简单来讲,就是库函数的作用,具有良好可重载性。上一张图片就简单明了了:
3.3.2 使用JNINativeMethod注册到线程环境
JNINativeMethod定义如下:
- static JNINativeMethod methods[] = {
- {"sudo","(Ljava/lang/String;)Z",(void*)native_sudo},
- {"nexit","()Z",(void*)native_exit},
- };
native_sudo是jni层定义的函数。
sudo是JAVA层调用的函数。
(Ljava/lang/String;)Z是函数传递参数和返回参数,多个参数使用";"进行分割。括号里的是形参,括号外的是返回值
这里的参数表示,后续作下补充。
注:该结构体,第二个参数的分号漏掉,会导致无法找到JNI函数。
注册的过程直接上代码了,这里可以直接套用:
- static int registerNativeMethods(JNIEnv* env , const char* className , JNINativeMethod* gMethods, int numMethods)
- {
- jclass clazz;
- clazz = (*env)->FindClass(env, className);
- if (clazz == NULL)
- {
- return JNI_FALSE;
- }
- if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0)
- {
- return JNI_FALSE;
- }
- return JNI_TRUE;
- }
- //自定义函数
- static int registerNatives(JNIEnv* env)
- {
- const char* kClassName = "io/github/yanbober/ndkapplication/NdkJniUtils";//指定要注册的类
- return registerNativeMethods(env, kClassName, methods, sizeof(methods) / sizeof(methods[0]));
- }
- JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
- {
- LOGD("customer---------------------------JNI_OnLoad-----into.\n");
- JNIEnv* env = NULL;
- jint result = -1;
- //test();
- if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK)
- {
- return -1;
- }
- assert(env != NULL);
- if (!registerNatives(env))
- {
- return -1;
- }
- return JNI_VERSION_1_4;
- }
3.3.3 JAVA层的定义
- public class NdkJniUtils {
- public native boolean sudo(String cmd);
- public native boolean nexit();
- static {
- System.loadLibrary("YanboberJniLibName");
- }
- }
这里使用了类封装。使用时,New一个NdkJniUtils即可调用JNI函数。
函数使用native声明之后,JAVA链接器会认为这个函数时外部函数,因此没有在JNI层作相关定义,JAVA项目工程也是可以编译通过的。
注:loadLibrary需要与之前build.gradle 中ndk字段声明的名字相同。
3.3.4 不使用JNINativeMethod的方法
不使用JNINativeMethod的方法时,函数名定义的名称必须按照规定的格式,相对比较复杂。个人并不喜欢这样定义。
以前作的笔记,直接copy了(需要使用javah工具):
确认javah生成头文件的工具能否使用。如果不能,需要确认环境变量。
使用方法:
在声明好native函数之后,进行build。
然后以build好的class,利用javah生成头文件,格式如下
- javah -d [dest dir] -classpath [debug dir] [class name]
-d: 头文件存放的目录。个人选择main下的目录(\helloworld\app\src\main\java),最好创建新目录,用于存放native定义(如jni目录),这样可以在项目路径上看到。
-classpath : 类存放的路径;(\helloworld\app\build\intermediates\classes\debug)
[classname]:及之前声明了native函数的类
当然如果感觉比较麻烦,在debug目录使用相对路径创建.h文件,然后将文件复制到main目录。
然后,在-d的目录下创建.c文件,对native函数作具体的定义。
- android调试+及JNI相关
- android eclipse 程序调试及相关快捷键
- Android 上调试 webkit framework 层及jni层
- android jni 调试
- Android的JNI调试
- Android JNI 调试
- android Jni 调试d
- JNI Android Studio 调试
- ADB简单调试技巧及Android JNI crash调试定位错误信息
- Android上JNI的调试
- Android上JNI的调试
- Android上JNI的调试
- Android上JNI的调试
- Android 远程调试 JNI 实现
- Android上JNI的调试
- Android Studio 2.2 Jni 调试
- 详细Android Studio Jni 调试
- android JNI相关的代码
- 解决vmware虚拟机策略太旧的方法
- tarjan算法--求无向图的割点和桥
- Flink广播的使用
- swift学习笔记0
- http://www.suthink.com/ 商标 世誉鑫诚 问问,免费注册
- android调试+及JNI相关
- MySQL查看表占用空间大小
- C++ 哈夫曼树(压缩、加密实现代码)
- Java实现Kafka读写笔记
- 阿里巴巴Java开发手册-编程规约
- swift学习笔记1 操作符
- android基于tcpdump的数据包捕获完整解决方案
- 原因:思维组织
- Linux命令之ln