Monday, May 27, 2013

ActionBarSherlock in Android Studio 0.1

[1st UPDATE: In Android Studio 0.1.1 the project structure of a new project has changed slightly: The name of top level directory is now postfixed with 'Project'. Everything else works as described.
2nd UPDATE, 23 June 2013: Fixed the build.gradle file for Android Studio 0.1.6
3rd UPDATE, 25 June 2013: Added a section to reflect latest changes in the Gradle Plugin and handling of the support library]

Note: While this guide uses ActionBarSherlock as an example the very same procedure will work for many library projects.

Since Android Studio was released as "Early Access Preview" there has been a lot of confusion how to use ActionBarSherlock and other library projects in it. Many people were successful when they imported projects from Eclipse after using ADT's export functionality but there was no how-to for projects created in Studio. I've been struggling with it myself for many hours.
After Xavier Ducrohet posted a little comment on Goolge+ it finally turned out that the problem essentially was caused by a misconception and lack of documentation: Android Studio's UI for managing dependencies is useless for the gradle based build system. And so are all the guides proposing a IntelliJ kind of dependency management.You have to manually edit your dependencies!

So here's a step-by-step guide how to integrate ActionBarSherlock into your Android Studio project:


Create a new project "SherlockTest":


Click "Next" until you're done:




After the wizard has finished you will find a new project with the following structure:


Now you need to put a copy of ActionBarSherlock into your project: Open a terminal, 'cd' into your project, create a 'libraries' directory and clone ActionBarSherlock from github:

[fex@yerbouti ~]$cd ~/AndroidStudioProjects/SherlockTest/
[fex@yerbouti SherlockTest]$mkdir libraries
[fex@yerbouti SherlockTest]$cd libraries
[fex@yerbouti libraries]git clone git://github.com/JakeWharton/ActionBarSherlock.git

After cloning ABS the project structure in Android Studio will show the newly added directories:


Now, you need to tell your build system that those directories exist by editing ~/AndroidStudioProjects/SherlockTest/settings.gradle. Just add the path to your library so that settings.gradle looks like this:

include ':SherlockTest', ':libraries:ActionBarSherlock:actionbarsherlock'

Next, create a build.gradle file in libraries/ActionBarSherlock/actionbarsherlock. Just copy the one from SherlockTest-SherlockTest (you can do this using Ctrl-C and Ctrl-V in Android Studio). You need to edit it a bit. So open the build.gradle file in libraries/ActionBarSherlock/actionbarsherlock change the 'apply-plugin' line to mark this as a library and add a sourceSet section to the android section. The whole build.gradle file should look like this now:

buildscript {
    repositories {
        maven { url 'http://repo1.maven.org/maven2' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.4'
    }
}
apply plugin: 'android-library'

dependencies {
    compile files('libs/android-support-v4.jar')
}

android {
    compileSdkVersion 17
    buildToolsVersion "17.0.0"

    defaultConfig {
        minSdkVersion 7
        targetSdkVersion 16
    }
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
        }

        instrumentTest.setRoot('tests')
    }
}

Now you can add the dependency to your main project by editing the build.gradle file located in the SherlockTest-SherlockTest subtree in the project structure. Just add

compile project(':libraries:ActionBarSherlock:actionbarsherlock')

to the dependencies section.
[EDIT: As of Android Studio 0.1.6 you have to remove the dependency on support-v4.jar as well. It is already referenced by ABS.]
[EDIT 25 June 2013: See additional notes below for the right way to referencing the support library!]

So the whole build.gradle file looks like this:

buildscript {
    repositories {
        maven { url 'http://repo1.maven.org/maven2' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.4'
    }
}
apply plugin: 'android'

dependencies {
    compile project(':libraries:ActionBarSherlock:actionbarsherlock')
}

android {
    compileSdkVersion 17
    buildToolsVersion "17.0.0"

    defaultConfig {
        minSdkVersion 7
        targetSdkVersion 16
    }
}

That's it! Now you can use Sherlock* classes in Android Studio and build your project from Studio as well. You might need to restart Android Studio or reload you project to get autocomplete of Sherlock* classes though.

Additional notes

While it all works as described you might want to tweak you build.gradle files a bit more.


Use latest Android Gradle Plugin

First, in order to always use the most recent version of the Android Gradle Plugin you should change all occurences of

dependencies {
        classpath 'com.android.tools.build:gradle:0.4'
    }

to

dependencies {
        classpath 'com.android.tools.build:gradle:0.4.+'
    }

Referencing the support library the right way

Second, you should not reference the support library the way it's done above. This only works if there's exactly one library depending on it. The right way to do it is by using the Android Support Repository. If you haven't installed it already you should do so using the SDK Manager from Studio. It's located in the "Extras" section.
After you have it installed you can reference the support library by replacing

dependencies {
    compile files('libs/android-support-v4.jar')
}

with

dependencies {
    compile 'com.android.support:support-v4:13.0.0'
}

You should also add this to the main build.gradle file (not the one in the top level directory) so that it reads:

buildscript {
    repositories {
        maven { url 'http://repo1.maven.org/maven2' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.4.+'
    }
}
apply plugin: 'android'

dependencies {
    compile 'com.android.support:support-v4:13.0.0'
    compile project(':libraries:ActionBarSherlock:actionbarsherlock')
}

android {
    compileSdkVersion 17
    buildToolsVersion "17.0.0"

    defaultConfig {
        minSdkVersion 7
        targetSdkVersion 16
    }
}


Monday, May 13, 2013

Cross compiling native audio libraries for Android - Part 2

Update July, 31 2013: The latest git version of libsndfile builds fine without editing sndfile-play.c

In part 1 of this small series of blog posts I've shown you how to set up a cross compile environment for building autotools projects for Android. Now let's ut it to the test and build some audio libraries. To follow this tutorial please create a 'src' subdirectory in your toolchains directory and cd into it:

cd $TOOLS/android-toolchains/arm-linux-androideabi-4.8
mkdir src

Ogg - first try

Let's start with ogg. You can find a source tarball on xiph.org. Download and extract it to your just created src folder:

cd src
wget http://downloads.xiph.org/releases/ogg/libogg-1.3.0.tar.gz
tar xvzf libogg-1.3.0.tar.gz

Now try to build it:

cd libogg-1.3.0
android-configure

This will fail with the following error:

checking host system type... Invalid configuration `arm-linux-androideabi': system `androideabi' not recognized
configure: error: /bin/sh ./config.sub arm-linux-androideabi failed

What's wrong?

This is an error you will frequently encounter. Configure is using a script called 'config.sub' and it doesn't know about arm-linux-androideabi. This doesn't come as much of a surprise as the version shipped with the tarball has a timestamp '2009-11-20'. I'm not sure but I don't think there was a compiler with arm-linux-androideabi back then.

Fortunately,  'config.sub' isn't really part of the actual sources but is generated with a script called 'autogen.sh' that is not part of the source tarball but can be found in the git tree.

Ogg - second try

So, let's clean up and try with ogg from git:

rm -rf libogg-*
git clone git://git.xiph.org/mirrors/ogg.git
cd ogg

This directory doesn't contain the 'configure' script, yet. So we have to create it by running 'autogen.sh':

./autogen.sh
android-configure
android-make
android-make install

These commands should run without problems. If you run into issues though you are probably missing some development tools in your Linux installation. Install them using apt-get, yum or whatever your distribution is using.

Now, let's verify our installation:

ls $TOOLS/android-toolchains/arm-linux-androideabi-4.8/lib | grep ogg 

Should yield output similar to this:
libogg.a
libogg.la
libogg.so
libogg.so.0
libogg.so.0.8.0

Great, the first native library has been built!

Vorbis

If everything went successfully with ogg building vorbis is straight forward:
cd ..
git clone git://git.xiph.org/mirrors/vorbis.git
cd vorbis
./autogen.sh
android-configure
android-make
android-make install

FLAC

Building flac is just the same:
cd ..
git clone git://git.xiph.org/flac.git

cd flac
./autogen.sh
android-configure
android-make
android-make install


UPDATE: Currently  FLAC from git won't build. Please, checkout the last working version d35b21e7b92a46fb64307f7b43f173f5efa35192 before building.

Update: I'm currently getting an error on the first run of android-make related to 'docbook-to-man'. The second run of android-make runs fine.

libsndfile - first try

Now try to build libsndfile the same way:


cd ..
git clone git://github.com/erikd/libsndfile.git
cd libsndfile
./autogen.sh
android-configure

Your ogg, vorbis and flac libraries should have been recognized:

Configuration summary :

    libsndfile version : .................. 1.0.26pre5

    Host CPU : ............................ arm
    Host Vendor : ......................... unknown
    Host OS : ............................. linux-androideabi

    Experimental code : ................... no
    Using ALSA in example programs : ...... no
    External FLAC/Ogg/Vorbis : ............ yes


Now build it:

android-make && android-make install

Done! You now have a complete set of libsndfile, libogg, libvorbis, libflac build for Android!

But there have been lots of warnings in the build process of libsndfile. So we should probably perform some tests before using it in an Android project. So the next part will show how to use those libraries and how to run the libsndfile test suite.

Cross compiling native audio libraries for Android - Part 1

Update July, 31 2013: Use more recent libs and NDK

Preface

In my science shows I'm using many sound cues - like playing an intro when the show starts, setting some sound accents to help the audience focus on those little gems and surely some dramatic music when it helps to build up the suspense.
I've been using my own cue playback software for this for many years and it has served me well. Right now I'm in the process of porting parts of this software to Android. In this blog I will publish some of the findings I make during this ongoing project - as a note to myself and as a help for others. I'll start with a small series on building native libraries for Android.


Android NDK


The Android NDK offers the tools to use native C/C++ code in Android projects. However, the documentation is not too verbose on how to use the NDK for building existing open source projects. While many projects need their own tweaks and patches a lot of  libraries I am using in my audio programs  (e.g. libsndfile, flac, libogg, libvorbis and  mpg123) are astonishingly easy to build once you properly set up your cross compile environment.
But beware of tiny little problems (read: compiler warnings): As you will see, e.g. libsndfile builds fine with a couple of minor tweaks - but that doesn't mean it will work as expected.

Preparing the tools

First, you need the Andoid SDK. If you don't already have it installed get it from http://developer.android.com/sdk/index.html. As there are different versions available, please follow the installation instructions for your copy.
Next, you need the latest version of the NDK for your operating system. Get it from http://developer.android.com/tools/sdk/ndk/index.html. At the time of this writing the lastest version is r8e. As I'm using a 64-bit Linux the file to get is android-ndk-r9-linux-x86_64.tar.bz2. For historical reasons I like to have my external tools all in $HOME/tools and export a corresponding environment variable:

export TOOLS=$HOME/tools

You don't need to follow this habit but the instructions are written this way. Now, extract your NDK tarball to $TOOLS:

cd $TOOLS
tar xvjf /path/to/downloaded/file/android-ndk-r9-linux-x86_64.tar.bz2

You'll find a new directory android-ndk-r8e in your $TOOLS directory. For convenience, I like to keep a symbolic link pointing to the latest NDK and set yet another environment variable:

ln -s android-ndk-r9 android-ndk
export NDK=$TOOLS/android-ndk


Setting up the toolchain

Working with software projects using autotools is much simpler if you set up a standalone toolchain. This is explained in $NDK/docs/STANDALONE-TOOLCHAIN.html. Here's the command to  put the arm-linux-androideabi-4.8 toolchain in $TOOLS/android-toolchains/arm-linux-androideabi-4.8:

$NDK/build/tools/make-standalone-toolchain.sh \
--platform=android-14 --toolchain=arm-linux-androideabi-4.8 \
--install-dir=$TOOLS/android-toolchains/arm-linux-androideabi-4.8 \
--system=linux-x86_64

I'm using --toolchain=arm-linux-androideabi-4.8 since I need some C++11 features that are not available in previous versions of gcc. Again, read $NDK/docs/STANDALONE-TOOLCHAIN.html for the other options.

Preparing the environment

For convenience you should setup a couple of convenience wrapper scripts and environment variables for handling autotools projects. First, create a directory for executables in your home directory:

mkdir $HOME/bin

Then modify your .bashrc or .bash_profile depending on your distribution or own preferences by adding the following lines:
# tools directory
TOOLS=$HOME/tools
export TOOLS

# Android NDK path
NDK=$TOOLS/android-ndk

# Add Android toolchains executables to the path
PATH=$PATH:$TOOLS/android-toolchains/arm-linux-androideabi-4.8/bin

# Add $HOME/bin to your path
PATH=$PATH:$HOME/bin

# Don't forget to export the modified $PATH
export PATH

Make sure that those variables are correctly set in your working shell.

Next, create a wrapper for 'configure' in $HOME/bin:

#!/bin/bash
# This file: $HOME/bin/android-configure
#
CXX=arm-linux-androideabi-g++
CC=arm-linux-androideabi-gcc
./configure --host=arm-linux-androideabi --prefix=$TOOLS/android-toolchains/arm-linux-androideabi-4.8 $@

and one for 'make':

#!/bin/bash
# This file: $HOME/bin/android-make
#
CXX=arm-linux-androideabi-g++
CC=arm-linux-androideabi-gcc
make $@

These wrappers just set the CXX and CC environment variables before calling './configure' or 'make', respectively.

Some projects use pkg-config to figure out compiler flags etc. So we create another wrapper:

#!/bin/bash
#
# This file: $HOME/bin/arm-linux-androideabi-pkg-config

# This file has no copyright assigned and is placed in the Public Domain.
# No warranty is given.

# Original version and further reading: 
# http://www.mega-nerd.com/erikd/Blog/CodeHacking/MinGWCross/pkg-config.html

# When using cross compiler tools, the native Linux
# pkg-config executable works fine as long as the default PKG_CONFIG_LIBDIR
# is overridden.
export PKG_CONFIG_LIBDIR=$TOOLS/android-toolchains/arm-linux-androideabi-4.8/lib/pkgconfig
# Also want to override the standard user defined PKG_CONFIG_PATH
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH_ARM_ANDROID_EABI

# Now just execute pkg-config with the given command line args.
pkg-config $@


Make them executable by:

chmod u+x $HOME/bin/android-configure
chmod u+x $HOME/bin/android-make
chmod u+x $HOME/bin/arm-linux-androideabi-pkg-config

How to use it in a perfect world

Whenever you come across an autotools project, i.e. a project that is build using the triplet './configure', 'make', 'make install' all you should need to do is use 'android-configure' instead of './configure' and 'android-make' instead of 'make'.


...and in the real world


In reality though there are lots of issues that may arise since Android is quite different from any usual Linux distribution. I'll discuss some of them in the forthcoming part 2.

Tuesday, January 22, 2013

Another blog with nothing to say?

Well, yes, this is another blog. Or, at least, it might become another blog. At the time of this writing there's little more than the slight intention to write about some of the stuff I'm doing in the lands of Android, Audio programming and Arduino.
How do these topics relate for me? All of the stuff I'm developing is used by me in my shows. I'm using Arduinos to trigger cues remotely, Android devices and laptops to play those cues. Moreover, I'm using Pd for some sound effects and demos of audio illusions and JACK for cross-platform audio programming.
That's what it's all about it will be all about, eventually.