10

In Android Studio 0.6 I created an android test project with a very simple C function wrapped with the JNI. I set android:debuggable="true" in the AndroidManifest.xml.

I ran ndk-build NDK_DEBUG=1. This generated a gdbserver and a gdb.setup file in the correct location.

enter image description here

However, when I built the project in Android studio, and ran ndk-gdb --debug I got the following output:

Android NDK installation path: /usr/local/android-ndk-r9d
Using default adb command: /Applications/Android Studio.app/sdk/platform-tools/adb
ADB version found: Android Debug Bridge version 1.0.31
Using ADB flags:
Using JDB command: /usr/bin/jdb
Using auto-detected project path: .
Found package name: com.example.testndk.app
ABIs targetted by application: armeabi-v7a
Device API Level: 19
Device CPU ABIs: armeabi-v7a armeabi
Compatible device ABI: armeabi-v7a
Using gdb setup init: ./libs/armeabi-v7a/gdb.setup
Using toolchain prefix: /usr/local/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-
Using app out directory: ./obj/local/armeabi-v7a
Found debuggable flag: true
Found gdb.setup under libs/armeabi-v7a, assuming app was built with NDK_DEBUG=1
Found data directory: '/data/data/com.example.testndk.app'
ERROR: Non-debuggable application installed on the target device.
       Please re-install the debuggable version!

I looked inside the apk gradle generated to make sure gdbserver was there, but I couldn't find the gdbserver or gdb.setup files! Where did they go?? It looks like gradle isn't packaging them in my apk!

Here's my build.gradle:

apply plugin: 'android'

android {
    compileSdkVersion 19
    buildToolsVersion "19.1.0"

    defaultConfig {
        applicationId "com.example.testndk.app"
        minSdkVersion 9
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"
    }

    sourceSets.main {
        jniLibs.srcDir 'src/main/libs' // use the jni .so compiled from the manual ndk-build command
        jni.srcDirs = [] //disable automatic ndk-build call
    }

    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:19.+'
}

How can I get gradle to properly package the gdbserver in my apk? If you want to try it yourself, I put the full source on github. https://github.com/cypressf/testndk

Cypress Frankenfeld
  • 2,317
  • 2
  • 28
  • 40

6 Answers6

13

I've experimented the same issue. Setting this:

android{
  buildTypes {
    debug {
        jniDebuggable true
    }
  }
}

wouldn't help since you don't rely on the android-plugin NDK integration.

One (not-so-good) solution is to manually copy the gdbserver and gdb.setup files to your app's nativeLibraryPath directory on the device, after your apk has been installed.

Xargs
  • 769
  • 8
  • 12
ph0b
  • 14,353
  • 4
  • 43
  • 41
  • 1
    This is an acceptable workaround for now, because I'm not always building with debug mode. Thanks! – Cypress Frankenfeld Jun 12 '14 at 15:56
  • On the other hand, if someone else comes up with a better answer that can package the files automatically using gradle, I'd love to hear from you. – Cypress Frankenfeld Jun 12 '14 at 15:57
  • How do you copy the files into the /data/data//lib/ folder? It is read-only. Do you need root access? Thanks. – user1906 Aug 29 '14 at 05:42
  • Yes, you need to root the phone first. This is an unpleasant workaround. – Cypress Frankenfeld Feb 10 '15 at 19:37
  • In my similar case this is because `adb` is not running as `root` so it can't access `/data/data/`. After execute `adb root` and `adb remount`, suppose your device is rooted, the `ndk-gdb` works – jayatubi May 06 '15 at 06:04
  • In version 0.4 of the experimental plugin the property is called: `debuggable` instead of `jniDebuggable` – JE42 Nov 29 '15 at 10:29
0

I also get the same issue.

=Way 1=

Due to gdbserver is named 'gdbserver' but not 'gbdserver.so', it woulud not be installed into APK. We can do some thing like this:http://ivansotof.com/2013/12/including-native-so-libraries-in-android/, finally we can make sure the APK contain the gdbserver in APK/lib/[ABI]/gdbserver.

=Way 2=

@ph0b's answer is useful for my project and it works! My gradle is v1.2, com.android.tools.build:gradle:0.10.+' Good luck my friend.

Some helpful link: http://ph0b.com/android-studio-gradle-and-ndk-integration/

chlin
  • 41
  • 4
  • 1
    The first link is broken. I found the original post which refers to http://stackoverflow.com/questions/16683775/include-so-library-in-apk-in-android-studio and says "What worked for me is just creating a zip file with the native library. The structure of the file must be: lib/armeabi/libaacdecoder.so Then I just renamed the file as accdecoderso.jar, moved to /libs/ and added it to Gradle dependencies. dependencies { compile files('libs/accdecoderso.jar') } This way you can keep your build.gradle file clean and it doesn’t have to compile jar files on every run." – Sofi Software LLC Dec 30 '14 at 06:32
0

I experienced same problem and solved it by modifying "package[ProductFlavor][BuildType]JniLibs" task this way (after android section in build.gradle):

Sync packageTask = project.getTasks().findByName("packageDebugJniLibs")
packageTask.include(['**/gdbserver', '**/gdb.setup'])

If you use product flavors for ex.: demo, full - you have to modify two tasks with names packageDemoDebugJniLibs and packageFullDebugJniLibs.

// EDIT : you also should add an import:

import org.gradle.api.tasks.Sync

but possibly it will also work if you write def packageTask = ...

marioc64
  • 381
  • 3
  • 12
  • Am getting: Error:(76, 0) Cannot invoke method include() on null object. I listed the package variants: "./gradlew tasks --all | grep package" so that's what I tried, but it's not working. – Sofi Software LLC Dec 30 '14 at 06:40
  • I realized that my solution applies only for android-library project. – marioc64 Jan 23 '15 at 13:43
0

I faced the same issue in two different cases.

1) If you are using Samsung phone for debug. They are not compatible with native debugging with gdb. Check this : http://developer.samsung.com/forum/thread/ndk-debugging-with-gdb/77/178834

2) If you are using any other phone( Sony xperia Z in my case), make sure your phone allows it to debug your app. It means go to developer options > select debug app: xyz.app

rvv
  • 21
  • 3
0

There is another way, using apktool:

✓ Decompile your .apk using apktool d path/to/your.apk

✓ Copy gdbserver and gdb.setup over to the your.apk/libs folder

✓ Rebuild your .apk with apktool b -o out.apk path/to/decompiled

✓ Resign your apk with:

jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore ~/.android/debug.keystore your.apk androiddebugkey

✓ Install your apk with adb install -r your.apk

Leandros
  • 16,805
  • 9
  • 69
  • 108
0

I'm not sure if my answer will answer to your question, but I had similar issue - .apk did not contain /lib/armeabi-v7a/gdbserver, and apparently my own debugger (Visual studio) required that one.

I've searched in %NDK_ROOT% (C:\ProgramData\Microsoft\AndroidNDK64\android-ndk-r11c\) and found that gdbserver, which I require was under path: "C:\ProgramData\Microsoft\AndroidNDK64\android-ndk-r11c\prebuilt\android-arm\gdbserver\gdbserver"

(I've binary compared that it's same file as packaged into .apk file)

I've copied that file into folder specified by gradle:

sourceSets {
    ...
    debug.jniLibs.srcDirs = [
        'libs/debug'

    ]
    release.jniLibs.srcDirs = [
        'libs/release'

    ]

So into libs/debug, and gdbserver ended up into .apk file.

From Visual studio I've reconfigured as launch activity as "Launcher activity" and after that debug session launched successfully.

But I guess I will need to add more visual studio projects in order to enable actual source code debugging - now at least break and threads windows seemed to fill up.

TarmoPikaro
  • 4,723
  • 2
  • 50
  • 62