安卓View的截图并将其保存到手机外部存储文件夹

前言

首先需要注意的是,目前截图有很多种,我今天在学习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;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值