Jump to content
  • Advertisement
  • Remove ads and support GameDev.net for only $3. Learn more: The New GDNet+: No Ads!

  • 12/21/17 08:09 AM
    Sign in to follow this  

    Android Debugging with Visual Studio Code

    General and Gameplay Programming


    This article discusses how to debug native Android applications using Microsoft Visual Studio Code, which can be useful for game developers implementing background services, prototyping, or other native processes on the Android platform.

    Of course, Android Studio and Visual Studio 2017/2015 also offer Android debugging capabilities, but they're more restrictive with the configuration environment and only allow debugging of applications packaged in an APK - so we are unable to debug any native processes we might be using to prototype, develop services, or other native processes on Android.

    Speaking of APKs, note that VSCode also supports debugging APKs via the Android extension.



    The following components are required to enable debugging:

    1. Visual Studio Code with the C/C++ extension installed.

    2. GNU Debugger (GDB) from the Android NDK.

      Windows <NDK_ROOT>\prebuilt\windows-x86_64\bin
      Linux <NDK_ROOT>\prebuilt\linux-x86_64\bin
      macOS <NDK_ROOT>\prebuilt\darwin-x86_64\bin


    3. A build of the target project with debugging enabled. This can be achieved by passing NDK_DEBUG=1 on the ndk-build command line, or by adding it to the project's Application.mk file. Enabling NDK_DEBUG also causes ndk-build to copy the correct version of gdbserver to the project's output directory. This will need to be copied to the target device to enable the debugger connection.
      1. Also, if the project's Application.mk file specifies the APP_OPTIM setting, it must be set to debug to disable compiler optimizations. While debugging optimized code it possible, it will be a more limited and difficult debugging experience. Optimization can be disabled by passing APP_OPTIM=debug on the ndk-build command line, or by modifying it in the project's Application.mk file.

      2. If the project does not specify the APP_OPTIM setting, setting NDK_DEBUG as described above will automatically disable optimizations.

    Debugging Setup

    Before debugging the first time, open the project workspace in VSCode and perform the following steps:

    1. Open the Debug menu and click Add Configuration...
    2. Choose C/C++ (gdb) Launch as the configuration type. If this option is not available the C/C++ extension is not installed and none of this is going to work.

    3. Configure the debugger settings for the project. The required attributes are described below.

      name The name of the debugging task. This is the name that will be displayed in the UI.
      type Should be set to cppdebug.
      request Should be set to launch.
      program The program to debug. This should point to the local version of the executable with debug symbols (the non-stripped version), which is normally in obj/local/armeabi-v7a under the project's build directory (or obj/local/arm64-v8a for 64 bit builds).
      cwd Doesn't really have any effect, but is required. Can just be set to ${workspaceFolder}.
      MIMode Should be set to gdb.
      miDebuggerPath The path to the gdb executable. This should point to the directory in the Android NDK as indicated above.
      miDebuggerServerAddress The target address to connect to. Since the device is connected via USB, this should be set to localhost:<port>, where <port> is the TCP port chosen for the debugger connection. This same port must be used when starting gdbserver on the device.
      additionalSOLibSearchPath Any additional local paths to search for debug symbols. The directory specified for the program attribute will automatically be searched first. This should point to the directories of the non-stripped versions of any additional shared libraries to be debugged (if they are not in the same directory as the main executable). Separate multiple paths with a colon.
      setupCommands An array of additional gdb commands to be executed during setup of the debugger. This needs to be used to execute the set solib-absolute-prefix command to set the local path to the stripped version of all binaries being debugged.
      preLaunchTask A task to execute before starting the debugger. See the section below about defining tasks in VSCode.

    The other attributes created for the default configuration can be deleted.

    Example launch.json file

        "version": "0.2.0",
        "configurations": [
                "name": "Remote GDB",
                "type": "cppdbg",
                "request": "launch",
                "preLaunchTask": "Forward debug port",
                "cwd": "${workspaceRoot}",
                "program": "${workspaceRoot}/app/Intermediate/android/myapp/local/armeabi-v7a/myapp",
                "additionalSOLibSearchPath": "${workspaceRoot}/app/Intermediate/android/mylib/local/armeabi-v7a",
                "miDebuggerServerAddress": "localhost:5039",
                "setupCommands": [
                        "text": "set solib-absolute-prefix ${workspaceRoot}/app/path/android",
                        "ignoreFailures": false
                "windows": {
                    "miDebuggerPath": "C:/Tools/android-ndk-r13b/prebuilt/windows-x86_64/bin/gdb.exe",
                    "MIMode": "gdb"

    Refer to the C/C++ debugging documentation for additional information. In particular, the logging attribute can be used to enable additional logging output, which can be useful for troubleshooting if the debugger is not working as expected.

    Preparing to Debug

    With the debugger configuration set, there are some additional steps required to debug the project:

    1. Copy the target binaries to the target device.
    2. Copy gdbserver to the target device.

    Starting the Debugger

    With all preparations complete, it's time to start debugging. Use the same port number in these steps as was used in the debugger configuration above.

    1. Execute gdbserver on the target device (execute permissions may need to be enabled). The server can be run in two modes: execute or attach.
      1. Execute mode will load the target executable and then wait for a client to attach. When the client attaches it will begin execution of the program. This mode is necessary to debug an application's initialization.
      2. Attach mode will attach to an already running process. It will not interrupt the process.

        Run mode gdbserver :<port> <exe>
        Attach mode gdbserver :<port> --attach <pid>
    2. Forward the debugger port from the device with ADB: adb forward tcp:<port> tcp:<port>

    3. Start the debugger in VSCode.

      1. Enable the Debug panel by clicking the bug icon on the left side of the VSCode window.
      2. Select the debug configuration from the list at the top of the panel.
      3. Click the go button to launch the debugger.
    Once the debugger starts to connect, the VSCode debug console will display messages from the debugger and allow manual debugger commands to be executed if necessary (the program must be stopped to execute debug commands). The debug panels will display debugging information (variable watches, callstacks, breakpoints, etc.), and a debugger toolbar will provide access to common debug commands. Mouse cursor based display of variables is also supported.


    VSCode also supports the definition of tasks, which can be used to execute any command line process, typcially as part of building and/or testing code. These tasks can also be used to support debugging. For instance, a task could be defined to forward the debugger port. This could then be incorporated in the debugger configuration using the preLaunchTask attribute to ensure the port is forwarded before attempting to connect the debugger. Tasks can be configured by selecting Configure Tasks... from the Tasks menu. See the VSCode documentation for more information about task configuration.

    Example tasks.json file

        "version": "2.0.0",
        "tasks": [
                "label": "Forward debug port",
                "type": "shell",
                "command": "adb",
                "args": [
                "presentation": {
                    "reveal": "never"
                "problemMatcher": []

      Report Article
    Sign in to follow this  

    User Feedback

    Create an account or sign in to comment

    You need to be a member in order to leave a comment

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now

  • Advertisement
  • Advertisement
  • Latest Featured Articles

  • Featured Blogs

  • Popular Now

  • Similar Content

    • By Brizzler
      Hey Everyone, 
      I'd like to review some of your indies games! I'm interested in games made for the Universal Windows Platform (UWP).
      Reply to this post if your interested in having your games reviewed and youtubed on my channel:
    • By marcus12

      Glad to share that our mobile game: Solbot Energy Rush available on Android and iOS platform got accepted into:

      Indie Prize Showcase at Casual Connect Asia 2018 to be held in November-12 to 14.

      As indies it's a big encouragement for us!
      Playstore: https://play.google.com/store/apps/details?id=com.freakoutgames.chromaflyer

      iTunes : https://itunes.apple.com/us/app/solbot-energy-rush/id1368418939?ls=1&mt=8
    • By Ruslan_Abdullakh
      Hello there! I'd like to show you my new game - Hurry Birdie. It's an endless game where you have to dodge tree brunches and stones falling from above. Your birdie flies from side to side and speeds up when you press the screen.
      Features:   * Nice design; * You can unlock new birdies; * Easy to play; * Leaderboard; * Good timekiller.   Download here: iOS: https://itunes.apple.com/app/id1434970622?mt=8 Android: https://play.google.com/store/apps/details?id=com.abdullakh.hurrybirdie
    • By babaliaris
      I'm trying to understand how to load models with Assimp. Well learning how to use this library isn't that hard, the thing is how to use the data. From what I understand so far, each model consists of several meshes which you can render individually in order to get the final result (the model). Also from what assimp says:
      One mesh uses only a single material everywhere - if parts of the model use a different material, this part is moved to a separate mesh at the same node The only thing that confuses me is how to create the shader that will use these data to draw a mesh. Lets say I have all the information about a mesh like this:
      class Meshe { std::vector<Texture> diffuse_textures; std::vector<Texture> specular_textures; std::vector<Vertex> vertices; std::vector<unsigned int> indices; } And lets make the simplest shaders:
      Vertex Shader:
      #version 330 core layout(location = 0) in vec3 aPos; layout(location = 1) in vec3 aNormal; layout(location = 2) in vec2 aTexCoord; uniform vec3 model; uniform vec3 view; uniform vec3 projection; out vec2 TextureCoordinate; out vec3 Normals; void main() { gl_Position = projection * view * model * vec4(aPos, 1.0f); TextureCoordinate = aTexCoord Normals = normalize(mat3(transpose(inverse(model))) * aNormal); } Fragment Shader:
      #version 330 core out vec4 Output; in vec2 TextureCoordinate; in vec3 Normals; uniform sampler2D diffuse; uniform sampler2D specular; void main() { Output = texture(diffuse, TextureCoordinate); }  
      Will this work? I mean, assimp says that each mesh has only one material that covers it, but that material how many diffuse and specular textures can it have? Does it makes sense for a material to have more than one diffuse or more that one specular textures?  If each material has only two textures, one for the diffuse and one for the specular then its easy, i'm using the specular texture on the lighting calculations and the diffuse on the actual output.
      But what happens if the textures are more? How am i defining them on the fragment shader without knowing the actual number? Also how do i use them? 
    • By FlyX
      Hey Gamedev.net Community!
      I am working on a mobile builder game that's already running for 8 years.
      In its early days, the game had a nice content progression until level 30(current max level is 140). With content progression, I mean at what level items unlock in the build menu. However, over the last ~4 years, the previous developer decided to unlock all the content between lvl 1 and level 30 (reasoning that the new content should be available for all players). This results in 1200 ~available items at level 1 and ~3300 items at level 30. Overwhelming players at the start and missing any content progression after level 30(can be reached within a few weeks, while a big part of the community is playing since multiple years).
      But how should this be addressed in a running game with a considerable user base across all levels?
      Internally we have a passionate discussion between moving existing items to later levels(and risking to anger existing players) or just adding new content to later levels(don't address the too much choice issue at the start)
      Since we are kinda stuck in the discussion, it would be nice to hear some external input
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!