安卓应用内防止截图

禁止截图的实现

禁止截图通过对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);

}

之前QQ有个qq赞赏照片的功能,也防止截图,这个功能调用的是安卓和IOS底层的一个功能消息接口,拦截这个消息就能禁止截图。

截图工具类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;

}

}

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

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工具

screencapAndroid原生自带的工具,是一个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

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值