Debugging an Android NDK application with logging messages

Android logging system provides a method for collecting logs from various applications into a series of circular buffers. The logcat command is used to view the logs. Log message is the simplest method of debugging a program, yet one of the most powerful ones. This recipe focuses on message logging in NDK.

How to do it…

The following steps create our sample Android project:

  1. Create an Android application named NDKLoggingDemo. Set the package name as cookbook.chapter3. Create an activity named NDKLoggingDemoActivity. Please refer to the Loading native libraries and registering native methods recipe of Chapter 2, Java Native Interface, if you want more detailed instructions.
  2. Right-click on the project NDKLoggingDemo, select Android Tools | Add Native Support. A window appears, click on Finish to dismiss it.
  3. Add a new file named mylog.h under the jni folder, and add the following content to it:
    #ifndef COOKBOOK_LOG_H
    #define COOKBOOK_LOG_H
    
    #include <android/log.h>
    
    #define LOG_LEVEL 9
    #define LOG_TAG "NDKLoggingDemo"
    
    #define LOGU(level, ...) if (level <= LOG_LEVEL) {__android_log_print(ANDROID_LOG_UNKNOWN, LOG_TAG, __VA_ARGS__);}
    #define LOGD(level, ...) if (level <= LOG_LEVEL) {__android_log_print(ANDROID_LOG_DEFAULT, LOG_TAG, __VA_ARGS__);}
    #define LOGV(level, ...) if (level <= LOG_LEVEL) {__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__);}
    #define LOGDE(level, ...) if (level <= LOG_LEVEL) {__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__);}
    #define LOGI(level, ...) if (level <= LOG_LEVEL) {__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__);}
    #define LOGW(level, ...) if (level <= LOG_LEVEL) {__android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__);}
    #define LOGE(level, ...) if (level <= LOG_LEVEL) {__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__);}
    #define LOGF(level, ...) if (level <= LOG_LEVEL) {__android_log_print(ANDROID_LOG_FATAL, LOG_TAG, __VA_ARGS__);}
    #define LOGS(level, ...) if (level <= LOG_LEVEL) {__android_log_print(ANDROID_LOG_SILENT, LOG_TAG, __VA_ARGS__);}
    
    #endif
  4. Add the following content to NDKLoggingDemo.cpp:
    #include <jni.h>
    #include "mylog.h"
    
    void outputLogs() {
      LOGU(9, "unknown log message");
      LOGD(8, "default log message");
      LOGV(7, "verbose log message");
      LOGDE(6, "debug log message");
      LOGI(5, "information log message");
      LOGW(4, "warning log message");
      LOGE(3, "error log message");
      LOGF(2, "fatal error log message");
      LOGS(1, "silent log message");
    }
    
    extern "C" {
      JNIEXPORT void JNICALL Java_cookbook_chapter3_NDKLoggingDemoActivity_LoggingDemo(JNIEnv* env, jobject o){
        outputLogs();
      }
    }
  5. Change the content of NDKLoggingDemoActivity.java to the following:
    package cookbook.chapter3;
    
    import android.os.Bundle;
    import android.app.Activity;
    
    public class NDKLoggingDemoActivity extends Activity {
       @Override
       public void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           LoggingDemo();
       }
       public native void LoggingDemo();
       static {
           System.loadLibrary("NDKLoggingDemo");
       }
    }
  6. Change the Android.mk file to include the Android log library as follows:
    LOCAL_PATH := $(call my-dir)
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE    := NDKLoggingDemo
    LOCAL_SRC_FILES := NDKLoggingDemo.cpp
    LOCAL_LDLIBS := -llog
    include $(BUILD_SHARED_LIBRARY)
  7. Right-click on the NDKLoggingDemo project, and select Build Project.
  8. Start the monitor logcat output by entering the following command. Then, start the sample Android app on an Android device:
    $ adb logcat -c
    $ adb logcat NDKLoggingDemo:I *:S -v time
    

    The following is a screenshot of the logcat output:

    How to do it…
  9. Start another command line terminal, and enter the following command in it:
    $ adb logcat NDKLoggingDemo:V *:S -v time
    

    This will result into the following output:

    How to do it…
  10. Change the line in mylog.h from #define LOG_LEVEL 9 to #define LOG_LEVEL 4. Rebuild the application, then restart the application.
  11. The outputs of the two terminals we started earlier are the same.
    How to do it…

How it works...

This recipe shows how to use Android log messages. Each log message in Android consists of the following three parts:

  • Priority: It is usually used to filter log messages. In our project, we can control the log by changing the following code:
    #define LOG_LEVEL 4 

    Alternatively, we can selectively display the log output using logcat.

  • Log tag: It is usually used to identify the log source.
  • Log message: It provides the detailed log message.

Tip

Sending log messages on Android consumes CPU resources and frequent log messages can affect the application performance. In addition, the logs are stored in a circular buffer. Too many logs will overwrite some earlier logs, which may not be desirable. Due to these facts, it is recommended we only log errors and exceptions at the release build.

logcat is the command-line tool to view Android logs. It allows one to filter logs according to the log tag and priority. It is also capable of dispalying logs in different formats.

For example, we used the following logcat command in step 8 of the preceding How to do it... section.

adb logcat NDKLoggingDemo:I *:S -v time

The command filters out logs except those with the NDKLoggingDemo tag and priority I (information) or higher. The filter is given in a tag:priority format. NDKLoggingDemo:I indicates logs with a NDKLoggingDemo tag and priority information or higher will be displayed. *:S sets the priority level for all other tags as "silent".

More details about logcat filtering and format can be found at http://developer.android.com/tools/help/logcat.html and http://developer.android.com/tools/debugging/debugging-log.html#outputFormat.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset