1.Create Android Studio Project

(1)新建一个Empty Activity工程:TestNDK

(2)在工程的主Activity中加入对.so的引用.这步很关键,将System loadLibrary放入主Activity,是让程序启动后立刻加载.so,否则后面调试时,会有些麻烦

static {

// Load native library to invoke chreographerCallback().

System.loadLibrary("DebugNDK");

}

public native String stringFromJNI();

(3)使用javah生成相应的.h文件

在Android Studio的Terminal窗口中输入:

cd app\src\main\java #进入工程的app\src\main\java目录

javah stable.testndk.MainActivity #生成.h文件,stable.testndk是包名,MainActivity是native函数所在的类名

接下来就可以编译NDK了,NDK编译完再回来

(4)将NDK编译出的libs目录下的文件copy到app\libs目录下,如下:

app\libs\armeabi\

gdb.setup

gdbserver

libDebugNDK.so

app\libs\armeabi-v7a\

gdb.setup

gdbserver

libDebugNDK.so

app\libs\mips\

gdb.setup

gdbserver

libDebugNDK.so

app\libs\x86\

gdb.setup

gdbserver

libDebugNDK.so

(5)修改app\build.gradle,在android下加入如下代码,告知jniLibs所在目录

sourceSets {

main() {

jniLibs.srcDirs = ['libs']

}

}

(6)rebuild工程,可以通过Build->Build APK来生成APK,然后用7Zip看一下里面是将.so打包进去了.

接下来进入第三步调试NDK

2.NDK程序的编译

(1)以 android-ndk-r10b\samples\hello-jni为模板,建立自己的NDK程序(DebugNDK).

自己的程序需要修改Android.mk文件,增加工程及代码文件,这里将所有的hello-jni更改为DebugNDK.

修改DebugNDK.c中的jni对外接口函数名,修改为上面使用javah到处的.h中的相应函数(Java_stable_testndk_MainActivity_stringFromJNI).

(2)编译.so

在windows命令行下,进入工程目录(TestNDK目录),输入如下命令:

ndk-build NDK_DEBUG=1 #注意事先要将ndk-build所在目录设置到系统环境变量中

之后开始编译,最终在工程目录下会生成libs和obj两个目录,其中libs目录下的是发布到硬件的.so, obj下是用于调试的,后面会用到.

好了到此可以回到 上面个 Create Android Studio Project 的第4步了.

3.NDK调试

服务器端配置

(1)在手机上运行TestNDK程序

(2)将编译NDK程序时生成的gdbserver pull到手机(我是放到/data/data/stable.testndk.

gdbserver在app\libs\x86\下,可以将其放到手机 /data/data/stable.testndk/lib 下

在windows命令行下,执行:

adb push .\app\libs\x86\gdbserver /data/data/stable.testndk/lib/

(3)在手机上启动gdbserver并attach你想调试的进程,并指定监听调试命令的端口(此端口是手机上的端口)

在windows命令行下,执行:

adb shell #进入手机

cd /data/data/stable.testndk/lib

ps | grep stable.testndk #查看要调试进程的PID

gdbserver :1818 --attach 19906 #:1818是端口号,19906 是进程ID

此时,终端终端上会显示:

Attached; pid = 19906

Listening on port 1818

台式机端配置

(1)使用adb做端口映射,将pc机上的端口定向到手机上gdbserver监听的端口

adb forward tcp:1818 tcp:1818 #端口映射,将pc机的1818端口映射到手机的1818端口

(2)将设备上的app_process32拉到台式机,用于gdb调试.

adb pull /system/bin/app_process32 ./

(3)使用android-ndk-r10b\toolchains下的gdb客户端去连接gdbserver,gdb的类型要选择针对手机平台的,由于我使用的手机是x86 PC模拟器,因此要选择:

android-ndk-r10b\toolchains\x86-4.8\prebuilt\windows-x86_64\bin\i686-linux-android-gdb.exe

并且gdb版本要和gdbserver一致。(可以通过--version来确认)

在windows命令行下,执行如下命令,app_process32_path 表示app_process32所在目录。

android-ndk-r10b\toolchains\x86-4.8\prebuilt\windows-x86_64\bin\i686-linux-android-gdb.exe {app_process32_path}\app_process32

上面的命令执行完后,便进入gdb命令模式了(命令行前有(gdb)),然后执行:

target remote :1818 #连接本地的:1234端口,此端口已经和手机的1234端口做好映射。

set solib-search-path {solibpath} #加载所有的动态连接库,solibpath的路径位置可以参考:NDK编译输出文件 gdb.setup 中的"set solib-search-path XXX"的目录,但注意要使用绝对目录.

#我的是set solib-search-path D:/Android/android-ndk-r10b/samples/TestNDK/obj/local/x86

然后用info shared命令查看是否libDebugNDK.so的符号库已经加载,我的显示的是:

0xaabd92e0 0xaabd93c8 Yes D:\Android\android-ndk-r10b\samples\TestNDK\obj\local\x86\libDebugNDK.so #如果符号库未加载则在Yes后有个(*).

(4)设置断点,开始调试

在gdb模式,执行:

b Java_stable_testndk_MainActivity_stringFromJNI #设置断点

c #运行

然后在函数调用时,断点就可以停住了! Over!