android 调用系统源码截屏的改良方案

之前有个需求,获取launcher的截屏,那么自然无法通过View来转换成bitmap。那么只能通过系统源码来获取,网上找到的基本都是以下方法(注意需要系统权限):

surfacaController.screenshot(int,int);

但是这个方法有两个问题:

1、悬浮控件会排列到屏幕的左上角,导致截屏效果不理想。

2、旋转屏幕后截屏,图片会存在旋转问题

于是翻看源码发现这个方法有很多重载,然后很幸运的是真给我找到了一个重载:

     /**
1994       * @see SurfaceControl#screenshot(Rect, int, int, boolean, int)}
1995       * @hide
1996       */
1997      @UnsupportedAppUsage
1998      public static Bitmap screenshot(Rect sourceCrop, int width, int height, int rotation) {
1999          return screenshot(sourceCrop, width, height, false, rotation);
2000      }
2002      /**
2003       * Copy the current screen contents into a hardware bitmap and return it.
2004       * Note: If you want to modify the Bitmap in software, you will need to copy the Bitmap into
2005       * a software Bitmap using {@link Bitmap#copy(Bitmap.Config, boolean)}
2006       *
2007       * CAVEAT: Versions of screenshot that return a {@link Bitmap} can be extremely slow; avoid use
2008       * unless absolutely necessary; prefer the versions that use a {@link Surface} such as
2009       * {@link SurfaceControl#screenshot(IBinder, Surface)} or {@link GraphicBuffer} such as
2010       * {@link SurfaceControl#screenshotToBuffer(IBinder, Rect, int, int, boolean, int)}.
2011       *
2012       * @see SurfaceControl#screenshotToBuffer(IBinder, Rect, int, int, boolean, int)}
2013       * @hide
2014       */
2015      @UnsupportedAppUsage
2016      public static Bitmap screenshot(Rect sourceCrop, int width, int height,
2017              boolean useIdentityTransform, int rotation) {
2018          // TODO: should take the display as a parameter
2019          final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
2020          if (displayToken == null) {
2021              Log.w(TAG, "Failed to take screenshot because internal display is disconnected");
2022              return null;
2023          }
2024  
2025          if (rotation == ROTATION_90 || rotation == ROTATION_270) {
2026              rotation = (rotation == ROTATION_90) ? ROTATION_270 : ROTATION_90;
2027          }
2028  
2029          SurfaceControl.rotateCropForSF(sourceCrop, rotation);
2030          final ScreenshotGraphicBuffer buffer = screenshotToBuffer(displayToken, sourceCrop, width,
2031                  height, useIdentityTransform, rotation);
2032  
2033          if (buffer == null) {
2034              Log.w(TAG, "Failed to take screenshot");
2035              return null;
2036          }
2037          return Bitmap.wrapHardwareBuffer(buffer.getGraphicBuffer(), buffer.getColorSpace());
2038      }
2094      private static void rotateCropForSF(Rect crop, int rot) {
2095          if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
2096              int tmp = crop.top;
2097              crop.top = crop.left;
2098              crop.left = tmp;
2099              tmp = crop.right;
2100              crop.right = crop.bottom;
2101              crop.bottom = tmp;
2102          }
2103      }

可以发现,最后一个int类型参数代表的是拍摄的角度,如果向左旋转截屏就是270度,向右旋转截屏就是90度。

//解释:
ROTATION_0     //int值为0
ROTATION_90    //int值为1
ROTATION_180   //int值为2
ROTATION_270   //int值为3

现在就解决了屏幕旋转截屏的问题,但是惊喜的发现悬浮控件出现在左上角的问题也顺带解决了,这个我还没搞懂是什么原因,懂的大神请评论区指教。

最后贴上调用代码:

//系统截屏
    private Bitmap screenshotSystem() {
        Class<?> demo;
        Bitmap bitmap = null;
        try {
            demo = Class.forName("android.view.SurfaceControl");
            Method method = demo.getMethod("screenshot", Rect.class, int.class, int.class, int.class);
            Object obj = obj = method.invoke(null, new Rect(), getWidth(), getHeight(), int);;   //最后一个参数是屏幕旋转角度0,1,2,3对应0,90,180,270
            bitmap = (Bitmap) obj;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bitmap;
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值