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

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

相关文章

基于Python开发Windows自动更新控制工具

《基于Python开发Windows自动更新控制工具》在当今数字化时代,操作系统更新已成为计算机维护的重要组成部分,本文介绍一款基于Python和PyQt5的Windows自动更新控制工具,有需要的可... 目录设计原理与技术实现系统架构概述数学建模工具界面完整代码实现技术深度分析多层级控制理论服务层控制注

linux系统中java的cacerts的优先级详解

《linux系统中java的cacerts的优先级详解》文章讲解了Java信任库(cacerts)的优先级与管理方式,指出JDK自带的cacerts默认优先级更高,系统级cacerts需手动同步或显式... 目录Java 默认使用哪个?如何检查当前使用的信任库?简要了解Java的信任库总结了解 Java 信

uni-app小程序项目中实现前端图片压缩实现方式(附详细代码)

《uni-app小程序项目中实现前端图片压缩实现方式(附详细代码)》在uni-app开发中,文件上传和图片处理是很常见的需求,但也经常会遇到各种问题,下面:本文主要介绍uni-app小程序项目中实... 目录方式一:使用<canvas>实现图片压缩(推荐,兼容性好)示例代码(小程序平台):方式二:使用uni

MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决

《MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决》MyBatis默认开启一级缓存,同一事务中循环调用查询方法时会重复使用缓存数据,导致获取的序列主键值均为1,... 目录问题原因解决办法如果是存储过程总结问题myBATis有如下代码获取序列作为主键IdMappe

Python进行word模板内容替换的实现示例

《Python进行word模板内容替换的实现示例》本文介绍了使用Python自动化处理Word模板文档的常用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友... 目录技术背景与需求场景核心工具库介绍1.获取你的word模板内容2.正常文本内容的替换3.表格内容的

Oracle数据库在windows系统上重启步骤

《Oracle数据库在windows系统上重启步骤》有时候在服务中重启了oracle之后,数据库并不能正常访问,下面:本文主要介绍Oracle数据库在windows系统上重启的相关资料,文中通过代... oracle数据库在Windows上重启的方法我这里是使用oracle自带的sqlplus工具实现的方

使用Go调用第三方API的方法详解

《使用Go调用第三方API的方法详解》在现代应用开发中,调用第三方API是非常常见的场景,比如获取天气预报、翻译文本、发送短信等,Go作为一门高效并发的编程语言,拥有强大的标准库和丰富的第三方库,可以... 目录引言一、准备工作二、案例1:调用天气查询 API1. 注册并获取 API Key2. 代码实现3

基于Go语言开发一个 IP 归属地查询接口工具

《基于Go语言开发一个IP归属地查询接口工具》在日常开发中,IP地址归属地查询是一个常见需求,本文将带大家使用Go语言快速开发一个IP归属地查询接口服务,有需要的小伙伴可以了解下... 目录功能目标技术栈项目结构核心代码(main.go)使用方法扩展功能总结在日常开发中,IP 地址归属地查询是一个常见需求:

使用python制作一款文件粉碎工具

《使用python制作一款文件粉碎工具》这篇文章主要为大家详细介绍了如何使用python制作一款文件粉碎工具,能够有效粉碎密码文件和机密Excel表格等,感兴趣的小伙伴可以了解一下... 文件粉碎工具:适用于粉碎密码文件和机密的escel表格等等,主要作用就是防止 别人用数据恢复大师把你刚删除的机密的文件恢

Android实现图片浏览功能的示例详解(附带源码)

《Android实现图片浏览功能的示例详解(附带源码)》在许多应用中,都需要展示图片并支持用户进行浏览,本文主要为大家介绍了如何通过Android实现图片浏览功能,感兴趣的小伙伴可以跟随小编一起学习一... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码