对View截图

在某些特殊场合需要对View进行截图,使用View里面的getDrawingCache()方法,返回一个Bitmap对象,就可以实现截图的功能。

代码如下

private Bitmap testViewSnapshot(View view) {
        //使控件可以进行缓存
        view.setDrawingCacheEnabled(true);
        //获取缓存的 Bitmap
        Bitmap drawingCache = view.getDrawingCache();
        //复制获取的 Bitmap
        drawingCache = Bitmap.createBitmap(drawingCache);
        //关闭视图的缓存
        view.setDrawingCacheEnabled(false);

        return  drawingCache;
    }

这个View可以是任意的控件,是不是截图非常简单呢,那么接下来就是将Bitmap存储到相册里面

将Bitmap保存到本地

主要步骤
这里只介绍按下“保存”后如何将一个Bitmap对象保存为图片文件的执行步骤,对图片的下载,图片到Bitmap对象的转换,Bitmap对象的格式转换和压缩,以及界面设计部分全部都忽略了。

  1. 确定存储路径
  2. 获取外部存储权限
  3. 确定文件名
  4. 保存到文件中
  5. 发送广播,
  6. 通知系统扫描保存后的文件 确定存储路径

1. 确定存储路径

目前,大多数应用都会在外部存储的根路径下建立一个类似包名的多层目录,以存储需要共享的文件。例如/storage/emulated/0/sogou/image/。
由于Android系统的碎片化问题,不同设备上外部存储的路径很可能会不同,因此,不能直接使用/storage/emulated/0/作为外部存储的根路径。

Android SDK中 Environment类 提供了getExternalStorageDirectory()方法来获取外部存储的根路径。示例如下:

//获取需要存储到本地的路径
  File file = new File( Environment.getExternalStorageDirectory(),"/Meet/");
  //如果文件夹不存在 就创建文件夹
    if(!file.exists()){
        file.mkdirs();
    }

需要注意的是Environment.getExternalStorageDirectory()返回的路径中最后一个字符不是/,如果需要创建子目录,需要在子目录的前后都加上/。

2. 获取外部存储权限

由于需要在外部存储中写文件,需要在AndroidManifest.xml中增加如下的权限声明。

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  
   <!--在sdcard中创建/删除文件的权限 -->
	<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
	tools:ignore="ProtectedPermissions" />

3. 确定文件名

为了确保每次保存图片的名字不一样,这里我们使用System.currentTimeMillis()来对图片进行命名

File path =  new File(file,System.currentTimeMillis()+".png");

4. 保存到文件中

保存图片文件时,通过Bitmap的compress()方法将Bitmap对象压缩到一个文件输出流中,然后flush()即可。示例如下。

FileOutputStream fileOutputStream = new FileOutputStream(path);
 // compress - 压缩的意思  将bitmap保存到本地文件中
 bitmap.compress(Bitmap.CompressFormat.PNG, 80, fileOutputStream);
 //存储完成后需要清除相关的进程
 fileOutputStream.flush();
 fileOutputStream.close();

至此,已经实现将Bitmap对象保存成外部存储中的一个png格式的文件。但此时该文件只是保存在外部存储的一个目录中,必须进入其所在的目录中才可以看到。在系统图库,相册和其他应用中无法看到新建的图片文件。为了让其他应用能够知道图片文件被创建,必须通知MediaProvider服务将新建的文件添加到图片数据库中。

Android系统中常驻一个MediaProvider服务,对应的进程名为android.process.media,此服务用来管理本机上的媒体文件,提供媒体管理服务。在系统开机或者收到外部存储的挂载消息后,MediaProvider会调用MediaScanner,MediaScanner会扫描外部存储中的所有文件,根据文件类型的后缀将文件信息保存到对应的数据库中,供其他APP使用。

MediaScannerReceiver是一个广播接收者,当它接收到特定的广播请求后,就会去扫描指定的文件,并根据文件信息将其添加到数据库中。当图片文件被创建后,就可以发送广播给MediaScannerReceiver,通知其扫描新建的图片文件。示例如下。

发送广播&&通知系统扫描保存后的文件 确定存储路径

//保存图片后发送广播通知更新数据库
 Uri uri = Uri.fromFile(path);
  Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
  intent.setData(uri);
  sendBroadcast(intent);

至此,已经可以成功的将图片保存到本地文件中了,并且可以在相册里面看到保存的图片。

完整的代码如下

//点击按钮 保存图片
private void clickDownload() {
    ll_download.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Bitmap bitmap = testViewSnapshot(ll_content);
            //将bitMap保存到相册中
            saveBitmap(bitmap);
        }
    });
    }

//对View控件里面的内容进行截图
private Bitmap testViewSnapshot(View view) {
        //使控件可以进行缓存
        view.setDrawingCacheEnabled(true);
        //获取缓存的 Bitmap
        Bitmap drawingCache = view.getDrawingCache();
        //复制获取的 Bitmap
        drawingCache = Bitmap.createBitmap(drawingCache);
        //关闭视图的缓存
        view.setDrawingCacheEnabled(false);

        return  drawingCache;
    }


//保存BitMap图片到本地文件
private void saveBitmap(Bitmap bitmap) {
        //获取需要存储到本地的路径
        File file = new File( Environment.getExternalStorageDirectory(),"/Meet/");
        //如果文件夹不存在 就创建文件夹
        if(!file.exists()){
            file.mkdirs();
        }
        File path =  new File(file,System.currentTimeMillis()+".png");
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(path);
            // compress - 压缩的意思  将bitmap保存到本地文件中
            bitmap.compress(Bitmap.CompressFormat.PNG, 80, fileOutputStream);
            //存储完成后需要清除相关的进程
            fileOutputStream.flush();
            fileOutputStream.close();
            //保存图片后发送广播通知更新数据库
            Uri uri = Uri.fromFile(path);
            Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
            intent.setData(uri);
            sendBroadcast(intent);
            Toast.makeText(this, "保存成功", Toast.LENGTH_SHORT).show();
        } catch (FileNotFoundException e) {
            LogUtils.i("error:"+e.toString());
        } catch (IOException e) {
            LogUtils.i("error:"+e.toString());
        }
        LogUtils.i(path.getPath());
    }

这里就只给出主要的代码了,只需要改下按钮的点击和对那个View进行截图即可使用.