Android 控件截图保存本地并分享

目录

需求

需求分析

一、截图控件生成图片

二、将图片保存至本地

2.1 权限

2.2 保存图片

2.3 调用

三、分享

四、通过测试机型


需求

截图当前页面某个控件的内容,并且保存在本地,可分享。

需求分析

  • 1.截图控件生成图片

  • 2.保存至本地(需考虑版本兼容以及权限问题)

  • 3.分享(a.调用系统分享,b.自己集成三方SDK)

分析完事,咱们根据分析来一步步实现

一、截图控件生成图片

    private Runnable toastRunnable = new Runnable() {public void run() {Bitmap bm = Bitmap.createBitmap(ll_dialog.getWidth(), ll_dialog.getHeight(),Bitmap.Config.ARGB_8888);//创建画布Canvas canvas = new Canvas(bm);//View渲染到的画布。ll_dialog.draw(canvas);MLog.e("保存图片");}};
  • 1.图片要在页面中加载出来,需要获取该控件的宽高。

  • 2.根据空寂那的宽高设置Bitmap的

  • 3.View渲染到的画布,这个时候bm就生成成功了。

二、将图片保存至本地

保存图片的方式根据「版本和权限」分为两种:

  • Android Q(Android 10) 以上

    • 1、保存到应用的内部存储空间 (内部存储)

    • 2、保存到 Android 系统设置的共享存储空间(外部储存)

  • Android Q(Android 10) 以下

    • 获取外部存储目录(本文用的是这个)

      • 函数使用:getExternalStorageDirectory()

    • 获取外部存储公共目录

      • 函数使用:getExternalStoragePublicDirectory()

图片(包括照片和屏幕截图),存储在 DCIM/ 或 Pictures/ 目录。

2.1 权限

「Android Q不再需要申请文件读写权限」,默认可以读写自己沙盒文件和公共媒体文件。所以Q以上不需要再动态申请文件读写权限。

所以我们只需要兼容10以下的权限申请即可。

public class PerUtils {public static int REQUEST_CODE_WRITE = 1001;//校验权限public static boolean checkPerWRITE(Activity activity) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {return true;} else {String[] permissions = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};for (String str : permissions) {if (activity.checkSelfPermission(str) != PackageManager.PERMISSION_GRANTED) {activity.requestPermissions(permissions, REQUEST_CODE_WRITE);return false;}}}return true;}/*** 检测请求结果码判定是否授权** @param grantResults* @return*/public static boolean checkPermissionResult(int[] grantResults) {if (grantResults != null) {for (int result : grantResults) {if (result != PackageManager.PERMISSION_GRANTED) {return false;}}}return true;}
}

Activity.class调用

    if (PerUtils.checkPerWRITE(Activity.this)){saveBitmap();}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);try {if (requestCode == PerUtils.REQUEST_CODE_WRITE) {if (PerUtils.checkPermissionResult(grantResults)) {//授权成功saveBitmap();}else{//授权失败}}} catch (Exception e) {}}

2.2 保存图片

import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;import androidx.annotation.RequiresApi;import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;public class ShareImageUtils {// Android Q 以上@RequiresApi(api = Build.VERSION_CODES.Q)public static String saveQUp(Bitmap image, Context context, String fileName, int quality) {// 文件夹路径String imageSaveFilePath = Environment.DIRECTORY_DCIM + File.separator;MLog.e("TAG", "文件夹目录 >>> " + imageSaveFilePath);File filePath = new File(imageSaveFilePath);if (!filePath.exists()) {filePath.mkdirs();}// 文件名字MLog.e("TAG", "文件名字 >>> " + fileName);ContentValues contentValues = new ContentValues();contentValues.put(MediaStore.MediaColumns.TITLE, fileName);contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName);contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");contentValues.put(MediaStore.MediaColumns.DATE_TAKEN, fileName);//该媒体项在存储设备中的相对路径,该媒体项将在其中保留contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, imageSaveFilePath);Uri uri = null;OutputStream outputStream = null;ContentResolver localContentResolver = context.getContentResolver();try {uri = localContentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);outputStream = localContentResolver.openOutputStream(uri);// Bitmap图片保存image.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);outputStream.flush();outputStream.close();return getRealPathFromURI(uri);} catch (Exception e) {e.printStackTrace();if (uri != null) {localContentResolver.delete(uri, null, null);}return "";} finally {image.recycle();try {if (outputStream != null) {outputStream.close();}} catch (IOException e) {e.printStackTrace();}}}//根据Uri获取路径private static String getRealPathFromURI(Uri contentURI) {String result;Cursor cursor = MyApp.getAppContext().getContentResolver().query(contentURI, null, null, null, null);if (cursor == null) { // Source is Dropbox or other similar local file pathresult = contentURI.getPath();} else {cursor.moveToFirst();int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);result = cursor.getString(idx);cursor.close();}return result;}// Android Q 以下public static String saveQNext(Bitmap image, Context context, String fileName, int quality) {String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator;Log.i("TAG", "saveQNext: >>> " + path);File filePath = new File(path);if (!filePath.exists()) {filePath.mkdirs();}// 文件名称Log.i("TAG", "saveQNext: " + fileName);File file = new File(path, fileName);try {FileOutputStream fos = new FileOutputStream(file);// 通过io流的方式来压缩保存图片image.compress(Bitmap.CompressFormat.JPEG, quality, fos);fos.flush();fos.close();// 保存图片后发送广播通知更新数据库,不更新数据库不会立即显示Uri uri = Uri.fromFile(file);context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));return getRealPathFromURI(uri);} catch (IOException e) {e.printStackTrace();return "";}}
}           

如此便将生成的Bitmap保存在本地了。

2.3 调用

            String fileName = System.currentTimeMillis() + ".jpg";String path = "";//根据版本使用不同的方法if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {path = ShareImageUtils.saveQUp(bm, mContext, fileName, 100);} else {path = ShareImageUtils.saveQNext(bm, mContext, fileName, 100);}if (!MStringUtils.isNullOrEmpty(path)) {//保存成功} else {//保存失败}

三、分享

调用系统图片进行分享

        //由文件得到uriUri imageUri = Uri.fromFile(new File(path));MLog.e("share", "uri:" + path);Intent shareIntent = new Intent();shareIntent.setAction(Intent.ACTION_SEND);shareIntent.putExtra(Intent.EXTRA_STREAM, imageUri);shareIntent.setType("image/*");mContext.startActivity(Intent.createChooser(shareIntent, "Share"));

四、通过测试机型

  • 1.Android 13 三星

  • 2.Android 12 小米 K40

  • 3.Android 7.1 模拟器

  • 4.鸿蒙2.0系统 华为Play

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/42065.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【SpringCloud】Ribbon定制化配置

文章目录 使用Ribbon自带负载均衡算法添加负载均衡算法ConfigurationRestTemplate使用上面负载均衡算法 自定义负载均衡算法负载均衡算法实现RestTemplate在Controller中使用该负载均衡算法ServiceIInstance解释 使用Ribbon自带负载均衡算法 添加负载均衡算法Configuration /…

实现矩阵地图与rviz地图重合

文章目录 一、rviz地图转换矩形地图(只能用于全局规划)二、在rviz上显示地图边界信息,可视化调整,实现重合(只能用于局部规划)一、rviz地图转换矩形地图(只能用于全局规划) 此方法矩形地图可能会与rviz地图不重合,通过改变偏移量x_offset,y_offset接近地图 可以将矩…

FL Studio for Windows-21.1.0.3713中文直装版功能介绍及系统配置要求

FL Studio 21简称FL水果软件,全称是:Fruity Loops Studio编曲,由于其Logo长的比较像一款水果因此,在大家更多的是喜欢称他为水果萝卜,FL studio21是目前最新的版本,这是一款可以让你的计算机就像是一个全功能的录音室&…

Docker Dockerfile Docker-compose学习笔记

文章目录 Centos环境下安装Docker配置镜像源 Windows环境下安装Docker配置镜像源 使用Dokcer镜像1.获取镜像2.查看镜像信息(1)列出镜像(2)镜像标签(3)镜像详细信息(4)镜像历史 3.搜索镜像4.删除和清理镜像(1)使用标签删除镜像(2)使用ID删除镜像(3)清理镜像 5.创建镜像(1)基于已…

基于SpringBoot和Freemarker的页面静态化

页面静态化能够缓轻数据库的压力,还能提高页面的并发能力,但是网页静态化是比较适合大规模且相对变化不太频繁的数据。 页面静态化在实际应用中还是比较常见的,比如博客详情页、新闻网站或者文章类网站等等。这类数据变化不频繁比较适合静态…

56.linux 进程管理命令和用户管理命令

目录 一、进程管理命令 1.ps 2.pstree 3.kill 4.pkill 5.&后台运行程序 6.jobs 7.fg bg 8.top 二、用户管理命令 1.系统存储用户信息的文件 2.添加新用户 3.修改用户密码 4.删除用户 一、进程管理命令 1.ps 用于查看当前系统中运行的进程信息。它可以…

Golang 程序性能优化利器 PGO 详解(一):简单介绍及使用

在软件开发过程中,性能优化是不可或缺的一部分。无论是在Web服务、数据处理系统还是实时通信中,良好的性能都是至关重要的。Golang 从1.20版版本开始引入的 Profile Guided Optimization(PGO)机制能够帮助更好地优化 Go 程序的性能…

The Age of Data and AI: Challenges and Opportunities

Simply put Abstract: This paper examines the impact of the “Age of Data” on the field of artificial intelligence (AI). With the proliferation of digital technologies and advancements in data collection, storage, and processing, organizations now have ac…

进行 200 瓦太阳能 (PV) 模块设计以测量太阳能光伏阵列的电压、电流和功率、综合负荷频率和电压控制系统的方法研究(Simulink实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

Levenshtein python调用

函数解释: Levenshtein距离又称作编辑距离(Edit Distance),是指两个字符之间,由一个字符转变成另一个字符所需的最少编辑操作次数。被允许的操作有以下几种: a. Replace替换,将一个字符替换成另…

如何使用CSS实现一个响应式视频播放器?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 使用CSS实现响应式视频播放器⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅!这个专栏是为那些对Web开发感兴趣…

vue输入框只能输入数字类型,禁止输入和粘贴e

js怎么去除1e里面e 方法一:使用 Number() 函数将科学计数法表示的字符串转换为数字。然后,使用 toString() 方法将其转换回字符串形式,这样就会自动移除科学计数法中的 "e" var num 1e10; // 科学计数法表示的数字 var numStr …

【小梦C嘎嘎——启航篇】string介绍以及日常使用的接口演示

【小梦C嘎嘎——启航篇】string 使用😎 前言🙌C语言中的字符串标准库中的string类string 比较常使用的接口对上述函数和其他函数的测试代码演示: 总结撒花💞 😎博客昵称:博客小梦 😊最喜欢的座右…

c语言每日一练(9)

前言:每日一练系列,每一期都包含5道选择题,2道编程题,博主会尽可能详细地进行讲解,令初学者也能听的清晰。每日一练系列会持续更新,暑假时三天之内必有一更,到了开学之后,将看学业情…

rollup工具打包报错问题汇总

1. (!) this has been rewritten to undefined 原因:这是因为打包后没有给this指向window,导致this undefined,因此需要配置context参数来指定代码执行环境的参数为window 解决:rollup.config.js文件中添加配置 module.exports…

算法通关村第十关 | 数组中第k个最大元素

1.数组中第k大的数字 题目: LeetCode:数组中的第k个最大元素,给定整数数组nums和整数k,请返回数组中第k个最大的元素,请注意,你需要找的是数组排序后第k个最大的元素,而不是第k个不同的元素。 运…

JVM——配置常用参数,GC调优策略

文章目录 JVM 配置常用参数Java内存区域常见配置参数概览堆参数回收器参数项目中常用配置常用组合 常用 GC 调优策略GC 调优原则GC 调优目的GC 调优策略 JVM 配置常用参数 Java内存区域常见配置参数概览堆参数;回收器参数;项目中常用配置;常…

element-Plus中el-menu菜单无法正常收缩解决方案

<el-menu :collapse"true">如图所示收缩之后&#xff0c;有子级的菜单还有箭头文字显示 从代码对比看层级就不太对了&#xff0c;嵌套错误了&#xff0c;正常下方官网的ul标签下直接是li&#xff0c;在自己的代码中&#xff0c;ul标签下是div标签&#xff0c;层…

FairyGUI编辑器自定义菜单扩展插件

本文涉及到的软件有&#xff1a;FairyGUI&#xff0c;VSCode 代码环境涉及到了&#xff1a;Lua VSCode插件&#xff1a;EmmyLua 在编写FairyGUI编辑器菜单前&#xff0c;了解一下FairyGUIEditor的API会有效的帮助我们解决很多问题。FairyGUI的扩展是通过编辑器自带的插件功能…

【嵌入式】MKV31F512VLL12 微控制器 (MCU) 、Cyclone® IV E EP4CE10E22I8LN,FPGA-现场可编程门阵列芯片

1、MKV31F512VLL12 微控制器 (MCU) 是适用于BLDC、PMSM和ACIM电机控制应用的高性能解决方案。这些MCU采用运行频率为100MHz/120MHz、带数字信号处理 (DSP) 和浮点单元 (FPU) 的ARM Cortex-M4内核。KV3x MCU配备两个采样率高达1.2MS/s的16位ADC、多个控制定时器以及512KB闪存。 …