Saturday, October 3, 2009

Using SKIA in Android native code

I was in a tearing hurry to get started on Android's MeadiaPlayer like application. I searched all over the net and I could not find any then I set out, with a MacBook (not Pro ), to figure it out myself.

It took me a while, a week, to figure out SKIA usage. First I started with mediaplayer and got lost in the code and reached a dead end in mediaplayer.cpp, then I set out on WebKit. 

I could find everything I wanted in WebView.cpp. 
Here are the changes I did in SimpleJNI sample to get native rendering. 

First include the SKIA header files in SimpleJNI/jni/native.cpp

#include "GraphicsJNI.h"
#include "SkBlurMaskFilter.h"
#include "SkCanvas.h"
#include "SkCornerPathEffect.h"
#include "SkDumpCanvas.h"
#include "SkPath.h"
#include "SkPicture.h"
#include "SkPixelXorXfermode.h"
#include "SkPaint.h"
#include "SkRect.h"
#include "SkTime.h"

Then the entry into methods[] and draw() method definition 

static JNINativeMethod methods[] = {
{"draw", "(Landroid/graphics/Canvas;Landroid/graphics/Paint;)V",(void*)draw},

static jint
draw(JNIEnv *env, jobject thiz, jobject canv, jobject pa) {

SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv);
SkPaint* paint = GraphicsJNI::getNativePaint(env,pa);

SkPath path;
SkRect rect;

paint->setARGB(128, 0, 255, 0);
path.addRoundRect(rect, SkIntToScalar(10), SkIntToScalar(10));
canvas->gt;drawPath(path, *paint);

return 1;

And here is the java client, I removed “add()” related code and added draw method that takes canvas and paint

protected void onDraw(Canvas canvas) {
Paint p = new Paint();

finally declare draw method in Native class.

class Native {
static {
// The runtime will add "lib" on the front and ".o" on the end of
// the name supplied to loadLibrary.
static native int add(int a, int b);
static native int draw(Canvas can, Paint p);

It's not over yet, need to add libraries and include paths to jni/ file

# All of the shared libraries we link against.
libutils \
libandroid_runtime \
libutils \
libskiagl \
libcorecg \
# No static libraries.
# Also need the JNI headers.
external/skia/include/core \
external/skia/include/effects \
external/skia/include/images \
external/skia/include/utils \

now, save all and hit "make SimpleJNI" in the Android Root and should create SimpleJNI APK.

Some observations ..

I used Android 1.6 source code that supports Native code.

I have reused GraphicsJNI to convert Java objects, Canvas and Paint to native Skcanvas objects.

SimpleJNI does not build if I issue just “make” and “make
APP=SimpleJNI", I added an entry development/sdk-atree. and it started to work, Not sure why?

I always got “Permission denied” in Debug.startMethodTracing  opening /sdcard/SimpleJNI.trace.. (I used correct -sdcard ./imgcd option)

"adb install -r" "-r" option does not overwrite the older version of the application, I need to manually remove

Thanks to my team members, Mahalakshmi (script) and Sham (who followed my idea and provided mk file entries), here are some scripts, first to launch the emulator (I used MacBook, run from Android ROOT  the  path)

./out/host/darwin-x86/bin/emulator -kernel ./prebuilt/android-arm/kernel/kernel-qemu -ramdisk ./out/target/product/generic/ramdisk.img -data ./out/target/product/generic/userdata.img -system ./out/target/product/generic/system.img -init-data ./out/target/product/generic/userdata.img -sysdir ./out/target/product/generic/ -skindir ./development/emulator/skins/HVGA -skin layout -shell

To install SimpleJNI
>adb install -r ./out/target/product/generic/system/app/SimpleJNI.apk
To unistall SimpleJNI
>adb uninstall

I just scratched the surface of Android..hope to do more. Guys, leave your comments or any queries on hacks, let me see, if I could hack in.

No comments: