android之 JNI端获取并操作Surface
前一段时间研究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();
就显示出来了。