本文主要记录android系统截屏一键分享开发,后续优化。

近期接到新需求,需要做截屏,然后弹出小窗口,显示一键分享与截屏小图预览。类似于同花顺app截图弹出框,点击后出现分享界面.

效果图如下:

         

·一,分析该需求的整个流程,大致步骤如下

  • 1,监听到截图的动作
  • 2,获取当前图像
  • 3,弹出提示框(显示截屏预览小图,带计时器自动隐藏)
  • 4,点击分享后弹出分享窗,分享图片预览
  • 5,点击某个平台后,生成自定义拼图分享到第三方

其中监听截图动作,和图片展示与拼接是重点步骤。

二,实现方式,技术选择

1,目前兼容性较高的截图监听方案为ContentObserver,可以兼容到android9.0。android10目前还在调研中(目前未发现有效方法)

具体代码不多赘述,百度一大把,标准套路,记录几个核心问题,首先解决如何精准拿到截图问题。

String[] KEYWORDS = { "screenshot", "screenshots", "screen_shot", "screen-shot", "screen shot", "screencapture",      "screen_capture", "screen-capture", "screen capture", "screencap", "screen_cap", "screen-cap", "screen cap", "截屏" }

过滤拿到的路径是否包含上述关键词,此时,没必要继续拿图片,只是监听到有截图动作即可,调用view截图生成bitmap方式,这样,保证最准确。同时,可以排除无用信息提示框,Toast等窗口。

此方法生成当前窗口的截图
/ * 截取当前窗体的截图,根据[isShowStatusBar]判断是否包含当前窗体的状态栏* 原理是获取当前窗体decorView的缓存生成图片*/
public static Bitmap captureWindow(Activity activity) {boolean isStatuBar = false;// 获取当前窗体的View对象View view = activity.getWindow().getDecorView();view.setDrawingCacheEnabled(true);// 生成缓存view.buildDrawingCache();Bitmap bitmap = null;if (isStatuBar) {// 绘制整个窗体,包括状态栏bitmap = Bitmap.createBitmap(view.getDrawingCache(), 0, 0, view.getMeasuredWidth(),                         view.getMeasuredHeight());} else {// 获取状态栏高度Rect rect = new Rect();view.getWindowVisibleDisplayFrame(rect);Display display = activity.getWindowManager().getDefaultDisplay();// 减去状态栏高度bitmap = Bitmap.createBitmap(view.getDrawingCache(), 0,rect.top, display.getWidth(), display.getHeight() - rect.top);}view.setDrawingCacheEnabled(false);view.destroyDrawingCache();return bitmap;
}

生成bitmap 之后,考虑如何添加到当前Activity。方式有三种Popuwindow, dialog,和直接addView 方式。综合考虑,直接addView添加小窗口最合适。考虑如下,PopuWindow 和dialog弹出后,会抢占焦点,这样无法继续与原界面交互,那么倒计时小时的功能也变的无用。

为了考虑通用型,每个Activity可以操作到的根布局为contentView ,为Framelayout。

//直接拿到contentView然后Inflate窗口view。设置好位置后,addView 到contentView,这样,使用倒计时销毁时,直接contentView.remove()即可。保证了每个界面添加的通用型,即使嵌套Fragment,也不用考虑焦点问题。

final ViewGroup viewById = mContext.findViewById(android.R.id.content);
final View view = View.inflate(mContext,R.layout.screen_shot_dialog,null);

FrameLayout.LayoutParams f = new FrameLayout.LayoutParams(width,height);

f.gravity = Gravity.CENTER_VERTICAL | Gravity.RIGHT;

f.rightMargin = DisplayUtil.dip2px(mContext,20);

view.setLayoutParams(f);

final Bitmap bitmap = Utils.captureWindow(mContext); //获取当前窗口影像图片 替代从文件库取

imageView.setImageDrawable(new BitmapDrawable(bitmap));

viewById.addView(view);//最终添加到当前Activity

2,自定义分享图片的拼接问题。

思路有二,一可以使用canvas绘制bitmap,拼接。方法主要难点在绘制位置,以及性能开销。(标准API,课自行百度)

二,可以同样借鉴View生成图片方案,先创建一个布局,在相关位置填好截屏图片,二维码,文字等。然后生成bitmap。注意,在调用以下方法,view必须添加到布局且重绘完毕,所以,可以使用view.postRunable()。在runalbe任务里面生成图片,以保证view准备完毕。

/***抓取view 影像图片*/
public static Bitmap captureView(View view) {view.setDrawingCacheEnabled(true);// 生成缓存view.buildDrawingCache();Bitmap bitmap = null;// 绘制整个viewbitmap = Bitmap.createBitmap(view.getDrawingCache(), 0, 0,view.getWidth(), view.getHeight());view.setDrawingCacheEnabled(false);view.destroyDrawingCache();return bitmap;
}

在此注意,可以先添加到contentview 中,设置为隐藏,待生成完毕后,再移除掉。以保证生成正确。

               final View shareView = View.inflate(mContext,R.layout.share_view_splash,null);//用于生成分享图片的布局final ImageView iv_shot_share = shareView.findViewById(R.id.iv_shot_share);shareView.setVisibility(View.INVISIBLE);//设置为不可见,但是占用空间contentView.addView(shareView);contentView.requestLayout();iv_shot_share.post(new Runnable() {//使用post方法,保证view绘制完毕@Overridepublic void run() {Bitmap shareImg = Utils.captureView(shareView);//生成图片shareView.setVisibility(View.GONE);contentView.removeView(shareView);//移除}});}});

3,关于截屏预览裁剪。

Android  ImageVIew中现有的适配模式,centerCrop 等,无法满足,宽度充满,从顶部往下,超出则截掉的需求。所以,在ImageView 设置预览图时,需要对生成窗口视图bitmap进行二次处理。思路,使用Matrix将窗口视图缩放到与要展示的容器宽度比例。然后重新生成图片,从顶部开始,截出新图片。

public static Bitmap reClip(Bitmap bitmapOri,int widthTarget,int heightTarget){//xxxTarget 为ImageView 容器宽高int width = bitmapOri.getWidth();int height = bitmapOri.getHeight();Bitmap bitmap = null;float scaleWidth = (float) (widthTarget/1.0/width);//缩放Matrix matrix = new Matrix();matrix.postScale(scaleWidth,scaleWidth);Bitmap bitmapScale = Bitmap.createBitmap(bitmapOri,0,0,width,height,matrix,true);//按照缩放比例生成新图//在此要做判断,新截图片不能大于原始图片高度。否则异常终止,尤其注意普通屏幕,一般没问题。全面屏,不做此判断,会出现崩               溃,具体和要展示的容器宽高有关if(bitmapScale.getHeight()> heightTarget){bitmap = Bitmap.createBitmap(bitmapScale,0,0,bitmapScale.getWidth(),heightTarget);}else{bitmap = Bitmap.createBitmap(bitmapScale,0,0,bitmapScale.getWidth(),bitmapScale.getHeight());}return bitmap;}

使用bitmap 注意及时回收。

4,关于分享图片问题,生成的本地图片保存到公共空间,

Environment.getExternalStorageDirectory()//比如这里

开发中,保存到应用包名下(context.getCacheDir),微信可以,但是QQ会出现无反应问题,报错信息也不明显。原因是读取权限问题,之后android10 还会进一步限制,所以,涉及到第三方app传递文件时,注意存储位置。

Android截屏一键分享开发与实现方式的反思和总结相关推荐

  1. Android截屏分享

    最近项目需要实现Android截屏分享功能,包括Android截屏获取图片.将图片保存到本地.通知系统相册更新.通过微信.QQ.微博分享截屏图片,本篇博客作为总结回顾. 一.Android截屏获取图片 ...

  2. Android 截屏监听(截图分享功能实现)

    具体来说就是,检测到了用户在应用内有截图,弹出一个分享界面, 在截图下方添加一个二维码,进行分享. ●●●  前言 Android系统没有直接对截屏事件监听的接口,也没有广播,只能自己动手来丰衣足食, ...

  3. Android截屏分享之View生成图片进行保存分享、全屏,半屏、指定VIew、弹窗.......

    Android截屏主要应用在分享这个操作,所有的截屏,截取的是视图.接下来给大家分享一下这个功能的干货 温馨提示:我这里分享使用的是极光的Jshare,也可以使用原生分享 这里是JshareSDK接入 ...

  4. android开发截屏代码,android截屏代码:C++实现

    android截屏代码:C++实现 示例代码在: frameworks\base\services\surfaceflinger\tests\screencap\screencap.cpp /* * ...

  5. android华为虚拟截屏黑屏,Android截屏表面视图显示黑屏

    Android截屏表面视图显示黑屏 我试图通过代码拍摄我的游戏的截图,并通过一个意图来分享它.我能做这些事情,但是截图总是看起来是黑色的.下面是与分享截图相关的代码:View view = MainA ...

  6. android 截屏函数_android截屏功能实现代码

    这篇文章主要为大家详细介绍了android截屏功能的实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 android开发中通过View的getDrawingCache方法可以达到截屏的目的, ...

  7. Android截屏截图的几种方法总结

    Android截屏 Android截屏的原理:获取具体需要截屏的区域的Bitmap,然后绘制在画布上,保存为图片后进行分享或者其它用途 一.Activity截屏 1.截Activity界面(包含空白的 ...

  8. android盒子截图,Android截屏截图的几种方法总结

    Android截屏 Android截屏的原理:获取具体需要截屏的区域的Bitmap,然后绘制在画布上,保存为图片后进行分享或者其它用途 一.Activity截屏 1.截Activity界面(包含空白的 ...

  9. Android截屏截图方法汇总(Activity、View、ScrollView、ListView、RecycleView、WebView截屏截图)

    Android截屏 Android截屏的原理:获取具体需要截屏的区域的Bitmap,然后绘制在画布上,保存为图片后进行分享或者其它用途 一.Activity截屏 1.截Activity界面(包含空白的 ...

最新文章

  1. JS流程控制语句 二选一 (if...else语句) 语法: if(条件) { 条件成立时执行的代码} else {条件不成立时执行的代码}...
  2. java基础----IO打印流PrintStream
  3. Ruby BigDecimal库拒绝服务漏洞
  4. DML、DDl、DQL实战
  5. Makefile.am和makefile.in生成Makefile
  6. 被薅秃了!元气森林:损失近千万元 将为14.05万下单用户每人寄一箱白桃气泡水...
  7. php 向上取整_PHP取整方法小总结
  8. React-Router 4 两个常用路由变量
  9. 统计学习方法第15章-奇异值分解SVD
  10. 孙鑫VC学习笔记:第八讲 逃跑按钮的巧妙实现和MFC中指针的获取
  11. 项目设计----会员充值(基础)
  12. CTF杂项(一)——编码学基础
  13. java实验指导书 王立新,java实验指导书
  14. java定时器quartz表达式,quartz定时任务cron表达式
  15. 智能客服在2022:从成本中心奔向价值中心
  16. java 抽屉效果_[Java教程]抽屉组件的滑动效果_星空网
  17. iOS 内购项目的App Store推广
  18. DEV GridView 部分属性
  19. mysql管理工具10.1,NavicatforMySQL10
  20. 逃离美国,跨越8000公里远程办公,他开发了世界上最强的虚拟机

热门文章

  1. 仿写App,如何获取app内的图片资源?以安卓机为例
  2. 【转载】深入理解L1、L2范数
  3. Android的webview支持HTML5的离线应用功能
  4. 服务器连接显示18456,SQL2008无法连接到服务器,用户’XX’登录失败(错误18456)解决方法...
  5. Oracle数据库信息分类汇总计数
  6. SimpleAudioEngine音效的使用导致游戏出现卡顿记录
  7. Android逆向工具简单介绍
  8. bug 记录 - 安卓移动端高度使用 100vh 的坑
  9. 操作系统中的并发和并行
  10. 华为路由器怎么看是不是公网_路由器怎么看公网ip_怎么看路由器的公网ip?-192路由网...