示例代码在:
frameworks\base\services\surfaceflinger\tests\screencap\screencap.cpp
- /*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include <utils/Log.h>
- #include <binder/IPCThreadState.h>
- #include <binder/ProcessState.h>
- #include <binder/IServiceManager.h>
- #include <binder/IMemory.h>
- #include <surfaceflinger/ISurfaceComposer.h>
- #include <SkImageEncoder.h>
- #include <SkBitmap.h>
- using namespace android;
- int main(int argc, char** argv)
- {
- if (argc != 2) {
- printf("usage: %s path\n", argv[0]);
- exit(0);
- }
- const String16 name("SurfaceFlinger");
- sp<ISurfaceComposer> composer;
- getService(name, &composer);
- sp<IMemoryHeap> heap;
- uint32_t w, h;
- PixelFormat f;
- status_t err = composer->captureScreen(0, &heap, &w, &h, &f, 0, 0);
- if (err != NO_ERROR) {
- fprintf(stderr, "screen capture failed: %s\n", strerror(-err));
- exit(0);
- }
- printf("screen capture success: w=%u, h=%u, pixels=%p\n",
- w, h, heap->getBase());
- printf("saving file as PNG in %s ...\n", argv[1]);
- SkBitmap b;
- b.setConfig(SkBitmap::kARGB_8888_Config, w, h);
- b.setPixels(heap->getBase());
- SkImageEncoder::EncodeFile(argv[1], b,
- SkImageEncoder::kPNG_Type, SkImageEncoder::kDefaultQuality);
- return 0;
- }
编译后生成 /system/bin/test-screencap
测试时终端输入 test-screencap /mnt/sdcard/scapxx.png
可以看到SD卡生成截屏文件scapxx.png,默认大小为屏幕分辨率
如果想把这个功能写到自己的应用里
写个JNI,参考上面代码即可,但记得权限声明
- <span style="font-size:24px;"><uses-permission android:name="android.permission.READ_FRAME_BUFFER" /></span>
贴出JNI代码,或资源下载地址:http://download.youkuaiyun.com/detail/zmyde2010/3835127
jni/com_android_ScreenCap_ScreenCapNative.cpp
- /*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #define LOG_TAG "ScreenCapNative-JNI"
- //#define LOG_NDEBUG 0
- #include "JNIHelp.h"
- #include "jni.h"
- #include <utils/Log.h>
- #include <binder/IPCThreadState.h>
- #include <binder/ProcessState.h>
- #include <binder/IServiceManager.h>
- #include <binder/IMemory.h>
- #include <surfaceflinger/ISurfaceComposer.h>
- #include <SkImageEncoder.h>
- #include <SkBitmap.h>
- namespace android {
- static void android_ScreenCap_ScreenCapNative_nativeCaptureScreen(JNIEnv* env,
- jobject obj, jstring file)
- {
- const char *file_path = env->GetStringUTFChars(file, NULL);
- const String16 name("SurfaceFlinger");
- sp<ISurfaceComposer> composer;
- getService(name, &composer);
- sp<IMemoryHeap> heap;
- uint32_t w, h;
- PixelFormat f;
- status_t err = composer->captureScreen(0, &heap, &w, &h, &f, 0, 0);
- if (err != NO_ERROR) {
- LOGE("screen capture failed: %s\n", strerror(-err));
- exit(0);
- }
- LOGD("screen capture success: w=%u, h=%u, pixels=%p\n",
- w, h, heap->getBase());
- LOGD("saving file as PNG in %s ...\n", file_path);
- SkBitmap b;
- b.setConfig(SkBitmap::kARGB_8888_Config, w, h);
- b.setPixels(heap->getBase());
- SkImageEncoder::EncodeFile(file_path, b,
- SkImageEncoder::kPNG_Type, SkImageEncoder::kDefaultQuality);
- }
- static JNINativeMethod gScreenCapNativeMethods[] = {
- /* name, signature, funcPtr */
- { "nativeCaptureScreen", "(Ljava/lang/String;)V",
- (void*) android_ScreenCap_ScreenCapNative_nativeCaptureScreen },
- };
- int register_android_ScreenCap_ScreenCapNative(JNIEnv* env) {
- int res = jniRegisterNativeMethods(env, "com/android/ScreenCap/ScreenCapNative",
- gScreenCapNativeMethods, NELEM(gScreenCapNativeMethods));
- LOG_FATAL_IF(res < 0, "Unable to register native methods.");
- return 0;
- }
- extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
- {
- JNIEnv* env = NULL;
- jint result = -1;
- if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
- LOGE("GetEnv failed!");
- return result;
- }
- LOG_ASSERT(env, "Could not retrieve the env!");
- register_android_ScreenCap_ScreenCapNative(env);
- return JNI_VERSION_1_4;
- }
- } /* namespace android */
jni/Android.mk
- LOCAL_PATH:= $(call my-dir)
- include $(CLEAR_VARS)
- LOCAL_SRC_FILES := com_android_ScreenCap_ScreenCapNative.cpp
- LOCAL_C_INCLUDES += \
- $(JNI_H_INCLUDE)
- LOCAL_SHARED_LIBRARIES := \
- libnativehelper \
- libcutils \
- libutils \
- libbinder \
- libskia \
- libui \
- libsurfaceflinger_client
- LOCAL_C_INCLUDES += \
- external/skia/include/core \
- external/skia/include/effects \
- external/skia/include/images \
- external/skia/src/ports \
- external/skia/include/utils
- LOCAL_MODULE:= libscreencapjni
- LOCAL_MODULE_TAGS := optional
- LOCAL_PRELINK_MODULE := false
- include $(BUILD_SHARED_LIBRARY)
看到有人问Java怎么调用JNI,贴出例子:
src/com/android/ScreenCap/ScreenCapNative.java
- /* zmyde2010@csdn */
- package com.android.ScreenCap;
- import java.io.File;
- import android.os.Environment;
- public class ScreenCapNative {
- static {
- System.loadLibrary("screencapjni");
- };
- private native static void nativeCaptureScreen(String file);
- public static String startCaptureScreen() {
- String file_name = getUniqueFileName();
- if (file_name != null) {
- nativeCaptureScreen(file_name);
- }
- return file_name;
- }
- private static String getUniqueFileName() {
- File file = null;
- if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- file = createUniqueFile(Environment.getExternalStorageDirectory(),
- "ScreenCap.PNG");
- } else if (Environment.getInternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- file = createUniqueFile(Environment.getInternalStorageDirectory(),
- "ScreenCap.PNG");
- }
- return (file != null) ? file.getAbsolutePath() : null;
- }
- private static File createUniqueFile(File directory, String filename) {
- File file = new File(directory, filename);
- if (!file.exists()) {
- return file;
- }
- // Get the extension of the file, if any.
- int index = filename.lastIndexOf('.');
- String format;
- if (index != -1) {
- String name = filename.substring(0, index);
- String extension = filename.substring(index);
- format = name + "-%d" + extension;
- }
- else {
- format = filename + "-%d.PNG";
- }
- for (int i = 2; i < Integer.MAX_VALUE; i++) {
- file = new File(directory, String.format(format, i));
- if (!file.exists()) {
- return file;
- }
- }
- return null;
- }
- }
可以在你的Acitvity或Service里面调用 ScreenCapNative.startCaptureScreen();来截屏
4.0源码已经公布了,大家不要花时间研究2.3的截屏了
当然最好是系统级实现,响应某个组合键来截屏,像Android4.0
原文地址:http://blog.youkuaiyun.com/zmyde2010/article/details/6925498