本文基于android6.0。首先找到screencap在Android源码中的位置,若不清楚,可以通过在android目录下通过命令find . -namescreencap.cpp。本文直接给出路径/android/frameworks/base/cmds/screencap/screencap.cpp。入口函数为main,只要编译就可以直接使用。如果需要将数据传出来,需要利用socket,后面会更新,将当前屏幕信息实时传输到web端显示。(data->data(), data->size()是需求的数据和大小)。

screencap.cpp源码如下:

<pre name="code" class="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 <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>#include <linux/fb.h>
#include <sys/ioctl.h>
#include <sys/mman.h>#include <binder/ProcessState.h>#include <gui/SurfaceComposerClient.h>
#include <gui/ISurfaceComposer.h>#include <ui/DisplayInfo.h>
#include <ui/PixelFormat.h>// TODO: Fix Skia.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#include <SkImageEncoder.h>
#include <SkData.h>
#pragma GCC diagnostic popusing namespace android;static uint32_t DEFAULT_DISPLAY_ID = ISurfaceComposer::eDisplayIdMain;//eDisplayIdMain = 0static void usage(const char* pname)
{fprintf(stderr,"usage: %s [-hp] [-d display-id] [FILENAME]\n""   -h: this message\n""   -p: save the file as a png.\n""   -d: specify the display id to capture, default %d.\n""If FILENAME ends with .png it will be saved as a png.\n""If FILENAME is not given, the results will be printed to stdout.\n",pname, DEFAULT_DISPLAY_ID);
}static SkColorType flinger2skia(PixelFormat f)
{switch (f) {case PIXEL_FORMAT_RGB_565:return kRGB_565_SkColorType;default:return kN32_SkColorType;}
}static status_t vinfoToPixelFormat(const fb_var_screeninfo& vinfo,uint32_t* bytespp, uint32_t* f)
{switch (vinfo.bits_per_pixel) {case 16:*f = PIXEL_FORMAT_RGB_565;*bytespp = 2;break;case 24:*f = PIXEL_FORMAT_RGB_888;*bytespp = 3;break;case 32:// TODO: do better decoding of vinfo here*f = PIXEL_FORMAT_RGBX_8888;*bytespp = 4;break;default:return BAD_VALUE;}return NO_ERROR;
}static status_t notifyMediaScanner(const char* fileName) {String8 cmd("am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d file://");String8 fileUrl("\"");fileUrl.append(fileName);fileUrl.append("\"");cmd.append(fileName);cmd.append(" > /dev/null");int result = system(cmd.string());if (result < 0) {fprintf(stderr, "Unable to broadcast intent for media scanner.\n");return UNKNOWN_ERROR;}return NO_ERROR;
}int main(int argc, char** argv)
{//while(1){//创建ProcessState 当前进程属性,启动进程的线程池ProcessState::self()->startThreadPool();const char* pname = argv[0];bool png = false;int32_t displayId = DEFAULT_DISPLAY_ID;//DEFAULT_DISPLAY_ID = eDisplayIdMain = 0,int c;while ((c = getopt(argc, argv, "phd:")) != -1) {switch (c) {case 'p':png = true;break;case 'd':displayId = atoi(optarg);break;case '?':case 'h':usage(pname);return 1;}}argc -= optind;//optind = 1argv += optind;struct timeval tv;  //超时时间设置while(1){gettimeofday(&tv,NULL);ALOGE("tv.tv_sec = %ld ,tv.tv_usec = %ld\n", tv.tv_sec, tv.tv_usec);int fd = -1;const char* fn = NULL;if (argc == 0) {fd = dup(STDOUT_FILENO);//STDOUT_FILENO=1} else if (argc == 1) {fn = argv[0];fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0664);if (fd == -1) {fprintf(stderr, "Error opening file: %s (%s)\n", fn, strerror(errno));return 1;}const int len = strlen(fn);if (len >= 4 && 0 == strcmp(fn+len-4, ".png")) {png = true;}}if (fd == -1) {usage(pname);return 1;}
//------------------------------------------------------------------------------------    void const* mapbase = MAP_FAILED;ssize_t mapsize = -1;void const* base = NULL;uint32_t w, s, h, f;size_t size = 0;// Maps orientations from DisplayInfo to ISurfaceComposerstatic const uint32_t ORIENTATION_MAP[] = {ISurfaceComposer::eRotateNone, // 0 == DISPLAY_ORIENTATION_0ISurfaceComposer::eRotate270, // 1 == DISPLAY_ORIENTATION_90ISurfaceComposer::eRotate180, // 2 == DISPLAY_ORIENTATION_180ISurfaceComposer::eRotate90, // 3 == DISPLAY_ORIENTATION_270};
//------------------------------------------------------------------------------------ScreenshotClient screenshot;sp<IBinder> display = SurfaceComposerClient::getBuiltInDisplay(displayId);if (display == NULL) {fprintf(stderr, "Unable to get handle for display %d\n", displayId);return 1;}Vector<DisplayInfo> configs;SurfaceComposerClient::getDisplayConfigs(display, &configs);int activeConfig = SurfaceComposerClient::getActiveConfig(display);if (static_cast<size_t>(activeConfig) >= configs.size()) {fprintf(stderr, "Active config %d not inside configs (size %zu)\n",activeConfig, configs.size());return 1;}uint8_t displayOrientation = configs[activeConfig].orientation;uint32_t captureOrientation = ORIENTATION_MAP[displayOrientation];status_t result = screenshot.update(display, Rect(), 0, 0, 0, -1U,false, captureOrientation);if (result == NO_ERROR) {base = screenshot.getPixels();w = screenshot.getWidth();h = screenshot.getHeight();s = screenshot.getStride();f = screenshot.getFormat();size = screenshot.getSize();} else { const char* fbpath = "/dev/graphics/fb0";int fb = open(fbpath, O_RDONLY);if (fb >= 0) {struct fb_var_screeninfo vinfo;if (ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) == 0) {uint32_t bytespp;if (vinfoToPixelFormat(vinfo, &bytespp, &f) == NO_ERROR) {size_t offset = (vinfo.xoffset + vinfo.yoffset*vinfo.xres) * bytespp;w = vinfo.xres;h = vinfo.yres;s = vinfo.xres;size = w*h*bytespp;mapsize = offset + size;mapbase = mmap(0, mapsize, PROT_READ, MAP_PRIVATE, fb, 0);if (mapbase != MAP_FAILED) {base = (void const *)((char const *)mapbase + offset);}}}close(fb);}}if (base != NULL) {if (png) {const SkImageInfo info = SkImageInfo::Make(w, h, flinger2skia(f), kPremul_SkAlphaType);SkAutoTUnref<SkData> data(SkImageEncoder::EncodeData(info, base, s*bytesPerPixel(f),SkImageEncoder::kJPEG_Type, SkImageEncoder::kDefaultQuality));if (data.get()) {<span style="color:#FF0000;">FILE *fp;  if((fp=fopen("/data/audioBuffer.txt","a+"))==NULL) {  ALOGE("00000000000000000\n");   }  else {         fwrite(data->data(),data->size(),1, fp);ALOGE("data->size() = %zu\n",data->size()); } fclose(fp);</span>write(fd, data->data(), data->size()); //data->data(), data->size()可以将数据传出去实时录制当前屏幕}if (fn != NULL) {notifyMediaScanner(fn);}} else {write(fd, &w, 4);write(fd, &h, 4);write(fd, &f, 4);size_t Bpp = bytesPerPixel(f);for (size_t y=0 ; y<h ; y++) {write(fd, base, w*Bpp);base = (void *)((char *)base + s*Bpp);}}}close(fd);if (mapbase != MAP_FAILED) {munmap((void *)mapbase, mapsize);}
}return 0;
}

修改后进行编译:

source build/envsetup.sh

lunch 6

make -j8

运行模拟器:emulator -sdcard /home/bruceking90/Documents/workplace/sdcard.img &

之后进行截屏:adb shell screencap -p | sed 's/\r$//' > screen.png

此命令可以直接将png存放在android即当前目录下。

或者adb shell screencap -p /sdcard/screen.png

android后台获取当前屏幕截图(screencap.cpp修改)相关推荐

  1. android后台获取view,android – 如何获取当前显示在AdapterView中的项目?

    实现OnScrollListener 06000 并在listView中设置OnScrollListener listView.setOnScrollListener(NewsCategoryDC.t ...

  2. android后台获取view,如何获取AdapterView中当前显示的项目?

    实现OnScrollListener public class NewsCategoryDC extends Activity implements OnScrollListener { 并在list ...

  3. android后台截屏实现(2)--screencap源码修改

    首先找到screencap类在Android源码中的位置,/442/frameworks/base/cmds/screencap/screencap.cpp. 源码如下: [cpp] view pla ...

  4. android后台截屏实现(3)--编译screencap

    修改好之后就要编译了,screencap的编译是要在源码环境中进行的. 将修改后的screencap.cpp文件替换源码中的原始文件,然后修改screencap的Android.mk文件,修改后的文件 ...

  5. Android获取当前屏幕截图,简单粗暴!

    获取当前屏幕截图的Bitmap对象,然后就可以拿去做你想做的事情,代码很简单. public static Bitmap captureScreen(Activity activity) {activ ...

  6. android时间同步服务ipv6,Android O : DNS列表获取及IPv4/IPv6优先级修改

    一.Android应用获取有线网络DNS列表 /*** 获取DNS列表*/ private ListgetDnsList() { List dnsList = newArrayList();if (t ...

  7. Android开发——后台获取用户点击位置坐标(可获取用户支付宝密码)

    1. getevent命令 我们首先是根据adb shell getevent命令获取到被点击位置的信息. 这里要说明的是,不同的手机手机获得的点击输出是不一样的.以我的真机为例,输出如下 本文原创, ...

  8. Android后台杀死系列之三:LowMemoryKiller原理(4.3-6.0)

    本篇是Android后台杀死系列的第三篇,前面两篇已经对后台杀死注意事项,杀死恢复机制做了分析,本篇主要讲解的是Android后台杀死原理.相对于后台杀死恢复,LowMemoryKiller原理相对简 ...

  9. Android 后台杀死及恢复的机制

    App在后台久置后,再次从桌面或最近的任务列表唤醒时经常会发生崩溃,这往往是App在后台被系统杀死,再次恢复的时候遇到了问题,而在使用FragmentActivity+Fragment的时候,经常会遇 ...

  10. android apk获取root权限执行相应的操作 demo调试

    在apk中,有时候需要root权限,例如通过apk更新系统库等system的文件等,避免升级固件,或者在apk中需要直接访问某些设备等.下面是在apk中获取root权限的方法,前提是设备已经root过 ...

最新文章

  1. Java 数组转型和范型
  2. 电脑看书软件_能全平台阅读的图书软件,是kindle? No!大公司低调出品
  3. windows连接远程Hadoop/Spark
  4. Java Spring注解实现分析之@requestMapping工作原理
  5. 电脑技巧:Win10自带存储感知功能给电脑磁盘瘦身
  6. OpenCV掩码、blending、改变对比度和亮度、随机发生器和绘图
  7. 力扣--19删除链表中的倒数第n个节点
  8. ubuntu查看默认python版本_更改Ubuntu默认python版本的两种方法python- Anaconda
  9. linux系统之IP、TCP封包格式
  10. 关于代理服务器与NAT
  11. IDEA远程调试Java代码
  12. Costech A17M23SWB MTo
  13. 实验4 数据查询-mysql_实验四 数据库查询
  14. Arduino:设置ADC参考电压
  15. 大数据之Hadoop3.x 运行环境搭建(手把手搭建集群)
  16. 教你用Python画一棵圣诞树
  17. bzoj 2299(裴蜀定理)
  18. 隔行的BT.656标准信号
  19. Scrapy框架的使用之Scrapy爬取新浪微博
  20. 报告模板 仿 LaTeX beamer主题: Metropolis Powerpoint版本

热门文章

  1. 太极软件qn的代码_多版本QQ内置qn、qx模块
  2. 用CSS实现花里胡哨的按钮切换效果
  3. mescroll.js 上拉刷新 下拉加载
  4. AE拓展工具丨自定义工具栏 快速嵌入表达式
  5. SQL 基础教程 练习题 Chapter 1
  6. 针对Linux学习,值得阅读的五本书籍,不看可能错失机会
  7. Teorex Inpaint 6.0 简体中文最新破解版(自动去除图片上的水印)
  8. 【高速PCB电路设计】8.DDR模块设计实战
  9. 贝叶斯公式的理解——机器学习算法(一)
  10. 艾宾浩斯英语单词记忆表格生成器