<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 && $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->C/C++ General->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 <GraphicsJNI.h>
#include <SkCanvas.h>
#include <SkPaint.h>
#include <SkRect.h>
#include <SkColor.h>
#include <SkTypes.h>
#include <SkGraphics.h>
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->save();
canv->translate(100, 100);
drawFlag(canv);
canv->restore();
MY_LOGI("==c method end==");
/** 画旗帜 */
static void drawFlag(SkCanvas* canv) {
SkPaint* paint = new SkPaint();
paint->setFlags(paint->kAntiAlias_Flag);
SkRect* rect = new SkRect();
rect->set(0, 0, 200, 100);
paint->setColor(SK_ColorRED);
canv->drawRect(*rect, *paint);
paint->setColor(SK_ColorGRAY);
paint->setStrokeWidth(10);
canv->drawLine(5, 100, 5, 300, *paint);
paint->setTextSize(30);
paint->setColor(SK_ColorBLUE);
paint->setTextAlign(paint->kCenter_Align);
const char* text = "Hello World";
canv->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 <jni.h>
#include <utils/Log.h>
#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 <stdlib.h>
int register_org_join_skia_SkiaView(JNIEnv *env);
const JNINativeMethod* gMethods, int numMethods) {
jclass clazz;
MY_LOGI("Registering %s natives\n", className);
clazz = env->FindClass(className);
if (clazz == NULL) {
MY_LOGE("Native registration unable to find class '%s'\n", className);
return JNI_ERR;
if (env->RegisterNatives(clazz, gMethods, numMethods) < 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->GetEnv((void**) &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->properties->c/c++ build->settings->cygwin c compiler->includes->include paths->"${workspace_loc:/${ProjName}}"
添加链接库:同上,在cygwin c linker->libraries下添加。
3)cygwin warning: MS-DOS style path detected:...
添加环境变量CYGWIN=nodosfilewarning,可取消报警。
<b>四、后记</b>
附件工程!
本文转自winorlose2000 51CTO博客,原文链接:http://blog.51cto.com/vaero/790602,如需转载请自行联系原作者