OpenGL Programming/Installation/Android

From Wikibooks, open books for an open world
Jump to: navigation, search
Teapot running on Galaxy S

Our GLUT tutorials can be run on Android using the simple provided wrapper.

Contents

[edit] Making-of

To understand of the GLUT wrapper works internally, see Android GLUT Wrapper.

[edit] Connecting with USB

When you connect your device through USB, you can use the adb command (from the Android SDK) to browse the filesystem, install applications, debug them, etc.

The easiest way is to run adb as root.

[edit] Allow USB access for non-root users

Alternatively, you can allow unprivileged users to connect to the device, by creating a udev rule.

First, determine your device's idVendor, by typing 'dmesg' after you plug it; check for :

usb 2-1: New USB device found, idVendor=18d1, idProduct=4e22

Then create an udev rule as below, for instance in /etc/udev/rules.d/51-android.rules :

# Galaxy S
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", MODE="0666", GROUP="plugdev" 

(This can be further specialized by idProduct.)

Then restart your udev deamon:

/etc/init.d/udev restart

If you plug your device, the USB character device should have the "plugdev" group:

# ll /dev/bus/usb/002/
total 0
crw-rw-r-T 1 root plugdev 189, 140 janv. 19 21:50 013


[edit] Using our wrapper

In this wikibook, the samples are based on the GLUT library.

Since GLUT is not ported to Android yet, we wrote a simple GLUT-compatible wrapper for Android (see the code repository).

Note: the wrapper is still in its early life and may change in the near future.

Here's how to use it:

Look at the 'tut01_intro-android/' directory.

  • Plug your device (smartphone, tablet...) with USB
  • Add the Android tools to your PATH, for instance:
export PATH="$PATH:/usr/src/android-sdk-linux/tools:/usr/src/android-sdk-linux/platform-tools:/usr/src/android-ndk-r7"
  • Inside the jni/ directory, make tut.cpp a symlink to the GLUT code you need to compile (e.g. ../../tut02_clean/triangle.cpp)
  • Make assets a symlink to the tutorial you're compiling (e.g. ../tut02_clean)
  • Now you can type:
make clean; make && make install
  • You'll get an "OpenGL Wikibook" application on your device, ready to run!

[edit] Full-screen

To make your application full-screen, add this attribute in your AndroidManifest.xml

<application
  ...
  android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
>

[edit] Keyboard

The default Android keyboard does not have keys such as F1/F2/F3.

Instead, you can use Hacker's Keyboard, an alternative input method with more keys:

[edit] Icon

Make sure your application has android:icon defined in AndroidManifest.xml:

    <application ...
                 android:icon="@drawable/icon"

Create two icons:

  • res/drawable/icon.png (48x48)
  • res/drawable-hdpi/icon.png (72x72)

Now your application will have a custom icon on the launcher.

[edit] Debugging

[edit] Browsing standard output

If you want to see your program's standard outputs (stdout and stderr), you need to redirect them to the system log :

adb shell stop
adb shell setprop log.redirect-stdio true
adb shell start  # this may restart your Android session

To check the log files, you can use:

  • The command: adb logcat
  • The 'ddms' utility, with its graphical GUI to browse the logs

[edit] Checking JNI calls

The following will turn on more checks when calling JNI from C/C++:

adb shell stop
adb shell setprop dalvik.vm.checkjni true
adb shell start

You'll get additional traces on the system log, and JNI will be more strict on what it accepts.

[edit] GDB

GDB can be enabled too.

Note: as for NDKr7, there are a few issues to work-around:

  • see below if you use Cyanogen 7.1 for a fix to 'run-as'
  • use the "stabs" format for debug symbols in Android.mk, otherwise GDB will show the wrong source code lines [1]:
LOCAL_CXXFLAGS  := -gstabs+


GDB requires a debug build, add NDK_DEBUG=1 when building your C++ code:

ndk-build NDK_DEBUG=1

When starting gdb, make sure your AndroidManifest.xml mentions it's debuggable, otherwise gdb will behave badly (lack of thread information, crash, etc.):

    <application ...
            android:hasCode="true" android:debuggable="true"

The gdb-server needs a few seconds to start on the device, so your program will start running before it can be paused by the debugger. A work-around is to add a wait in your android_main function:

  sleep(5);

To start the debug session, type:

ndk-gdb --start

[edit] Cyanogen 2.3 fix

ndk-gdb relies on the 'run-as' command, which itself makes a number of checks on the /data/data directory. In Cyanogen 2.3, it's a symlink, and run-as fails with a cryptic message, and ndk-gdb fails in return with [2]:

ERROR: Could not extract package's data directory. Are you sure that
       your installed application is debuggable?

A work-around is to recreate /data/data with symlink :

cd /data/data /datadata.break-run-as
mkdir -m 771 /data/data/
chown system: v
mv /datadata/* /data/data/


[edit] Abstracting differences between OpenGL and GLES2

When you only use GLES2 functions, your application is nearly portable to both desktops and mobile devices. There are still a couple issues to address:

  • The GLSL #version is different
  • GLES2 requires precision hints that are not compatible with OpenGL 2.1.

See the Basic Tutorials 02 and 03 for details and a proposed solution.

[edit] FreeType

If you need FreeType (a library to render fonts), you'll need to cross-compile it. Note: The Android system uses FreeType but internally it doesn't expose it to native apps.

First, prepare the cross-compiler from the NDK:

/usr/src/android-ndk-r7/build/tools/make-standalone-toolchain.sh --platform=android-9 \
  --install-dir=/usr/src/ndk-standalone-9
PATH=/usr/src/ndk-standalone-9/bin:$PATH

Then use it to cross-compile freetype:

tar xf freetype-2.4.8.tar.bz2
cd freetype-2.4.8/
CFLAGS="-std=gnu99" ./configure --host=arm-linux-androideabi --prefix=/freetype --without-zlib
make
make install DESTDIR=$(pwd)

See this discussion for the --std option.

--without-zlib uses the internal copy of zlib inside freetype rather than one independently recompiled for Android. Otherwise you'd get errors such as:

./obj/local/armeabi/libfreetype.a(ftgzip.o): In function `ft_gzip_file_init':
ftgzip.c:(.text+0x3c4): undefined reference to `inflateInit2_'
./obj/local/armeabi/libfreetype.a(ftgzip.o): In function `ft_gzip_file_done':
ftgzip.c:(.text+0x43c): undefined reference to `inflateEnd'
./obj/local/armeabi/libfreetype.a(ftgzip.o): In function `ft_gzip_file_reset':
ftgzip.c:(.text+0x514): undefined reference to `inflateReset'
./obj/local/armeabi/libfreetype.a(ftgzip.o): In function `ft_gzip_file_fill_output':
ftgzip.c:(.text+0x780): undefined reference to `inflate'

Then write an Android.mk file in the new freetype/ directory:

LOCAL_PATH:= $(call my-dir)
 
include $(CLEAR_VARS)
 
LOCAL_MODULE := freetype
LOCAL_SRC_FILES := lib/libfreetype.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/include/freetype2
 
include $(PREBUILT_STATIC_LIBRARY)

See docs/STANDALONE-TOOLCHAIN.html and docs/PREBUILTS.html in the NDK for details. The CLEAR_VARS bit is not documented, but is necessary to avoid mixed-up paths; it is used in the native_app_glue NDK module.


To use FreeType in your project, edit your Android.mk:

...
LOCAL_STATIC_LIBRARIES := ... freetype
...
$(call import-module,freetype)

You will need to specify the freetype directory location as well, using the NDK_MODULE_PATH variable. For instance, you can copy freetype in your project directory and build using:

        ndk-build NDK_MODULE_PATH=. ...

Our wrapper already defines NDK_MODULE_PATH=$$NDK_MODULE_PATH:..

See also Gnash compilation instructions for Android:

[edit] References

  1. http://groups.google.com/group/android-ndk/browse_thread/thread/ebd969a055af3196
  2. http://forum.cyanogenmod.com/topic/27657-run-as-not-working-due-to-datadata-symlink/

< OpenGL Programming/Installation

Browse & download complete code
Personal tools
Namespaces

Variants
Actions
Navigation
Community
Toolbox
Sister projects
Print/export