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

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实现将HTML文件与字符串转换为图片

《Java实现将HTML文件与字符串转换为图片》在Java开发中,我们经常会遇到将HTML内容转换为图片的需求,本文小编就来和大家详细讲讲如何使用FreeSpire.DocforJava库来实现这一功... 目录前言核心实现:html 转图片完整代码场景 1:转换本地 HTML 文件为图片场景 2:转换 H

Java实现在Word文档中添加文本水印和图片水印的操作指南

《Java实现在Word文档中添加文本水印和图片水印的操作指南》在当今数字时代,文档的自动化处理与安全防护变得尤为重要,无论是为了保护版权、推广品牌,还是为了在文档中加入特定的标识,为Word文档添加... 目录引言Spire.Doc for Java:高效Word文档处理的利器代码实战:使用Java为Wo

JWT + 拦截器实现无状态登录系统

《JWT+拦截器实现无状态登录系统》JWT(JSONWebToken)提供了一种无状态的解决方案:用户登录后,服务器返回一个Token,后续请求携带该Token即可完成身份验证,无需服务器存储会话... 目录✅ 引言 一、JWT 是什么? 二、技术选型 三、项目结构 四、核心代码实现4.1 添加依赖(pom

基于C#实现PDF转图片的详细教程

《基于C#实现PDF转图片的详细教程》在数字化办公场景中,PDF文件的可视化处理需求日益增长,本文将围绕Spire.PDFfor.NET这一工具,详解如何通过C#将PDF转换为JPG、PNG等主流图片... 目录引言一、组件部署二、快速入门:PDF 转图片的核心 C# 代码三、分辨率设置 - 清晰度的决定因

Python从Word文档中提取图片并生成PPT的操作代码

《Python从Word文档中提取图片并生成PPT的操作代码》在日常办公场景中,我们经常需要从Word文档中提取图片,并将这些图片整理到PowerPoint幻灯片中,手动完成这一任务既耗时又容易出错,... 目录引言背景与需求解决方案概述代码解析代码核心逻辑说明总结引言在日常办公场景中,我们经常需要从 W

基于Python实现自动化邮件发送系统的完整指南

《基于Python实现自动化邮件发送系统的完整指南》在现代软件开发和自动化流程中,邮件通知是一个常见且实用的功能,无论是用于发送报告、告警信息还是用户提醒,通过Python实现自动化的邮件发送功能都能... 目录一、前言:二、项目概述三、配置文件 `.env` 解析四、代码结构解析1. 导入模块2. 加载环

Python实战之SEO优化自动化工具开发指南

《Python实战之SEO优化自动化工具开发指南》在数字化营销时代,搜索引擎优化(SEO)已成为网站获取流量的重要手段,本文将带您使用Python开发一套完整的SEO自动化工具,需要的可以了解下... 目录前言项目概述技术栈选择核心模块实现1. 关键词研究模块2. 网站技术seo检测模块3. 内容优化分析模

linux系统上安装JDK8全过程

《linux系统上安装JDK8全过程》文章介绍安装JDK的必要性及Linux下JDK8的安装步骤,包括卸载旧版本、下载解压、配置环境变量等,强调开发需JDK,运行可选JRE,现JDK已集成JRE... 目录为什么要安装jdk?1.查看linux系统是否有自带的jdk:2.下载jdk压缩包2.解压3.配置环境

Java使用正则提取字符串中的内容的详细步骤

《Java使用正则提取字符串中的内容的详细步骤》:本文主要介绍Java中使用正则表达式提取字符串内容的方法,通过Pattern和Matcher类实现,涵盖编译正则、查找匹配、分组捕获、数字与邮箱提... 目录1. 基础流程2. 关键方法说明3. 常见场景示例场景1:提取所有数字场景2:提取邮箱地址4. 高级

使用Python实现无损放大图片功能

《使用Python实现无损放大图片功能》本文介绍了如何使用Python的Pillow库进行无损图片放大,区分了JPEG和PNG格式在放大过程中的特点,并给出了示例代码,JPEG格式可能受压缩影响,需先... 目录一、什么是无损放大?二、实现方法步骤1:读取图片步骤2:无损放大图片步骤3:保存图片三、示php