Android Native 绘图方法

大部分 Android 应用程式,应该都是用 Java Code 完成所有的工作,包括绘图。但,有些情况下,你会希望绘图有更快的反应;例如 game ,这时 native code 可能是一个选择。

在 Android 上,有一个 graphic engine ,称为 Skia 。 Skia 的功能约等于 Cairo ,功能上相似,但 Skia 的支援没 Cairo 广。其实, Android 的 Java Code 都是透过 Skia 进行绘图,而 Skia 主要的 class type 是 SkCanvas ,所的有绘图功能都建构在这个 class 上。因此,如果我们能在 native code 取得 Android 所建立的 SkCanvas ,能直接使用 Skia 对画面做输出。

在 Android 的 UI 设计裡,每一个 UI component 都是一个 view ;例如: button 、 label 等等,全是 view 。当 Android 要画一个 view 时,会呼叫 view 的 onDraw() 画出 component 的外观。而 Android 会将一个 android.graphics.Canvas type 的物件,当成参数给 onDraw() 。 onDraw() 就在这个 canvas 上输出 component 的外观,例如画一个 button 。这个 canvas 其实就对映到一个 SkCanvas ,我们只要在这个 canvas 上作画,就等于画到画面上的一个区域。

Native code

Android 是透过 JNI 呼叫 native code ,于是我们在 Java side 定义了一个 View ,使该 View 透过 JNI 把 canvas 传送给我们的 native code ,以便在 native code 裡绘图。

#!cpp
package com.example;
import android.view.View;
import android.graphics.Canvas;

class myview extends View {
    public void onDraw(Canvas canvas) {
        nativedraw(canvas);
    }
    native void nativedraw(Canvas canvas);
    static {
        System.loadLibrary("mynative");
    }
}

在个这 class 裡,我们将 canvas 透过 JNI 传给 native code ,接下来我们定义 JNI 的 native function 。

#!cpp
#include <SkCanvas.h>

extern "C" {

#include <jni.h>

void
Java_com_example_myview_nativedraw(JNIEnv *env, jobject thiz, jobject obj) {
    jclass cls;
    jfieldID fid;
    SkCanvas *canvas;
   
    cls = env->GetObjectClass(obj);
    fid = env->GetFieldID(cls, "mNativeCanvas", "I");
    canvas = (SkCanvas *)env->GetIntField(obj, fid);
    /* ..... draw on canvas .... */
}

}

相关推荐