调用系统相机,截图工具与图库(调用系统的图片内容提供者)

2024-05-14 00:38

本文主要是介绍调用系统相机,截图工具与图库(调用系统的图片内容提供者),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文件存储

        android中有两块文件存储区域:internal与external。在早期android手机中,大部分设备含有一个内置的,固定的存储区域,即internal;另外还有一个可移动的存储区域(如sd卡等)即external。internal指的是/data/data/包名下的目录,而外部存储就是通过手机内存或者sd卡,用户可以通过文件管理等软件看到并且可以进行操作的存储区域。

        对于internal来说,当用户卸载app后,系统会将该区域的文件清空,并且一般来说是只有当前app才能访问得到的。
        对于external却不一样,用户,别的app都可以直接访问到,卸载时也不会自己清空。

        getFileDir():获取当前应用的位于internal区域的文件夹。

        getCacheDir():获取当前应用的位于internal区域的临时缓存文件夹。该区域中的文件在不使用时应立即删除掉,并且文件夹的大小应该限制在一个合理的范围内(如1M)。当系统内存不足时,系统会自动回收该区域中的文件。

        openFileOutput(String,int):以流的形式打开getFileDir()目录中某个指定的文件,其中第一个参数表示要打开的文件的名字。如下:

try {FileOutputStream temp = openFileOutput("temp", MODE_PRIVATE);temp.write("这是测试了啊啊啊".getBytes());temp.close();File f = new File(getFilesDir(),"temp");FileInputStream inputStream = new FileInputStream(f);byte[] buffer = new byte[1024*10];int read = inputStream.read(buffer);String s = new String(buffer,0,read);Log.e("tAG",s);//s的值就是temp.write中写入的string} catch (Exception e) {e.printStackTrace();} 
        getFilesDir(),getCacheDir(),getDatabasePath(String)获取的是internal存储区域。
        getExternalFilesDir(),getExternalCacheDir():得到的便是external。一般来讲,它指的是sd卡中的/Android/data/包名。当app被卸载时,该文件夹下的所有文件也会被删除。
        Environment.getExternalStorageDirectory():得到的是sd卡的根路径,自己可以在该路径下建立指定名称的文件夹。

        Environment.getExternalStoragePublicDirectory(String):获取系统生成的某个文件夹在external中的路径。如参数为Environment.DIRECTORY_DCIM便可能获取到DCIM文件夹。

        读取external区域的文件时需要添加WRITE_EXTERNAL_STORAGE权限,添加该权限后,默认的也会有READ_EXTERNAL_STORAGE权限。但是读取internal区域的文件时,不需要添加任何权限。

调用系统相机

具体见代码

Intent intent = new Intent();intent.setAction("android.media.action.IMAGE_CAPTURE");intent.addCategory("android.intent.category.DEFAULT");Uri uri = Uri.fromFile(file);intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);startActivityForResult(intent, 100);

        其中intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri),它是指定拍照后的照片存储到哪一个文件中。之所以设置它,是因为有可能拍照后无法获取拍照的图片,所以就可以把要图片存储到一个指定的文件中,然后通过流的方式进行操作,避免获取不到图片。

        上述的方法是自己指定图片的存储位置(包括图片名)。但是有一个弊端:没有办法通过ContentResolver访问系统的图片库得到自己调用相机所照的图片。为此,可以用下面一个更简单方法来完成

Intent intent = new Intent();intent.setAction("android.media.action.IMAGE_CAPTURE");intent.addCategory("android.intent.category.DEFAULT");/** 先向图片库中添加一条空数据,得到一个uri。然后再向这个uri中添加图片。* 这样即省时,也安全。因为uri之类的都是由系统生在的。* 而且也可以在图片库中得到刚照的图片。*/ContentValues values = new ContentValues();Uri uri = SelectActivity.this.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, uri);intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);startActivityForResult(intent, 100);

        但上述方法也有一个问题:调用系统相机时已经向数据库中插入了一条数据,当从照相界面直接按返回键时,这条数据也是存在的,而且系统也会在相应的位置创建一个文件(这个文件的大小是0kb,但是实实在在的存在)。因此,当用ContentResolver去访问图片库,可以获得相应的路径,id等属性。然后用BitmapFactory去解析路径时,返回的bitmap为null。故此,在解析的时候一定要判断该路径中的文件是不是存在

调用系统截图工具

先看代码(参见http://blog.csdn.net/floodingfire/article/details/8144604)

Intent intent = new Intent("com.android.camera.action.CROP");intent.setDataAndType(uri, "image/*");intent.putExtra("crop", true);intent.putExtra("aspectX", 2);intent.putExtra("aspectY", 1);intent.putExtra("outputX", 150);intent.putExtra("outputY", 150);//intent.putExtra("return-data", true);intent.putExtra("return-data", false);intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(fileCrop));startActivityForResult(intent, 50);
        其中setDataAndType()中第一个参数指的是要截取的图片的Uri。

        outputX与outputY指的是截取的图片在保存的时候的大小。如代码中设置的是150*150,那么该图片在保存的时候的大小就是150*150。

        最后一个和调用相机的时候传入的参数是一样的,也是指定截取的图片要保存的位置。

        return_data为true和false的意思,参见http://blog.csdn.net/floodingfire/article/details/8144587。

由于有可能无法获取到图片,所以最好是使用指定文件存储路径的方法,不要直接使用intent.getExtras().getParcelable("data")这种形式。

        aspectX与aspectY:在截图时x,y的比例。要注意:即使设置了不同的数字,但是图片保存时的大小还是按outputX,outputY来保存。

具体如下图:


        还可以再设置一个参数,intent.putExtra("noFaceDetection", true);这是为了防止人脸识别的

调用系统图库

代码:

Intent intent = new Intent();intent.setAction(Intent.ACTION_PICK);intent.addCategory("android.intent.category.DEFAULT");intent.setType("image/*");startActivityForResult(intent, 140);
这样会打开系统的图库,把所有的图片都会列出来。

获取相应的图片:

if(data != null){//data是Intent类型的Uri uri = data.getData();//startPhotoZoom(uri);/*Bundle extras = data.getExtras();Bitmap bitmap = extras.getParcelable("data");*/}
        其中得到的uri便是用户所选择的图片的uri。下面看一下ImageGallery.java中的源代码:
Intent result = new Intent(null, img.fullSizeImageUri());if (myExtras != null && myExtras.getBoolean("return-data")) {// The size of a transaction should be below 100K.Bitmap bitmap = img.fullSizeBitmap(IImage.UNCONSTRAINED, 100 * 1024);if (bitmap != null) {result.putExtra("data", bitmap);}}setResult(RESULT_OK, result);finish();
        首先,在result初始化的时候,便传入了一个uri(img.fullSizeImageUri()),而这个值正是我们通过data.getData()得到的,它代表的是原图的uri。

        其次,在源码的if判断中还为result传入了"data"等值。这个值就是通过

Bundle extras = data.getExtras();
Bitmap bitmap = extras.getParcelable("data");

        获取到的。但是是要注意:这里得到的bitmap是一个缩略图,并不是原图片。而且有些时候不一定可以得到。因此,不建议使用这种方法,而建议使用data.getData()直接获取原图的uri,然后通过查询数据库获取图片的地址。如下:

                    Uri uri = data.getData();//图片的uriCursor query = getContentResolver().query(uri, new String[]{MediaStore.Images.Media.DATA}, null, null, null);query.moveToFirst();String path = query.getString(0);//图片的文件路径query.close();
        上述data.getData()获取的便是new Intent时传入的第二个参数,即图片在数据库中的uri。

访问系统的图片数据库

        android中为图片数据库设置了一个内容提供者。因此可以通过ContentResolver访问 。该数据库所在的位置为:/data/data/com.android.provider.media。

示例:

ContentResolver resolver = getContentResolver();//Context调用Cursor cursor = resolver.query(Media.EXTERNAL_CONTENT_URI,new String[] { Media.BUCKET_DISPLAY_NAME, Media.DISPLAY_NAME,Media.DATA }, null, null, null);if (cursor.moveToNext()) {String count = cursor.getString(0);String name = cursor.getString(1);//照片-/storage/sdcard1/相机/照片/IMG_20140327_125017.jpg--IMG_20140327_125017.jpgSystem.out.println(count + "-"+cursor.getString(2)+"--" + name);}
        其中Media为:android.provider.MediaStore.Images.Media;

由上面可知:

        Media.BUCKET_DISPLAY_NAME指的是图片所在的文件夹的名字,

        DATA指的是图片的绝对路径,

        DISPLAY_NAME图片名字(包含后缀名)。

        DATE_TAKEN:拍照时间

        TITLE:照片名(不包含后缀名)

        MIME_TYPE:类型

        SIZE:大小。以字节为单位(如:1474761约等于1.41M)。

数据库为



后面一部分:


        由于可以知道某一张图片所在的文件夹的名字(Media.BUCKET_DISPLAY_NAME)与该文件夹对应的id(Media.BUCKET_ID)。因此,可以得到手机中所有含有图片的文件夹。又由于也可以得到某个图片文件的绝对路径,因此可以做成QQ中图片的界面效果(先列出所有的含有图片的文件夹,然后点击进去查看该文件夹中所有的图片)。

         由于查询的时候有可能会很长,所以这里需要采用异步查询的方法。最好使用的是:AsyncQueryHandler。

代码:

//开启异步任务进行查询。使用系统自带的AsyncQueryHandler进行操作.它会自动的开启新线程进行查询,查询结束后,会执行onQueryCompleteAsyncQueryHandler handler = new AsyncQueryHandler(getContentResolver()) {@Overrideprotected void onQueryComplete(int token, Object cookie,Cursor cursor) {while (cursor.moveToNext()) {String id = cursor.getString(0);String name = cursor.getString(1);System.out.println(id + "----id----name:" + name);if (!bucketIds.contains(id)) {// 如果该id是第一次出现,就把该id给记录下来。并且不重复记录bucketIds.add(id);buckets.put(id, new BucketItem());}// 对同一个id的BucketItem进行赋值BucketItem item = buckets.get(id);// 对图片路径进行赋值List<ImageItem> images = item.getImages();if (images == null) {images = new ArrayList<ImageItem>();}ImageItem imageItem = new ImageItem();imageItem.setPath(cursor.getString(2));imageItem.setId(cursor.getString(3));images.add(imageItem);item.setImages(images);item.setId(id);item.setName(name);int count = item.getCount();item.setCount(++count);buckets.put(id, item);}cursor.close();begin();//数据封装完毕后,应该进行的操作。比如用ListView进行显示等。}};String[] projection = new String[] { Media.BUCKET_ID,Media.BUCKET_DISPLAY_NAME, Media.DATA, Media._ID };handler.startQuery(10, null, Media.EXTERNAL_CONTENT_URI,projection, null, null, null);





这篇关于调用系统相机,截图工具与图库(调用系统的图片内容提供者)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/987268

相关文章

使用Java实现通用树形结构构建工具类

《使用Java实现通用树形结构构建工具类》这篇文章主要为大家详细介绍了如何使用Java实现通用树形结构构建工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录完整代码一、设计思想与核心功能二、核心实现原理1. 数据结构准备阶段2. 循环依赖检测算法3. 树形结构构建4. 搜索子

在C#中调用Python代码的两种实现方式

《在C#中调用Python代码的两种实现方式》:本文主要介绍在C#中调用Python代码的两种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#调用python代码的方式1. 使用 Python.NET2. 使用外部进程调用 Python 脚本总结C#调

使用Python实现获取网页指定内容

《使用Python实现获取网页指定内容》在当今互联网时代,网页数据抓取是一项非常重要的技能,本文将带你从零开始学习如何使用Python获取网页中的指定内容,希望对大家有所帮助... 目录引言1. 网页抓取的基本概念2. python中的网页抓取库3. 安装必要的库4. 发送HTTP请求并获取网页内容5. 解

利用Python开发Markdown表格结构转换为Excel工具

《利用Python开发Markdown表格结构转换为Excel工具》在数据管理和文档编写过程中,我们经常使用Markdown来记录表格数据,但它没有Excel使用方便,所以本文将使用Python编写一... 目录1.完整代码2. 项目概述3. 代码解析3.1 依赖库3.2 GUI 设计3.3 解析 Mark

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件

Linux系统之主机网络配置方式

《Linux系统之主机网络配置方式》:本文主要介绍Linux系统之主机网络配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、查看主机的网络参数1、查看主机名2、查看IP地址3、查看网关4、查看DNS二、配置网卡1、修改网卡配置文件2、nmcli工具【通用

Linux系统之dns域名解析全过程

《Linux系统之dns域名解析全过程》:本文主要介绍Linux系统之dns域名解析全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、dns域名解析介绍1、DNS核心概念1.1 区域 zone1.2 记录 record二、DNS服务的配置1、正向解析的配置

SpringCloud之LoadBalancer负载均衡服务调用过程

《SpringCloud之LoadBalancer负载均衡服务调用过程》:本文主要介绍SpringCloud之LoadBalancer负载均衡服务调用过程,具有很好的参考价值,希望对大家有所帮助,... 目录前言一、LoadBalancer是什么?二、使用步骤1、启动consul2、客户端加入依赖3、以服务

Python实现常用文本内容提取

《Python实现常用文本内容提取》在日常工作和学习中,我们经常需要从PDF、Word文档中提取文本,本文将介绍如何使用Python编写一个文本内容提取工具,有需要的小伙伴可以参考下... 目录一、引言二、文本内容提取的原理三、文本内容提取的设计四、文本内容提取的实现五、完整代码示例一、引言在日常工作和学

jvm调优常用命令行工具详解

《jvm调优常用命令行工具详解》:本文主要介绍jvm调优常用命令行工具的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一 jinfo命令查看参数1.1 查看jvm参数二 jstack命令2.1 查看现场堆栈信息三 jstat 实时查看堆内存,gc情况3.1