Android实现长图文截图功能实例代码

 更新时间:2018年11月14日 10:21:07   作者:_Ricky_  
这篇文章主要给大家介绍了关于Android实现长图文截图功能的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

截图是我们日常开发经常会遇到的一个功能,最近工作遇到的需求又升级了,需要实现长图文的截图功能,经常查找相关资料终于实现了,支持截取微博、知乎、今日头条等第三方APP......

先瞅瞅效果图:


效果图

再瞅瞅最终的长截图:

我是长截图一,瞅瞅嘛...

我是长截图二,再瞅一下嘛...

上一周脑子突然冒出长截图这个功能,想着如何截取如微博,知乎,头条等这些第三方APP的界面呢?出于好奇心,花了一周业余时间,撸一个看看。

不就是截屏+拼图,还能有什么难度么?这个。。。好像确实是。

Question:

1.如何截屏?

Android 5.0 API 21之前,想要系统截屏,是需要root,不过Android 5.0开始开放了响应的截屏接口:

MediaProjection (added in API level 21.)

A token granting applications the ability to capture screen contents and/or record system audio. The exact capabilities
granted depend on the type of MediaProjection.

2.如何优雅的截图?

悬浮窗那么小,难道每次我都得滑一定的距离,然后点一次悬浮窗么,理论上可以,但体验不好。估计更多人倾向只要触摸屏幕就可以截图,所以选择监听悬浮窗外的触屏事件。

3.如何监听悬浮窗口外部的TouchEvent?

悬浮窗外的触屏事件都已经脱离整个应用了,如何监听呢?这里确实卡了些时间,因为确实找不到如何捕获这个事件的好,我感觉这个问题也是最烦的一个,后来来了点灵感,我设置一个全屏的透明背景,然后给这个背景设置onTouch事件,哦!!!恍然大悟,以为这样就可以了?错!!这样会出现整个手机的事件都将被这个透明背景拦截,无法传递到手机桌面,如果非开发人员安装了这个软件。。,告诉他,重新开机吧。。。所以翻了下WindowManager的源码,看到flag参数,把各种flag参数的注释看了遍,最后定位在如下几个flag参数值上。

  /** Window flag: this window won't ever get key input focus, so the
   * user can not send key or other button events to it. Those will
   * instead go to whatever focusable window is behind it. This flag
   * will also enable {@link #FLAG_NOT_TOUCH_MODAL} whether or not that
   * is explicitly set.
   *
   * <p>Setting this flag also implies that the window will not need to
   * interact with
   * a soft input method, so it will be Z-ordered and positioned
   * independently of any active input method (typically this means it
   * gets Z-ordered on top of the input method, so it can use the full
   * screen for its content and cover the input method if needed. You
   * can use {@link #FLAG_ALT_FOCUSABLE_IM} to modify this behavior. */
  public static final int FLAG_NOT_FOCUSABLE  = 0x00000008;

  /** Window flag: this window can never receive touch events. */
  public static final int FLAG_NOT_TOUCHABLE  = 0x00000010;

  /** Window flag: even when this window is focusable (its
   * {@link #FLAG_NOT_FOCUSABLE} is not set), allow any pointer events
   * outside of the window to be sent to the windows behind it. Otherwise
   * it will consume all pointer events itself, regardless of whether they
   * are inside of the window. */
  public static final int FLAG_NOT_TOUCH_MODAL = 0x00000020;
  /** Window flag: if you have set {@link #FLAG_NOT_TOUCH_MODAL}, you
   * can set this flag to receive a single special MotionEvent with
   * the action
   * {@link MotionEvent#ACTION_OUTSIDE MotionEvent.ACTION_OUTSIDE} for
   * touches that occur outside of your window. Note that you will not
   * receive the full down/move/up gesture, only the location of the
   * first down as an ACTION_OUTSIDE.
   */
  public static final int FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000;

在全屏透明背景的环境下,本以为可以监听桌面的Down、Move、Up事件,但是出现事件全部被拦截死在这个透明背景上,无法传到手机桌面,再发现组合这些参数,总结这种思路不可取。

查看注释可以知道设置FLAG_WATCH_OUTSIDE_TOUCH可以在窗口外部(即App外部)接收一个指定事件MotionEvent#ACTION_OUTSIDE,但同时,你将无法接收到任何的Down、Move、Up事件。所以,也只能这样了。。有其它高招的兄弟指点下哈。

4.如何控制截屏频次?

在步骤3的基础上,基本可以做一个截图策略了,比如,每接收一次ACTION_OUTSIDE就截一次图,又或者,每次监听一次ACTION_OUTSIDE,就进行一次计数器的累加,为了保证截图能承上启下连贯,可以设置阈值为2这样。

5.如何拼图?

这里因人而异了,但目的都一样,将上述步骤所截的图对比出不同的地方,然后把不同的地方拼接起来。出于运算效率考虑,这里我是用JNI来实现的,主函数:

JNIEXPORT void JNICALL Java_com_zfw_screenshot_utils_SewUtils_merge(
  JNIEnv *env, jobject thiz, jobject bmp0, jobject bmp1, jobject bmp2, int h0, int h1, int h2, int samePart, int len) {

 int *pixels_0 = lockPixel(env, bmp0);
 int *pixels_1 = lockPixel(env, bmp1);
 int *pixels_2 = lockPixel(env, bmp2);
 /* -------------------- merge the difference ----------------------- */
 int index = 0;
 while(index < h0) {
  if(index < h1) {
   getRowPixels(pixels_0, index, pixels_1, index, len);
  } else {
   getRowPixels(pixels_0, index, pixels_2, index - h1 + samePart, len);
  }
  index++;
 }
 /* -------------------- merge the difference ----------------------- */
 unlockPixel(env, bmp0);
 unlockPixel(env, bmp1);
 unlockPixel(env, bmp2);
}

功能实现上没什么难度,感觉更多的是得选好实现的策略,比如如何优雅的监听悬浮窗外的Touch事件,如何优雅的实现一个“定点”截图的策略,如何优雅的对比两个Bitmap的不同地方,进行拼接。

源码传送门:https://github.com/zengfw/LongScreenShot (本地下载)

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

相关文章

  • Android编程之Button控件配合Toast控件用法分析

    Android编程之Button控件配合Toast控件用法分析

    这篇文章主要介绍了Android编程之Button控件配合Toast控件用法,结合实例形式分析了Button控件及Toast控件的功能及具体使用技巧,需要的朋友可以参考下
    2015-12-12
  • Android 加载大图及多图避免程序出现OOM(OutOfMemory)异常

    Android 加载大图及多图避免程序出现OOM(OutOfMemory)异常

    这篇文章主要介绍了Android 加载大图及多图避免程序出现OOM(OutOfMemory)异常的相关资料,需要的朋友可以参考下
    2017-03-03
  • Android中的Notification机制深入理解

    Android中的Notification机制深入理解

    这篇文章主要给大家介绍了关于Android中Notification机制的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-02-02
  • Android通过代码控制ListView上下滚动的方法

    Android通过代码控制ListView上下滚动的方法

    今天小编就为大家分享一篇关于Android通过代码控制ListView上下滚动的方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • Android利用Espresso进行UI自动化测试的方法详解

    Android利用Espresso进行UI自动化测试的方法详解

    因为我是搞android开发的,所以被分到了自动化测试小组,所以了解了一些UI自动化测试。下面这篇文章主要给大家介绍了关于Android利用Espresso进行UI自动化测试的相关资料,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-12-12
  • android中px和dp,px和sp之间的转换方法

    android中px和dp,px和sp之间的转换方法

    在Android开发中dp和px,sp和px之间的转换时必不可少的。下面脚本之家小编给大家带来了android中px和dp,px和sp之间的转换方法,感兴趣的朋友一起看看吧
    2018-06-06
  • Android 自动完成文本框的实例

    Android 自动完成文本框的实例

    下面小编就为大家分享一篇Android 自动完成文本框的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-01-01
  • Android自定义View实现投票进度条

    Android自定义View实现投票进度条

    这篇文章主要为大家详细介绍了Android自定义View实现投票进度条,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-11-11
  • 解析Android应用启动后自动创建桌面快捷方式的实现方法

    解析Android应用启动后自动创建桌面快捷方式的实现方法

    和IOS开发和Windows Phone开发相比,Android是开放的,Android上的开发也相对更加灵活,能够做很多事情。有的朋友会发现,在某些Android应用安装以后,第一次运行,就会在桌面创建快捷方式。这是如何做到的呢
    2013-05-05
  • Android自定义View onDraw()方法会调用两次的问题解决

    Android自定义View onDraw()方法会调用两次的问题解决

    这篇文章主要介绍了Android自定义View onDraw()方法会调用两次的问题解决,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2024-01-01

最新评论