天天看点

Android skia简单应用

<b>Android skia</b><b>简单应用</b>

         很简单的Skia 2D图形库的调用。

<b>一、</b><b>Skia 2D</b><b>图形库</b>

         Skia是Google一个底层的图形、图像、动画、SVG、文本等多方面的图形库,它是Android中图形系统的引擎。

         Skia的系统库为libskia.so、libskiagl.so(不同版本名称可能有出入)。而libjnigraphics.so图形库由于和其密切相关,一般会一同调用。

<b>二、开始</b><b>Skia</b><b>工程</b>

<b>1</b><b>)Java</b><b>外壳</b>

public class SkiaView extends View { 

    /** TAG标识 */ 

    private static final String TAG = "SkiaView"; 

    /** 载入动态库 */ 

    static { 

        try { 

            System.loadLibrary("SkiaJni"); 

        } catch(UnsatisfiedLinkError e) { 

            Log.e(TAG, "Couldn't load native libs"); 

            e.printStackTrace(); 

        } 

    } 

    public SkiaView(Context context) { 

        super(context); 

    @Override 

    protected void onDraw(Canvas canvas) { 

        super.onDraw(canvas); 

        Log.i(TAG, "==draw start=="); 

        // 调用本地方法 

        native_renderCanvas(canvas); 

        Log.i(TAG, "==draw end=="); 

    /** 本地渲染画布方法 */ 

    private native void native_renderCanvas(Canvas canvas); 

<b>2</b><b>)C/C++</b><b>封装</b>

2.1)我的环境

         XP+Eclipse+Cygwin。并需要准备源码,这里是2.3.3_r1。

2.2)建立工程

         1. 工程地址:AndroidSkia工程根目录jni文件夹。

         2. Build command:bash --login -c "cd $WORKSPACE/AndroidSkia &amp;&amp; $NDKROOT/ndk-build"

         $WORKSPACE、$NDKROOT为工作空间、NDK路径。在Cygwin根目录\home\[your name]\ .bash_profile文件内配置。

         3.includes jni、skia等需要的头文件。当前如下:

<a href="http://blog.51cto.com/attachment/201208/085716764.png" target="_blank"></a>

2.3)Android.mk

LOCAL_PATH := $(call my-dir) 

include $(CLEAR_VARS) 

MY_ANDROID_SOURCE = F:/01.软件/01.开发/05.android/android_sys_src/2.3.3_r1 

MY_ANDROID_SYSLIB = $(MY_ANDROID_SOURCE)/out/target/product/generic/system/lib 

#也可以在cygwin\home\Join\.bash_profile文件内配置,如下: 

#   export MY_ANDROID_SOURCE="/cygdrive/f/..." 

#   export MY_ANDROID_SYSLIB="/cygdrive/f/..." 

LOCAL_MODULE := libSkiaJni 

LOCAL_SRC_FILES := \ 

    jniLoad.cpp \ 

    org_join_skia_SkiaView.cpp 

LOCAL_C_INCLUDES := \ 

    $(MY_ANDROID_SOURCE)/dalvik/libnativehelper/include/nativehelper \ 

    $(MY_ANDROID_SOURCE)/frameworks/base/include \ 

    $(MY_ANDROID_SOURCE)/system/core/include \ 

    $(MY_ANDROID_SOURCE)/frameworks/base/native/include \ 

    $(MY_ANDROID_SOURCE)/frameworks/base/core/jni/android/graphics \ 

    $(MY_ANDROID_SOURCE)/external/skia/include/core \ 

    $(MY_ANDROID_SOURCE)/external/skia/include/config \ 

    $(MY_ANDROID_SOURCE)/external/skia/include/images 

#同时在工程Properties-&gt;C/C++ General-&gt;Paths and Symbols属性内include相应文件目录 

#否则编程时找不到.h文件,不便写代码,但不会影响编译。而LOCAL_LDLIBS/LOCAL_LDFLAGS必需添加。 

#LOCAL_LDLIBS := -L$(MY_ANDROID_SYSLIB) -llog -ljnigraphics  -lskia -landroid_runtime 

#也可以用以下方式指定so库 

LOCAL_LDFLAGS := \ 

    $(MY_ANDROID_SYSLIB)/liblog.so \ 

    $(MY_ANDROID_SYSLIB)/libjnigraphics.so \ 

    $(MY_ANDROID_SYSLIB)/libskia.so \ 

    $(MY_ANDROID_SYSLIB)/libskiagl.so \ 

    $(MY_ANDROID_SYSLIB)/libandroid_runtime.so 

include $(BUILD_SHARED_LIBRARY) 

         LOCAL_C_INCLUDES的头文件路径,第一个是jni的,最后三是lskia的,倒数四是ljnigraphics的,其他为基础的(如llog,除了某一是landroid_runtime的,忘了哪个==)。

         MY_ANDROID_SYSLIB也可从模拟器导出。

2.4)org_join_skia_SkiaView.cpp

#include "jniLoad.h" 

#include &lt;GraphicsJNI.h&gt; 

#include &lt;SkCanvas.h&gt; 

#include &lt;SkPaint.h&gt; 

#include &lt;SkRect.h&gt; 

#include &lt;SkColor.h&gt; 

#include &lt;SkTypes.h&gt; 

#include &lt;SkGraphics.h&gt; 

static void drawFlag(SkCanvas* canv); 

static void native_renderCanvas(JNIEnv* env, jobject obj, jobject canvas) { 

    MY_LOGI("==c method start=="); 

    SkCanvas* canv = GraphicsJNI::getNativeCanvas(env, canvas); 

    if (!canv) { 

        MY_LOGE("==canv is NULL=="); 

        return; 

    canv-&gt;save(); 

    canv-&gt;translate(100, 100); 

    drawFlag(canv); 

    canv-&gt;restore(); 

    MY_LOGI("==c method end=="); 

/** 画旗帜 */ 

static void drawFlag(SkCanvas* canv) { 

    SkPaint* paint = new SkPaint(); 

    paint-&gt;setFlags(paint-&gt;kAntiAlias_Flag); 

    SkRect* rect = new SkRect(); 

    rect-&gt;set(0, 0, 200, 100); 

    paint-&gt;setColor(SK_ColorRED); 

    canv-&gt;drawRect(*rect, *paint); 

    paint-&gt;setColor(SK_ColorGRAY); 

    paint-&gt;setStrokeWidth(10); 

    canv-&gt;drawLine(5, 100, 5, 300, *paint); 

    paint-&gt;setTextSize(30); 

    paint-&gt;setColor(SK_ColorBLUE); 

    paint-&gt;setTextAlign(paint-&gt;kCenter_Align); 

    const char* text = "Hello World"; 

    canv-&gt;drawText(text, strlen(text), 100, 60, *paint); 

/** 

 * JNI registration. 

 */ 

static JNINativeMethod methods[] = { { "native_renderCanvas", 

        "(Landroid/graphics/Canvas;)V", (void*) native_renderCanvas } }; 

int register_org_join_skia_SkiaView(JNIEnv *env) { 

    return jniRegisterNativeMethods(env, "org/join/skia/SkiaView", methods, 

            sizeof(methods) / sizeof(methods[0])); 

2.5)jniLoad.h

#ifndef JNILOAD_H_ 

#define JNILOAD_H_ 

#include &lt;jni.h&gt; 

#include &lt;utils/Log.h&gt; 

#define MY_LOG_TAG "JNI_LOG" 

#define MY_LOGI(...) __android_log_print(ANDROID_LOG_INFO, MY_LOG_TAG, __VA_ARGS__) 

#define MY_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, MY_LOG_TAG, __VA_ARGS__) 

#ifdef __cplusplus 

extern "C" { 

#endif 

int jniRegisterNativeMethods(JNIEnv* env, const char* className, 

        const JNINativeMethod* gMethods, int numMethods); 

#endif /* JNILOAD_H_ */ 

2.6)jniLoad.cpp

#include &lt;stdlib.h&gt; 

int register_org_join_skia_SkiaView(JNIEnv *env); 

        const JNINativeMethod* gMethods, int numMethods) { 

    jclass clazz; 

    MY_LOGI("Registering %s natives\n", className); 

    clazz = env-&gt;FindClass(className); 

    if (clazz == NULL) { 

        MY_LOGE("Native registration unable to find class '%s'\n", className); 

        return JNI_ERR; 

    if (env-&gt;RegisterNatives(clazz, gMethods, numMethods) &lt; 0) { 

        MY_LOGE("RegisterNatives failed for '%s'\n", className); 

    return JNI_OK; 

jint JNI_OnLoad(JavaVM* vm, void* reserved) { 

    JNIEnv* env = NULL; 

    jint result = JNI_ERR; 

    if (vm-&gt;GetEnv((void**) &amp;env, JNI_VERSION_1_4) != JNI_OK) { 

        MY_LOGE("GetEnv failed!"); 

        return result; 

    MY_LOGI("loading . . ."); 

    if(register_org_join_skia_SkiaView(env) != JNI_OK) { 

        MY_LOGE("can't load org_join_skia_SkiaView"); 

        goto end; 

    /** 

     * register others 

     */ 

    MY_LOGI("loaded"); 

    result = JNI_VERSION_1_4; 

end: 

    return result; 

<b>3</b><b>)运行效果</b>

<a href="http://blog.51cto.com/attachment/201208/090150569.png" target="_blank"></a>

<b>三、</b><b>Cygwin</b><b>问题</b>

         使用Cygwin时可能遇到的问题,之前都没提到过,现在补上==。

1)make 3.81 bug - error: multiple target patterns. Stop.

         下载http://www.cmake.org/files/cygwin/make.exe替换原来的make.exe

2)添加当前工程下的头文件和库文件

         添加include路径:project-&gt;properties-&gt;c/c++ build-&gt;settings-&gt;cygwin c compiler-&gt;includes-&gt;include paths-&gt;"${workspace_loc:/${ProjName}}"

         添加链接库:同上,在cygwin c linker-&gt;libraries下添加。

3)cygwin warning: MS-DOS style path detected:...

         添加环境变量CYGWIN=nodosfilewarning,可取消报警。

<b>四、后记</b>

         附件工程!

     本文转自winorlose2000 51CTO博客,原文链接:http://blog.51cto.com/vaero/790602,如需转载请自行联系原作者

继续阅读