type
status
date
slug
summary
tags
category
icon
password

ANativeWindow是什么

ANativeWindow是C/C++中定义的一个结构体,等同于Java中的Surface.
Android NDK中可以访问到ANativeWindow.
ANativeWindow中存放像素信息的结构是:ANativeWindow_Buffer:
typedef struct ANativeWindow_Buffer { /// The number of pixels that are shown horizontally. int32_t width; /// The number of pixels that are shown vertically. int32_t height; /// The number of *pixels* that a line in the buffer takes in /// memory. This may be >= width. int32_t stride; /// The format of the buffer. One of AHardwareBuffer_Format. int32_t format; /// The actual bits. void* bits; /// Do not touch. uint32_t reserved[6]; } ANativeWindow_Buffer;

主要API

  • 获取与surface对应的ANativeWindow
    • ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface);
  • 保持/释放ANativeWindow对象的引用
    • void ANativeWindow_acquire(ANativeWindow* window); void ANativeWindow_release(ANativeWindow* window);
  • 向buffer中写入数据并提交
    • int32_t ANativeWindow_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds); // 这之间的代码可以执行一些向buffer中写入数据的操作 int32_t ANativeWindow_unlockAndPost(ANativeWindow* window);
  • 获取Window Surface的信息:宽/高/像素格式
    • int32_t ANativeWindow_getWidth(ANativeWindow* window); int32_t ANativeWindow_getHeight(ANativeWindow* window); int32_t ANativeWindow_getFormat(ANativeWindow* window);
      像素格式定义在AHARDWAREBUFFER_FORMAT_*
  • 改变Window Buffer的格式和大小
    • int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window, int32_t width, int32_t height, int32_t format);

一般的流程

  1. 通过ANativeWindow_fromSurface获取与Surface对应的ANativeWindow对象
  1. ANativeWindow_setBuffersGeometry设置buffer的尺寸和格式
  1. ANativeWindow_acquire获取引用对象
  1. 利用ANativeWindow_lock/ANativeWindow_unlockAndPost与之间的绘制代码绘制图像
  1. ANativeWindow_release释放引用.

一个简单的例子

写个简单的例子:利用ANativeWindow绘制一个灰色的背景.
  • C++代码
    • #include <jni.h> #include <string> #include <android/native_window.h> #include <android/native_window_jni.h> void drawColor(JNIEnv *env,jobject obj,jobject surface, jint colorARGB) { int alpha = colorARGB >> 24 & 0xFF; int red = colorARGB >> 16 & 0xFF; int green = colorARGB >> 8 & 0xFF; int blue = colorARGB & 0xFF; int colorABGR = alpha << 24 | (blue << 16) | (green << 8) | red; ANativeWindow *window = ANativeWindow_fromSurface(env,surface); int32_t result = ANativeWindow_setBuffersGeometry(window,640,640,AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM); if (result < 0){ ANativeWindow_release(window); window = nullptr; return; } ANativeWindow_acquire(window); ANativeWindow_Buffer buffer; if (ANativeWindow_lock(window,&buffer, nullptr) < 0){ ANativeWindow_release(window); window = nullptr; return; } auto *line = (uint32_t *) buffer.bits; for (int y = 0; y < buffer.height; ++y) { for (int x = 0; x < buffer.width; ++x) { line[x] = colorABGR; } line += buffer.stride; } if (ANativeWindow_unlockAndPost(window) < 0){ return; } ANativeWindow_release(window); } extern "C" JNIEXPORT void JNICALL Java_com_jiangkang_androiddemos_MainActivity_drawColor(JNIEnv *env, jobject thiz, jobject surface, jint color) { drawColor(env,thiz,surface,color); }
  • Activity代码
    • import android.graphics.Color import android.os.Bundle import android.view.Surface import android.view.SurfaceHolder import androidx.appcompat.app.AppCompatActivity import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) surface_view.holder.addCallback(object : SurfaceHolder.Callback2 { override fun surfaceRedrawNeeded(holder: SurfaceHolder?) { } override fun surfaceChanged( holder: SurfaceHolder?, format: Int, width: Int, height: Int ) { } override fun surfaceDestroyed(holder: SurfaceHolder?) { } override fun surfaceCreated(holder: SurfaceHolder?) { holder?.let { drawColor(it.surface, Color.GRAY) } } }) } external fun drawColor(surface: Surface, color: Int) companion object { init { System.loadLibrary("native-lib") } } }

总结

  1. Native层中的ANativeWindow对应Java层中的Surface,因此可以利用SurfaceView + ANativeWindow,用C++代码绘制屏幕;
  1. 在图像/视频处理中会利用到ANativeWindow,也可以与EGL,FFMPEG等结合使用
  1. Flutter Engine中正是通过 ANativeWindow才将Dart中的UI与Android中UI联系到一起的.
Android中的Deep Link与 APP LinkAndroid中的存储路径
姜康
姜康
一个软件工程师
公告
type
status
date
slug
summary
tags
category
icon
password
🎉博客网站重新制作了🎉
👏欢迎更新体验👏