android 直接在屏幕上繪圖

android 的application 都是有窗口系統的,會把各種事件給阻攔掉.但是,用c++寫的程序是直接在linux上運行的,並沒有窗口這一概念,所以可以向鼠標一樣,只繪製圖像而不響應任何窗口時間.

具體實現是通過SurfaceComposerClient,這個類相當於surfaceflinger的代理,可以創建一個顯示圖像的surface. 

注意,不同系統的接口可能不一樣.若有問題,可以參考一下本系統中frameworks/base/service/input/SpriteController.cpp中的doUpdateSprites()函數.這個函數是顯示鼠標的最主核心的函數.

#include<SkImageDecoder.h>
#include <utils/RefBase.h>
#include <utils/Looper.h>
#include <gui/SurfaceComposerClient.h>
#include <gui/Surface.h>
#include <SkBitmap.h>
#include <SkCanvas.h>
#include <SkColor.h>
#include <SkPaint.h>
#include <SkXfermode.h>
#include <android/native_window.h>
#include <unistd.h>
#include <cutils/log.h>
#include <ui/DisplayInfo.h>

#define LOG_TAG "zhy"

using namespace android;
int main()
{
    SkBitmap bitmap;
    SkImageDecoder::DecodeFile("/system/data/test.png", &bitmap);
    sp<SurfaceComposerClient> pSurfaceComposerClient = new SurfaceComposerClient();
    int32_t width = bitmap.height();
    int32_t height = bitmap.width();
    ALOGI("width= %d \n", width);
    ALOGI("height= %d \n", height);
    sp<SurfaceControl> surfaceControl = pSurfaceComposerClient->createSurface(
        String8("test"), width, height, PIXEL_FORMAT_RGBA_8888,
        ISurfaceComposerClient::eHidden);
    
    if (surfaceControl == NULL || !surfaceControl->isValid()) {
        ALOGE("Error creating sprite surface.");
        return -1;
    }
    sp<Surface> surface = surfaceControl->getSurface();
    ANativeWindow_Buffer outBuffer;
    status_t status = surface->lock(&outBuffer, NULL);
    if (status) {
                ALOGE("Error %d locking sprite surface before drawing.", status);
    } else {
        SkBitmap surfaceBitmap;
        ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
        surfaceBitmap.setConfig(SkBitmap::kARGB_8888_Config,
                outBuffer.width, outBuffer.height, bpr);
        surfaceBitmap.setPixels(outBuffer.bits);
        SkCanvas surfaceCanvas(surfaceBitmap);
        SkPaint paint;
        paint.setXfermodeMode(SkXfermode::kSrc_Mode);
        surfaceCanvas.drawBitmap(bitmap, 0, 0, &paint);
        if (outBuffer.width > uint32_t(bitmap.width())) {
            paint.setColor(0); // transparent fill color
            surfaceCanvas.drawRectCoords(bitmap.width(), 0,
                    outBuffer.width, bitmap.height(), paint);
        }
        if (outBuffer.height > uint32_t(bitmap.height())) {
            paint.setColor(0); // transparent fill color
            surfaceCanvas.drawRectCoords(0, bitmap.height(),
                    outBuffer.width, outBuffer.height, paint);
        }
        status = surface->unlockAndPost();
        if (status) {
            ALOGE("Error %d unlocking and posting sprite surface after drawing.", status);
        }
    }
   
    int x = 0, y = 0;
    SurfaceComposerClient::openGlobalTransaction();
    //surfaceControl->setAlpha(1.0f);
    surfaceControl->setLayer(100000);
    //surfaceControl->setMatrix(1.0, 1.0, 1.0, 1.0);
    SurfaceComposerClient::closeGlobalTransaction();
    while(true){
        ALOGI("openGlobalTransaction \n");
        SurfaceComposerClient::openGlobalTransaction();
        surfaceControl->setPosition(x, y);
        x = (x+10) %1920;
        y = (y+10) %1280;
             static bool isShow = false;
             if(!isShow){
                 surfaceControl->show();
                 isShow = true;
             }
          ALOGI("closeGlobalTransaction \n");
        SurfaceComposerClient::closeGlobalTransaction();
           sleep(1);
           
    }
    return 0;
}

最簡單的 surface 創建 

SurfaceTest.cpp

#include <cutils/memory.h>
 
#include <utils/Log.h>
 
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <android/native_window.h>
 
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
 
using namespace android;
 
 
int main()
{
    // set up the thread-pool
    sp<ProcessState> proc(ProcessState::self());
    ProcessState::self()->startThreadPool();
 
    // create a client to surfaceflinger
    sp<SurfaceComposerClient> client = new SurfaceComposerClient();
    
    sp<SurfaceControl> surfaceControl = client->createSurface(String8("resize"),
            160, 240, PIXEL_FORMAT_RGB_565, 0);
 
    sp<Surface> surface = surfaceControl->getSurface();
 
    SurfaceComposerClient::openGlobalTransaction();
    surfaceControl->setLayer(100000);
    SurfaceComposerClient::closeGlobalTransaction();
 
    ANativeWindow_Buffer outBuffer;
    surface->lock(&outBuffer, NULL);
    ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
    android_memset16((uint16_t*)outBuffer.bits, 0xF800, bpr*outBuffer.height);
    surface->unlockAndPost();
 
    surface->lock(&outBuffer,NULL);
    android_memset16((uint16_t*)outBuffer.bits, 0x07E0, bpr*outBuffer.height);
    surface->unlockAndPost();
 
    SurfaceComposerClient::openGlobalTransaction();
    surfaceControl->setSize(320, 240);
    SurfaceComposerClient::closeGlobalTransaction();
 
    
    IPCThreadState::self()->joinThreadPool();
    
    return 0;
}

Android.mk

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
 
LOCAL_SRC_FILES:= \
	SurfaceTest.cpp
 
LOCAL_SHARED_LIBRARIES := \
	libcutils \
	libutils \
    libui \
    libgui \
	libbinder
 
LOCAL_MODULE:= SurfaceTest
 
LOCAL_MODULE_TAGS := tests
 
include $(BUILD_EXECUTABLE)
 

複製自

https://www.cnblogs.com/Jaunty/p/3753322.html

https://blog.csdn.net/qq_34738528/article/details/103296115

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章