目录
需求
截图当前页面某个控件的内容,并且保存在本地,可分享。
需求分析
-
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();
}
@Override
public 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 path
result = 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 {
//保存失败
}
三、分享
调用系统图片进行分享
//由文件得到uri
Uri 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