Android优化——截屏优化之缩短数据读取时间

缩短数据读取时间

在我遇到的场景中,OS对正在开发的App进行特定授权后,App可以在系统内使用screencap进行截图操作(另外一种截图的方式需要依赖当前Activity,不适合当前的场景),因此目标在于优化此命令的执行及数据输出上。

目标:缩短screencap输出数据的读取时间——绕开磁盘IO进行数据处理。

screencap命令

screencap格式:

screencap: invalid option -- -
usage: screencap [-hp] [-d display-id] [FILENAME]
   -h: this message
   -p: save the file as a png.
   -d: specify the display id to capture, default 0.
If FILENAME ends with .png it will be saved as a png.
If FILENAME is not given, the results will be printed to stdout.
  • -h 当前case暂且不适用;
  • -p 将截图保存为PNG格式;
  • -d 设置当前截图操作的id值,当前case暂且不适用;

原来方案

在原来方案中使用系统shell命令screencap进行截图,并且直接使用命令参数[FILENAME]将截图数据从内存写入到磁盘文件。

原有方案的代码(省略部分无关代码,添加部分注释):

public static String takeScreenshot(long timestamp, double size, int quality) {
        try {
            // image naming and path  to include download cache appending name you choose for file
            String dirPath = /* 截图存放路径 */
            // 省略...
            String imagePath = /* 生成截图文件名 */ 

            Process sh = Runtime.getRuntime().exec("/system/bin/screencap -p " + imagePath, null, null);
            sh.waitFor();

            // 此处省略....
            return outputPath; // 最后截图生成路径
        } catch (Exception e) {
			// exception
        }
        return null;
    }

上面代码逻辑:使用screencap命令截图,参数-p表明截图格式为PNG,并将最终图片写入磁盘中;
主要的耗时就在此时将截图数据写入到磁盘中。

运行时间

代码中执行最耗时位置在java.lang.ProcesswaitFor方法,执行时间如下:

在这里插入图片描述

从上图看出,整个方法执行时间2.52s,其中waitFor()方法执行了2.44s,这是screencap命令正在执行操作:

  • 进行屏幕截图操作;
  • 将数据写入到磁盘中;

因此需要优化的关键在于如何缩短将数据读取到内存处理时间。

修改方案

重新定义了takeScreenshot()方法,其中原有的参数处理在其他位置进行处理,因为依据原有方案截图输出图片名是可知的。

    public static Bitmap takeScreenshot() {
        try {
            Logcat.i("takeScreenshot", "START TO TAKE A SCREENSHOT...");
            long startTimeMillis = System.currentTimeMillis();
            Process sh = Runtime.getRuntime().exec("/system/bin/screencap -p" );
            Bitmap bitmap;
            byte[] byteArray = new byte[360 * 640 * 4]; // 此处的数组大小依据最终的图片大小而定,此处定义为360x640,测试设备的一般大小
            try (BufferedInputStream bis = new BufferedInputStream(sh.getInputStream())) {
                int length = bis.read(byteArray);
                bitmap = BitmapFactory.decodeByteArray(byteArray, 0, length);
                long endTimeMillis = System.currentTimeMillis();
                Logcat.d("takeScreenshot", "截图时间:" + (endTimeMillis - startTimeMillis) + "ms");
            }

            Logcat.i("takeScreenshot", "END TAKING A SCREENSHOT...");
            sh.destroy();
            return bitmap;
        } catch (Exception e) {
            // Several error may come out with file handling or DOM
            Logcat.e(TAG, "takeScreenshot: EXCEPTION " + e.getMessage());
        }
        return null;
    }

上述代码只做了一件事情,即重定义了takeScreenshot()方法,

  • 使用screencap命令截图,但不设置参数[FILENAME]输出路径——即将截图数据直接打印到stdout标准输出上;
  • stdout对象上直接获取数据,即获取输入流对象sh.getInputStream(),从中读取图片字节数据。
  • 读取完成后主动destroy进程,即java.lang.Process对象。

不使用waitFor()方法,因为waitFor()方法阻塞当前线程,一直等待到Process表示的进程自动终止。

public boolean waitFor(long timeout,
                       TimeUnit unit)
                throws InterruptedException
Causes the current thread to wait, if necessary, until the subprocess represented by this Process object has terminated, or the specified waiting time elapses.
If the subprocess has already terminated then this method returns immediately with the value true. If the process has not terminated and the timeout value is less than, or equal to, zero, then this method returns immediately with the value false.

The default implementation of this methods polls the exitValue to check if the process has terminated. Concrete implementations of this class are strongly encouraged to override this method with a more efficient implementation.

运行时间

重新定义的方案执行时间记录。

从修改方案执行执行图中可以看到的是,takeScreenshot()方法执行时间622ms,比原有方案缩短了大约1.9s

其后将截图图片的压缩,异步写入到磁盘,可在其他逻辑中进行处理,不影响整体执行结果。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

VoidHope

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值