前言
首先需要注意的是,目前截图有很多种,我今天在学习Bitmap的相关知识点时,只对View的截图进行了一个了解,以下的内容是对View内容截图的一个总结。整体实现的是截取图片然后将这张图片保存到手机外部存储中。接下来就对这个过程进行总结!
动态授权
因为这个操作涉及到文件的读写,然后我们可以知道,在安卓更新到一定版本之后,对用户的一些隐私权限需要进行一个动态授权,即单单在Manifest.xml中进行注册还不行。
Mainfest.xml注册权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Java代码中注册
需要注意的是,什么会话需要该权限就在该会话中进行注册。以下将核心代码放出:
//可以先进行判断,因为在23版本之前的系统是不需要动态授权的
if (Build.VERSION.SDK_INT>=23){
registerSystemPermissions();
}
private void registerSystemPermissions() {
//首先是判断所需的权限是否已经授权
/*,Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS*/
String[] strings = {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE};
//判断是否全部授权完毕
Boolean aBoolean = checkIsAllPermissionAllow(strings);
if (aBoolean){
//表示已经授权
//TODO
System.out.println("已授权");
}
else {
//没有授权需要进行授权
ActivityCompat.requestPermissions(this,strings,0*123);
}
}
private Boolean checkIsAllPermissionAllow(String[] strings) {
for (int i=0;i<strings.length;i++){
if (ContextCompat.checkSelfPermission(this,strings[i])!= PackageManager.PERMISSION_GRANTED){
return false;
}
}
return true;
}
其中整个动态授权中的核心代码其实也就是两句
ActivityCompat.requestPermissions(this,strings,0*123);
ContextCompat.checkSelfPermission(this,strings[i])!= PackageManager.PERMISSION_GRANTED
第一句是授权权限,第二句是判断是否已经授权权限。自此授权工作完成。
捕获View的截图信息
具体的目标就是获得整个View,然后将view进行Bitmap的转换。
View decorView = getWindow().getDecorView();
decorView.setDrawingCacheEnabled(true);
Bitmap drawingCache = decorView.getDrawingCache();
//将获得的view的bitmap进行复制
Bitmap bitmap = Bitmap.createBitmap(drawingCache);
decorView.setDrawingCacheEnabled(false);
值得注意的是,setDrawingCacheEnable是允许View进行一个缓存,用完记得将其关闭。获得了view以及将其转换为bitmap,就可以开始准备输出流对其进行输出。
BitmapFactory.options
这个方法上面的代码没有提及,但是这个方法可以有效避免OOM问题,具体使用如下:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
输出文件
按照我们之前IO流的学习,可以直接就会想到,对bitmap转换成byte[]进行一个输出的写操作,但是我们这边存在一个更加便捷的方式,还能更好的预防OOM的问题。
//选择存储文件夹
File externalStorageDirectory = Environment.getExternalStorageDirectory();
File file = new File(externalStorageDirectory, "/DCIM");
savePic(bitmap,file);
private void savePic(Bitmap outbitmap,File outputstream) {
if (!outputstream.exists()){
outputstream.mkdirs();
}
System.out.println(outputstream);
File file = new File(outputstream, System.currentTimeMillis() + ".png");
FileOutputStream fileOutputStream=null;
try {
fileOutputStream = new FileOutputStream(file);
boolean compress = outbitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
fileOutputStream.flush();
fileOutputStream.close();
if (compress){
Toast.makeText(CaptrueActivity.this, "截图成功", Toast.LENGTH_SHORT).show();
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
我们可以使用bitmap自带的compress方法进行输出,其实这个方法是可以用来缩放的,而且能很大程度下保留图片的质量,正所谓一举两得。
Bitmap.compress
这个方法存在三个参数,首先第一个是保存的格式,可以看到我们代码中是将其选择为png格式;第二参数则是非缩放率,像代码中的100,则代表压缩0%,以此类推;第三个参数则是输出流,即是我们将这个文件写到什么地方的输出流。
自此基本的截图操作就到此为止,下面将会贴上将为完整的代码仅供参考。
完整代码示例
package com.yjs.myapplication.Activity;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.text.format.Time;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.Toast;
import com.yjs.myapplication.R;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class CaptrueActivity extends AppCompatActivity {
private Button capturebtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_captrue);
//首先还是要申请一下权限,涉及到用户隐私的问题
if (Build.VERSION.SDK_INT>=23){
registerSystemPermissions();
}
Button captrueBtn = findViewById(R.id.capturebtn);
captrueBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//做一个截图操作
Runnable runnable = new Runnable() {
@Override
public void run() {
//获得XML文件的根view
View decorView = getWindow().getDecorView();
decorView.setDrawingCacheEnabled(true);
Bitmap drawingCache = decorView.getDrawingCache();
//获得了view之后可以重新设置view的大小
Bitmap bitmap = Bitmap.createBitmap(drawingCache);
decorView.setDrawingCacheEnabled(false);
//压缩完成后可以进行存储操作
File externalStorageDirectory = Environment.getExternalStorageDirectory();
File file = new File(externalStorageDirectory, "/DCIM");
savePic(bitmap,file);
}
private void savePic(Bitmap outbitmap,File outputstream) {
if (!outputstream.exists()){
outputstream.mkdirs();
}
System.out.println(outputstream);
File file = new File(outputstream, System.currentTimeMillis() + ".png");
FileOutputStream fileOutputStream=null;
try {
fileOutputStream = new FileOutputStream(file);
boolean compress = outbitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
fileOutputStream.flush();
fileOutputStream.close();
if (compress){
Toast.makeText(CaptrueActivity.this, "截图成功", Toast.LENGTH_SHORT).show();
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
};
runnable.run();
}
});
}
private void registerSystemPermissions() {
//首先是判断所需的权限是否已经授权
/*,Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS*/
String[] strings = {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE};
//判断是否全部授权完毕
Boolean aBoolean = checkIsAllPermissionAllow(strings);
if (aBoolean){
//表示已经授权
//TODO
System.out.println("已授权");
}
else {
//没有授权需要进行授权
ActivityCompat.requestPermissions(this,strings,0*123);
}
}
private Boolean checkIsAllPermissionAllow(String[] strings) {
for (int i=0;i<strings.length;i++){
if (ContextCompat.checkSelfPermission(this,strings[i])!= PackageManager.PERMISSION_GRANTED){
return false;
}
}
return true;
}
}