Code Snippets

Rss feed of the category

Android NDK tips

Written by Xavier Gouchet - 23 april 2014 - no comments

The Android NDK can get really powerful, but one of the few drawbacks is that the Android.mk configuration file must list the source files. And if your project contains too many files, it can get quite difficult to maintain. Here's a little tip to list the files in a JNI source trees that is more readable, and more maintainable.

Here's your default Android.mk file


   LOCAL_PATH := $(call my-dir)

   include $(CLEAR_VARS)

   LOCAL_MODULE    := hello-jni
   LOCAL_SRC_FILES := hello-jni.c foo/spam.c  foo/eggs.c foo/bacon.c bar/banana.c 

   include $(BUILD_SHARED_LIBRARY)

Assuming you have folders foo and bar inside your jni folders, each with many source files, here's how you can list all your sources. First create a sources.mk file in each subfolder, with the following code in it :


LOCAL_SRC_FILES += foo/spam.c  foo/eggs.c foo/bacon.c

Then modify the Android.mk file that resides in your jni folder like this ;


   LOCAL_PATH := $(call my-dir)

   include $(CLEAR_VARS)

   LOCAL_MODULE    := hello-jni
   LOCAL_SRC_FILES := hello-jni.c

   include $(LOCAL_PATH)/foo/sources.mk

   include $(BUILD_SHARED_LIBRARY)

Taming the LogCat (part 3)

Written by Xavier Gouchet - 31 january 2014 - no comments

Those who have used the adb tool might have stumbled upon the following message :


$ adb logcat
     - waiting for device -
     error: more than one device and emulator

In such case, you need to find, then specify the device's serial like this :



$ adb devices -l
    List of devices attached 
    XXX900AKC2             device usb:3-1.3 product:falcon model:XT1032 device:falcon_umts
    XXXBDAD913017009       device usb:1-1   product:yakju  model:Nexus  device:maguro

$ adb logcat -s XXXBDAD913017009

Here I used the logcat command but it's the same thing when you want to install an apk or pull a file from a device.

I've just discovered that if you don't specify a serial, adb will look for an environment variable named ANDROID_SERIAL to know which device to use. If you're often using several devices in USB, you can just add the following aliases to your .bashrc file.


# ANDROID DEVICES SERIAL NUMBERS
alias adb-use-galaxy-nexus='export ANDROID_SERIAL=XXXBDAD913017009'
alias adb-use-moto-g='export ANDROID_SERIAL=XXX900AKC2'
alias reset-android-serial='unset ANDROID_SERIAL'

When using the adb logcat command, you can also set in the ANDROID_LOG_TAGS environment variable a list of tag/severity filter, like in the following example.


# suppresses all log messages except those with the tag "ActivityManager", at priority "Info" or above, and all log messages with tag "MyApp", with priority "Debug" or above
export ANDROID_LOG_TAGS="ActivityManager:I MyApp:D *:S"

These tips are fully compatible with the PidCat tool I talked about earlier.

Enabling / Disabling activities at runtime

Written by Xavier Gouchet - 20 february 2013 - no comments

Sometimes, you might want an activity to be available only under specific conditions. But you may want to completely disable it at runtime when some conditions are met. For instance based on the time, or the user geolocation.

This could also let one have different activities based on the user's configuration

You can do so simply by using the PackageManager. In the following example, I disable an activity and enable another one.


PackageManager pm = getPackageManager();
pm.setComponentEnabledSetting(new ComponentName(this, ActivityC.class), 
    PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
pm.setComponentEnabledSetting(new ComponentName(this, ActivityA.class), 
    PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0);

The manifest declares the two activities with the same intent filter, namely the home screen shortcut. But using the previous code, I'm able to get a single one of them in the launcher menu at any given time.

A more complete Activity Lifecycle

Written by Xavier Gouchet - 05 february 2013 - no comments

In one of my application, I want to perform an action when the user has been idle for more than n minutes.

While searching the web I found those two callbacks in the Activity class : onUserInteraction() and onUserLeaveHint , both available since Cupcake.

The first one is simply called whenever an interaction is consumed by the activity : touch, key event, trackball event. The second is called just before onPause() when the user leaves your Activity on purpose. For example by pressing the home button, launching another activity from the notification bar. It won't be called when an Activity generated by the system comes in the foreground (an incoming phone call for instance).

And there are a lot more callbacks in an Activity that one can override. So, after some extensive logging and reading through AOSP sources, here's a new and more complete Activity lifecycle graph, with all the callbacks one may find usefull. I also included the callbacks sent to an Activity's fragments.

Android Full LifeCycle

Feel free to add any remark to make this diagram as accurate as possible.

Taming the LogCat

Written by Xavier Gouchet - 30 january 2013 - no comments

A couple of days ago, a question popped on StackOverflow, asking how to link a log line in LogCat to the source code, just like it happens when you Log an exception.

The first answers where to add a fake Exception. Naturally, there will be the line you want, but also a lot of noise in your LogCat.

Then someone proposed a method to simulated an exception Log, without the whole stacktrace (see the answer here).

The solution works fine, but can be quite verbose. With a little bit of try and error, I found out that the most important part is the "at (file.java:42)". It doesn't matter where it is in the message. You can even have mor than one, it only takes into account the last one.

So I worked out a LogLink class to use this systme anywhere and seamlessly. Here's an example of how it works :


	// can be one of INSERT_FIRST, INSERT_LAST or INSERT_NONE
	// default value is INSERT_LAST, and you can call it only once
	LogUtils.setInsertMode(LogUtils.INSERT_LAST); 
	
	// also exist as v, d, w, e and wtf 
	LogUtils.i("MyClass", "A message");

The previous code will output the following output

MyClass     A message at (MyClass.java:42)

You can see and download the LogUtils class here