[置顶] Android 应用内禁止截屏功能的实现
截图介绍
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
代码实现
截图工具类ScreenUtils
public 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
- 104
- 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
- 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.
*
* <p>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);
}
}
[置顶] Android 应用内禁止截屏功能的实现的更多相关文章
- Android应用内 代码截屏(获取View快照)和 禁止截屏
1. 应用内的代码截屏(获取View的快照) Android的View类中提供了获取控件绘制缓存的方法,这种截屏的方式仅限于应用内自己的Activity界面,不需要任何权限,严格来说该方法不属于截屏, ...
- react native 中实现个别页面禁止截屏
这里主要用到了原生模块,下面贴出FlagSecureModule.java的代码 package com.studyproj.flagsecure; import android.util.Log; ...
- 手把手教你实现Android真机远程截屏
先看效果演示 接下来手把手教你实现这样的效果. minicap简介 minicap是一个可以远程获取android屏幕画面的开源库,它在低版本的Android系统上采用截屏的方式获取画面,在Andro ...
- Android自己定义截屏功能,相似QQ截屏
由于公司业务需求 须要对一个屏幕进行截屏.但自带的截屏功能是远远不够项目的功能需求 ,我们是做一个画板软件 .须要的像QQ那样截屏之后 ,能够看到我们自己定义的工具.有画笔,button等等 .and ...
- android4.3 截屏功能的尝试与失败分析
1.背景 上一篇讲了在源码中捕获到了android手机的截屏函数(同时按下电源键与音量减,详情http://blog.csdn.net/buptgshengod/article/details/199 ...
- PhantomJS linux系统下安装步骤及使用方法(网页截屏功能)
PhantomJS 是一个基于 WebKit 的服务器端 JavaScript API.它全面支持web而不需浏览器支持,其快速,原生支持各种Web标准: DOM 处理, CSS 选择器, JSON, ...
- Atitit截屏功能的设计解决方案
Atitit截屏功能的设计解决方案 自己实现.... 使用快捷键.. 弹出自己的win,,背景是屏幕快照 点击鼠标光标变成十字状态 出现截屏窗口调整截屏窗口位置与大小 释放鼠标,三个btn,, 复制 ...
- iOS截屏功能
代码: - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. // ...
- 使用laravel框架与phantomjs实现截屏功能
在网上看到的关于phantomjs实现截屏功能很多都是与node结合在一起使用,并需要输入命令才能执行.因此我想要实现输入网址即可截屏并输出图片的功能.示例:http://120.77.171.182 ...
随机推荐
- Linux学习-逻辑滚动条管理员 (Logical Volume Manager)
LVM 可以整合多个实体 partition 在一起, 让这些 partitions 看起来就像是一个磁盘一样!而且,还可以在未来新增或移除其他的实 体 partition 到这个 LVM 管理的磁盘 ...
- 安装go 1.5 & 部署
https://storage.googleapis.com/golang/go1.5.linux-amd64.tar.gz tar -C /usr/local -xzf go1.5.linux-am ...
- 主席树 - Luogu 1001 A+B problem
看着大佬们的解法我瑟瑟发抖 我用主席树写一写吧 #include<iostream> #include<iomanip> #include<cmath> #incl ...
- Python 调用multiprocessing模块下面的Process类方法(实现服务器、客户端并发)-UDP协议
#基于UDP协议的multiprocessing自定义通信 服务端: from multiprocessing import Process import socket def task(server ...
- P1988 最大数
最大数 08年江苏的一道省选题. 题目描述: 用两种操作维护一个数列: 1. 查询:查询当前数列中末尾L个数中的最大的数,并输出这个数的值. 2. 插入:将n加上t,其中t是最近一次查询操作的答案(如 ...
- Python web 周总结
按顺序查询 order_by() order_by(- ) 下拉框默认显示 <select name="canteen_type_id" id="" ...
- 【bzoj3170】[Tjoi 2013]松鼠聚会 旋转坐标系
题目描述 有N个小松鼠,它们的家用一个点x,y表示,两个点的距离定义为:点(x,y)和它周围的8个点即上下左右四个点和对角的四个点,距离为1.现在N个松鼠要走到一个松鼠家去,求走过的最短距离. 输入 ...
- kb-07线段树-05-区间整体修改查询;(水)
/* */ #include<iostream> #include<cstring> #include<cstdio> using namespace std; s ...
- ACM程序设计选修课——1076汇编语言(重定向+模拟)
1076: 汇编语言 Time Limit: 1 Sec Memory Limit: 128 MB Submit: 34 Solved: 4 [Submit][Status][Web Board] ...
- cssText批量修改样式
cssText所有浏览器都支持. cssText 的使用 obj.style.cssText = " width:200px;position:absolute;left:100px;&qu ...