android 遠程調試,android調試+及JNI相關

 2023-11-30 阅读 16 评论 0

摘要:原址 1.adb的使用 ?./adb remount ?//使得文件系統可讀寫? ./adb push 8188eu.ko /system/lib/modules ?傳輸文件 調試真機: 需要知道usb的廠商和產品ID,然后添加udev規則(否則,linux中可能識別不到真機的USB)。可以利用lsusb查看VID SUB
原址

1.adb的使用

?./adb remount ?//使得文件系統可讀寫?

./adb push 8188eu.ko /system/lib/modules ?傳輸文件

調試真機:

需要知道usb的廠商和產品ID,然后添加udev規則(否則,linux中可能識別不到真機的USB)。可以利用lsusb查看VID

  1. SUBSYSTEM=="usb",?SYSFS{idVendor}=="04e8",?MODE="0666"?
  2. /etc/udev/rules.d/53-android.rules??

1.1 查看設備(包括模擬設備和真實設備)

  1. ?adb?devices?

1.2 進入目標板的shell

  1. adb?shell?

? ? 如果存在多個設備,需要以下命令?

  1. adb?shell?-s?+?設備名?

????進入shell之后,可以使用dmesg查看內核打印信息。

? ??這點在權限遇到問題時非常有用,內核打印可以直接看到gid和uid的問題。(筆者對內核底層比較熟悉,目前不清楚JAVA層會有什么相關提示)。android 遠程調試。例如:

  1. qtaguid:?ctrl_counterset(s?1?10106):?insufficient?priv?from?pid=3318?tgid=3260?uid=1000
  2. <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的路徑?

  1. ndk.dir=D\:\\Android\\android-sdk\\android-ndk-r11c-windows-x86_64\\android-ndk-r11c?

3.2 build.gradle的defaultConfig配置添加

  1. ?ndk{
  2. ????????????moduleName?"YanboberJniLibName"
  3. ????????????ldLibs?"log",?"z",?"m"
  4. ????????????abiFilters?"armeabi",?"armeabi-v7a",?"x86"
  5. ????????}

?? ? moduleName是庫文件的名字(不含.so或dll后綴)

?? ? jni的目錄結構:

3.3 JNI接口的聲明和定義

3.3.1 C 中的聲明

  1. #ifdef?__cplusplus
  2. extern?"C"?{
  3. #endif
  4. ?
  5. JNIEXPORT?jboolean?JNICALL?native_sudo(JNIEnv?*env,?jobject?obj,?jstring?xmd);
  6. JNIEXPORT?jboolean?JNICALL?native_exit(JNIEnv?*env,?jobject?obj);
  7. #ifdef?__cplusplus
  8. }
  9. #endif

?? ??JNIEnv 從linux的本質上來講是本地線程的環境,JNIEnv只在當前線程中有效。android 調試工具。指針不能從一個線程進入另一個線程,但可以在不同的線程中調用本地方法(這時,所傳遞的env是不同的)

? ??總結下:JNIEnv是與線程相關的變量,不同線程的JNIEnv彼此獨立。而JavaVM是虛擬機的JNI層的代表,在虛擬機進程中只有一個JavaVM,所以該進程的所有線程都可以使用這個JavaVM。

????簡單來講,就是庫函數的作用,具有良好可重載性。上一張圖片就簡單明了了:

3.3.2 使用JNINativeMethod注冊到線程環境

JNINativeMethod定義如下:

  1. static?JNINativeMethod?methods[]?=?{
  2. ??????{"sudo","(Ljava/lang/String;)Z",(void*)native_sudo},
  3. ??????{"nexit","()Z",(void*)native_exit},
  4. };

????native_sudo是jni層定義的函數。Android jni。

? ? sudo是JAVA層調用的函數。

? ??(Ljava/lang/String;)Z是函數傳遞參數和返回參數,多個參數使用";"進行分割。括號里的是形參,括號外的是返回值

? ? 這里的參數表示,后續作下補充。

? ??注:該結構體,第二個參數的分號漏掉,會導致無法找到JNI函數。android權限處理、

?

????注冊的過程直接上代碼了,這里可以直接套用:

  1. static?int?registerNativeMethods(JNIEnv*?env?,?const?char*?className?,?JNINativeMethod*?gMethods,?int?numMethods)
  2. {
  3. ????jclass?clazz;
  4. ????clazz?=?(*env)->FindClass(env,?className);
  5. ????if?(clazz?==?NULL)
  6. ????{
  7. ????????return?JNI_FALSE;
  8. ????}
  9. ?
  10. ????if?((*env)->RegisterNatives(env,?clazz,?gMethods,?numMethods)?<?0)
  11. ????{
  12. ????????return?JNI_FALSE;
  13. ????}
  14. ?
  15. ????return?JNI_TRUE;
  16. }
  17. ?
  18. //自定義函數
  19. static?int?registerNatives(JNIEnv*?env)
  20. {
  21. ????const?char*?kClassName?=?"io/github/yanbober/ndkapplication/NdkJniUtils";//指定要注冊的類
  22. ????return?registerNativeMethods(env,?kClassName,?methods,??sizeof(methods)?/?sizeof(methods[0]));
  23. }
  24. ?
  25. JNIEXPORT?jint?JNICALL?JNI_OnLoad(JavaVM*?vm,?void*?reserved)
  26. {
  27. ????LOGD("customer---------------------------JNI_OnLoad-----into.\n");
  28. ????JNIEnv*?env?=?NULL;
  29. ????jint?result?=?-1;
  30. ?
  31. ????//test();
  32. ?
  33. ????if?((*vm)->GetEnv(vm,?(void**)?&env,?JNI_VERSION_1_4)?!=?JNI_OK)
  34. ????{
  35. ????????return?-1;
  36. ????}
  37. ????assert(env?!=?NULL);
  38. ?
  39. ????if?(!registerNatives(env))
  40. ????{
  41. ????????return?-1;
  42. ????}
  43. ?
  44. ????return?JNI_VERSION_1_4;
  45. }

?3.3.3 JAVA層的定義

  1. public?class?NdkJniUtils?{
  2. ?
  3. ????public?native?boolean?sudo(String?cmd);
  4. ????public?native?boolean?nexit();
  5. ?
  6. ????static?{
  7. ????????System.loadLibrary("YanboberJniLibName");
  8. ????}
  9. }

?? ? 這里使用了類封裝。使用時,New一個NdkJniUtils即可調用JNI函數。

? ? ?函數使用native聲明之后,JAVA鏈接器會認為這個函數時外部函數,因此沒有在JNI層作相關定義,JAVA項目工程也是可以編譯通過的。

?????注:loadLibrary需要與之前build.gradle 中ndk字段聲明的名字相同。android 無線adb調試?

3.3.4 不使用JNINativeMethod的方法

?不使用JNINativeMethod的方法時,函數名定義的名稱必須按照規定的格式,相對比較復雜。個人并不喜歡這樣定義。

? 以前作的筆記,直接copy了(需要使用javah工具):

?確認javah生成頭文件的工具能否使用。如果不能,需要確認環境變量。android調試?

? 使用方法:

? 在聲明好native函數之后,進行build。

?然后以build好的class,利用javah生成頭文件,格式如下

  1. 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目錄。android 7、

?

然后,在-d的目錄下創建.c文件,對native函數作具體的定義。

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/3/185671.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息