截图介绍

Android的调试工具DDMS提供有截屏功能,很多软件也会有截屏功能,在做支付等安全类应用的时候,为了保证用户的资产和系统安全,往往会禁止应用内截屏,禁止之后,在此应用处于前台的情况下,截屏功能将不能使用,如下图所示

截图的原理

DDMS的实现方式

DDMS是通过adb调用设备端的adbd(ADB daemon)提供的framebuffer service进行截屏(源码在system/core/adb/framebuffer_service.c),在较早版本的Android中,framebuffer service通过直接读framebuffer 设备(/dev/graphics/fb0)来截屏,但是读framebuffer设备(/dev/graphics/fb0)的方式在某些使用硬件overlay显示的设备上可能无法截取到某些画面(例如video playback和camera preview画面)。

在较新版本的Android中,framebuffer service则调用截屏工具screencap来截屏。

screencap工具

screencap是Android原生自带的工具,是一个C写的可执行文件,在设备上的/system/bin/下面可以找到它,screencap截屏后可保存为PNG格式文件或RGB RAW文件。screencap的源码frameworks/base/cmds/screencap/,它调用SurfaceFlinger提供的截屏接口ScreenshotClient,其源码在frameworks/native/libs/gui/SurfaceComposerClient.cpp(该路径在不同版本的Android源码中可能略有差别),ScreenshotClient通过进程间通信调用SurfaceFlinger service的截屏功能,源码在frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp中的函数SurfaceFlinger::captureScreen。

SurfaceFlinger提供的上述截屏接口则可以完美截取任何屏幕画面,因此相对来说是Android上最正规最完善的截屏方法,使用起来也非常简单。

关于SurfaceFlinger和framebuffer的内容不再做赘述,因为描述起来非常复杂,不是本文的重点,有兴趣的同学可以参考相关资料学习。

截图的实现

shell命令实现

screencap 命令 用法如下screencap [-hp] [FILENAME] -h: this message -p: save the file as a png.If FILENAME ends with .png it will be saved as a png.If FILENAME is not given, the results will be printed to stdout.

如果文件名以.png结尾时,它将保存为png文件 如果文件名没有给出,则结果被会被输出到stdout

例如 以下命令会将屏幕截图保存在sd卡路径下,文件名为screen.png$ adb shell screencap -p /sdcard/screen.png

代码实现

截图工具类ScreenUtilspublic class ScreenUtils { private ScreenUtils() { /* cannot be instantiated */ throw new UnsupportedOperationException("cannot be instantiated"); } /** * 获得屏幕高度 * *@param context *@return */ public static int getScreenWidth(Context context) { WindowManager wm = (WindowManager) context .getSystemService(Context.WINDOW_SERVICE); DisplayMetrics outMetrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(outMetrics); return outMetrics.widthPixels; } /** * 获得屏幕宽度 * *@param context *@return */ public static int getScreenHeight(Context context) { WindowManager wm = (WindowManager) context .getSystemService(Context.WINDOW_SERVICE); DisplayMetrics outMetrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(outMetrics); return outMetrics.heightPixels; } /** * 获得状态栏的高度 * *@param context *@return */ public static int getStatusHeight(Context context) { int statusHeight = -1; try { Class> clazz = Class.forName("com.android.internal.R$dimen"); Object object = clazz.newInstance(); int height = Integer.parseInt(clazz.getField("status_bar_height") .get(object).toString()); statusHeight = context.getResources().getDimensionPixelSize(height); } catch (Exception e) { e.printStackTrace(); } return statusHeight; } /** * 获取当前屏幕截图,包含状态栏 * *@param activity *@return */ public static Bitmap snapShotWithStatusBar(Activity activity) { View view = activity.getWindow().getDecorView(); view.setDrawingCacheEnabled(true); view.buildDrawingCache(); Bitmap bmp = view.getDrawingCache(); int width = getScreenWidth(activity); int height = getScreenHeight(activity); Bitmap bp = null; bp = Bitmap.createBitmap(bmp, 0, 0, width, height); view.destroyDrawingCache(); return bp; } /** * 获取当前屏幕截图,不包含状态栏 * *@param activity *@return */ public static Bitmap snapShotWithoutStatusBar(Activity activity) { View view = activity.getWindow().getDecorView(); view.setDrawingCacheEnabled(true); view.buildDrawingCache(); Bitmap bmp = view.getDrawingCache(); Rect frame = new Rect(); activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame); int statusBarHeight = frame.top; int width = getScreenWidth(activity); int height = getScreenHeight(activity); Bitmap bp = null; bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height - statusBarHeight); view.destroyDrawingCache(); return bp; }}1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

1041

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

通过调用以上工具类的截图方法就可以拿到图片的bitmap然后就可以随心所欲的进行进一步操作了。

禁止截图的实现

禁止截图通过对window对象加标志位FLAG_SECURE实现,此标识位的注释如下,/** Window flag: treat the content of the window as secure, preventing * it from appearing in screenshots or from being viewed on non-secure * displays. * *

See {@link android.view.Display#FLAG_SECURE} for more details about * secure surfaces and secure displays. */ public static final int FLAG_SECURE = 0x00002000;

使用方式如下:@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE); }private void initializeScreenshotSecurity() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH &&TextSecurePreferences.isScreenSecurityEnabled(this)){getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);} else {getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);}}

本文转自 一点点征服 博客园博客,原文链接:http://www.cnblogs.com/ldq2016/p/6893815.html,如需转载请自行联系原作者

html禁止手机截屏,[置顶] Android 应用内禁止截屏功能的实现相关推荐

  1. android listview标题置顶,Android仿QQ左滑删除置顶ListView操作

    最近闲来无事,于是研究了一下qq的左滑删除效果,尝试着实现了一下,先上效果图: 大致思路原理: - 通过设置margin实现菜单的显示与隐藏 - 监听onTouchEvent,处理滑动事件 上代码 i ...

  2. [置顶] Android自定义控件 芝麻信用分雷达图

    [置顶] Android自定义控件 芝麻信用分雷达图 标签: android自定义雷达芝麻信用 2016-10-23 20:11  3548人阅读  评论(24)  收藏  举报   分类: 自定义控 ...

  3. android imageview 锯齿,[置顶] android 自定义圆角ImageView以及锯齿的处理

    看到很多人开发过程中要使用圆角图片时,解决方法有: 1.重新绘制一张图片 2.通过布局来配置 3.通过重写View来实现 其中1,2在这里就不讲了,重点讲讲方法三的实现. 实现一:通过截取画布一个圆形 ...

  4. android列表实现置顶,Android利用RecyclerView实现全选、置顶和拖拽功能示例

    Android利用RecyclerView实现全选.置顶和拖拽功能示例 发布时间:2020-08-23 16:26:42 来源:脚本之家 阅读:159 作者:爱开发 前言 今天给大家分享是如何在Rec ...

  5. ubuntu firefox不能播放MP4,ubuntu Firefox flash 浏览器全屏置顶

    ubuntu默认安装的Firefox是不能播放MP4的, sudo apt-get install gnome-mplayer ubuntu默认安装的Firefox是不能播放flash的, sudo ...

  6. [置顶] Android九环刀之RatingBar之评委请亮分

    九环刀          出自<碧血剑>山东盗首沙天广手下杀豹岗寨主.第七阵比兵刃,杀豹岗寨主提了一柄泼风九环刀上阵,威风凛凛,果然一战成功,把对方的手臂砍伤了. 今天我们学习如何利用An ...

  7. vue 页面不置顶问题(页面内操作、页面跳转后) - 集合篇

    文章目录 vue 页面内切换dom,页面跳转后 都不置顶? 一.页面内操作: 1.1 代码如下: 二.页面之间跳转: 2.1 代码截图 · 说明: 2.2 增加代码 · 示下: 三.拓展 · (直接置 ...

  8. [置顶]Android 面试题汇总

    MicrosoftInternetExplorer402DocumentNotSpecified7.8 磅Normal0 面试题基础储备 1.Activity相关 a.Activity的特点 1.可见 ...

  9. [置顶]android ListView包含Checkbox滑动时状态改变

    题外话: 在xamarin android的开发中基本上所有人都会遇到这个小小的坎,的确有点麻烦,当时我也折腾了好一半天,如果你能看到这篇博客,说明你和我当初也是一样的焦灼,如果你想解决掉这个小小的坎 ...

最新文章

  1. 大厂项目是如何死掉的?太过真实!
  2. Javascript教程:AngularJS的五个超酷特性
  3. Linux源码安装mysql 5.5.13 (cmake编译)
  4. 课程设计---约瑟夫环
  5. Multipart/form-data POST文件上传详解
  6. GXU - 7D - 区间求和 - 前缀和
  7. mysql加索引快很多
  8. python多线程编程(7):线程间通信
  9. 教师计算机培训心得体会范文,xx年教师计算机培训心得体会范文.doc
  10. 去年写的测试GDAL用法的一些函数
  11. gsm模块 java 录音_深入详解Android GSM驱动模块
  12. 查询优化器内核剖析第六篇:谈谈Join的顺序问题,纠正江湖偏方
  13. (2)安装配置开发工具-JsDroid引流脚本混合式开发技术系列教程By飞云脚本学院
  14. 细述微信浏览器打不开文件下载链接的几种解决方案
  15. 用CMSS指令提高串口群发短信的效率
  16. 大数据Spark(四十四):Structured Streaming概述
  17. Android关机充电打开log,Android关机log
  18. 华为“天才少年” DIY 生日礼物:四个月打造能缝葡萄的机械臂!
  19. 【PyG】图神经网络GAT代码自学
  20. windows 2008/2012(64位) IIS配置asp程序 500 - 内部服务器错误。您查找的资源存在问题,因而无法显示。

热门文章

  1. PHP设计模式系列 - 数据访问对象模式
  2. Android 蓝牙相关的广播
  3. 数组-去重、排序方法、json排序
  4. 使用汉文博士检索汉字
  5. RAC 中 ASM 实例名 与 节点的对应关系
  6. 对话框获取目录、文件路径
  7. Delphi 两种类的声明方法
  8. TZOJ 2999 Network(连通图割点数量)
  9. 如何优化myeclipse.
  10. sqlserver中的分页sql语句,不同于mysql中的limit,相当于top+top