2025-02-10

前一段時間研究android, 在jni端操作surface遇到麻煩,主要是C++基礎太差,Surface.cpp讀瞭n遍,也仿照網上查到的資料,試圖從Java端傳遞Surface,然後jni端進行操作。卻總是遇到各種各樣的異常,前前後後卡住瞭7天,最後終於解決瞭,放出這個方法,總會對某些朋友有幫助。

  其實不是原創的,隻是,網上有1000篇帖子,有999篇都講的同一種方法,但在我這裡卻偏偏成功不瞭。終於那天偶然看到一篇e文的帖子,是有人分析瞭 havlenapetr 的libjnivideo.so, 然後放出瞭ta使用的方法,原來想當簡單:


static android::sp<android::Surface> native_surface;

static android::Surface* getNativeSurface(JNIEnv* env, jobject jsurface, jint version)
{
    jclass clazz = env->FindClass("android/view/Surface");
    jfieldID field_surface;
    if(version <=8)
    {
        field_surface = env->GetFieldID(clazz, "mSurface", "I");
    }
    else
        field_surface = env->GetFieldID(clazz, ANDROID_VIEW_SURFACE_JNI_ID, "I");

    if (field_surface == NULL)
    {
        return NULL;
    }
    return (android::Surface *) env->GetIntField(jsurface, field_surface);
}

int setSurface(JNIEnv *env, jobject jsurface, jint version)
{
    native_surface = getNativeSurface(env, jsurface, version);

    if(android::Surface::isValid(native_surface))
    {
        __android_log_print(ANDROID_LOG_INFO, "libjni", "native_surface is valid");
        return 1;
    }
    else
        __android_log_print(ANDROID_LOG_ERROR, "libjni", "native_surface is invalid");

    return 0;
}

  jsurface就是從Java端傳遞過來的,然後這裡的 native_surface,就是我們想要的native surface瞭。為什麼要 傳遞個version? 因為 android2.2以上的版本,android.view.Surface裡面沒有“mSurface"瞭,而是用瞭一個常量 ANDROID_VIEW_SURFACE_JNI_ID, 區分下版本就行瞭。

  然後又發現jni端操作surface也是相當簡單,至少顯示圖像之類的很容易:

static android::Surface::SurfaceInfo info;
static android::Region dirtyRegion;

做下初始化:

  dirtyRegion.set(android::Rect(0x3FFF, 0x3FFF));

然後

  native_surface->lock(&info, &dirtyRegion, true);

  memcpy(info.bits, buf, bufSize);

  native_surface->unlockAndPost();

就顯示出來瞭。

作者:ljplum

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *