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

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

文章目录

缩短数据读取时间screencap命令原来方案运行时间

修改方案运行时间

缩短数据读取时间

在我遇到的场景中,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.Process的waitFor方法,执行时间如下:

从上图看出,整个方法执行时间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。

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

相关推荐

在老狼的歌声里追忆青春,一群中年人蹦起来了
365b体育最新下载地址

在老狼的歌声里追忆青春,一群中年人蹦起来了

📅 07-09 👁️ 5755
中国寓言
365体育送365

中国寓言

📅 08-16 👁️ 5676
发行说明
bt365投注

发行说明

📅 09-23 👁️ 2037
《恐怖黎明》全成就解锁指南
365体育送365

《恐怖黎明》全成就解锁指南

📅 10-17 👁️ 2120
退烧贴多少度才能用
365b体育最新下载地址

退烧贴多少度才能用

📅 09-16 👁️ 7622
化工工程设计常用三维配管软件有哪些?国产化工管道CAD系统推荐
2025兰州香烟价格表图 兰州烟黑中支、硬蓝价格一览表
如何使用CAD打断命令?掌握这些技巧,你真的不容错过!-BIM免费教程
FRIENDSHIP中文(简体)翻译:剑桥词典
bt365投注

FRIENDSHIP中文(简体)翻译:剑桥词典

📅 09-14 👁️ 1920