文档章节

android调用系统相机拍照

YougaKing
 YougaKing
发布于 2016/09/06 16:17
字数 1459
阅读 1451
收藏 3

获取缩略图

直接调取相机拍照,无需任何权限,但是只能获取到缩略图

       Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
       if (takePictureIntent.resolveActivity(getPackageManager()) != null) {//判断是否有相机应用
           startActivityForResult(takePictureIntent, REQ_THUMB);
       }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case REQ_THUMB://返回结果
                if (resultCode != Activity.RESULT_OK) return;
                Bundle extras = data.getExtras();
                Bitmap imageBitmap = (Bitmap) extras.get("data");
                mImageView.setImageBitmap(imageBitmap);
                break;
        }
    }

 图片很模糊。一般不采取此种方式

保存全尺寸照片

调取相机拍照保存一个全尺寸的照片,必须提供完整的文件名,相机应用自动保存照片。此时也无需任何权限,创建一个空的临时文件用来保存图片,使用日期时间戳新照片返回一个唯一的文件名

    String mCurrentPhotoPath;
    private File createImageFile() throws IOException {
        // Create an image file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date());
        String imageFileName = "JPEG_" + timeStamp + "_";
        //.getExternalFilesDir()方法可以获取到 SDCard/Android/data/你的应用的包名/files/ 目录,一般放一些长时间保存的数据
        File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        //创建临时文件,文件前缀不能少于三个字符,后缀如果为空默认未".tmp"
        File image = File.createTempFile(
                imageFileName,  /* 前缀 */
                ".jpg",         /* 后缀 */
                storageDir      /* 文件夹 */
        );
        mCurrentPhotoPath = "file:" + image.getAbsolutePath();
        return image;
    }

每执行一次就会创建一个空的文件

利用上述方法创建的文件只能是自己的app访问,随着app的卸载,文件也会删除。对于Android N以下,文件直接Uri.fromFile(file)就可以直接使用,Audroid N 即编译app的版本 compileSdkVersion 24时,此时会报出FileUriExposedException异常,解释如下:

  • 对于面向 Android N 的应用,Android 框架执行的 StrictMode,API 禁止向您的应用外公开 file://URI。
    如果一项包含文件 URI 的 Intent 离开您的应用,应用失败,并出现 FileUriExposedException异常。

  • 若要在应用间共享文件,您应发送一项 content://URI,并授予 URI 临时访问权限。
    进行此授权的最简单方式是使用 FileProvider类。 如需有关权限和共享文件的更多信息,
    请参阅共享文件

        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // Ensure that there's a camera activity to handle the intent
        if (takePictureIntent.resolveActivity(getPackageManager()) != null) {//判断是否有相机应用
            // Create the File where the photo should go
            File photoFile = null;
            try {
                photoFile = createImageFile();//创建临时图片文件
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            // Continue only if the File was successfully created
            if (photoFile != null) {
                //FileProvider 是一个特殊的 ContentProvider 的子类,
                //它使用 content:// Uri 代替了 file:/// Uri. ,更便利而且安全的为另一个app分享文件
                Uri photoURI = FileProvider.getUriForFile(this,
                        "com.example.android.fileprovider",
                        photoFile);
                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
                startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
            }
        }

现在,需要配置FileProvider。在应用程序的清单,提供者添加到您的应用程序,authorities="applicationId.fileprovider",使用时

Uri photoURI = FileProvider.getUriForFile(context,"applicationId.fileprovider", photoFile)

清单中authorities 和 参数authority保持一致。

        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.youga.capturingphotos.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths"/>
        </provider>
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="my_images" path="Android/data/com.youga.capturingphotos.name/files/Pictures" />
</paths>
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case REQUEST_TAKE_PHOTO://返回结果
                if (resultCode != Activity.RESULT_OK) return;
                mImageView.setImageBitmap(BitmapFactory.decodeFile(mCurrentPhotoPath));
                break;
        }
    }

关于FileProvider

FileProvider 是 ContentProvider 的一个特殊的子类,它有利于安全地分享应用相关的文件,通过对一个文件创建content:// Uri而不是file:/// Uri

由于FileProvider的默认功能包括文件的content URI的生成,你并不需要在代码中定义一个子类。相反,你可以在你的应用中包含一个FileProvider通过在XML文件中指定它。对于指定FileProvider,添加一个<provider>元素在你应用的清单文件中。设置android:name属性为android.support.v4.content.FileProvider。根据你控制的域名设置android:authorities属性为一个URI authority(authorities可以随意填写,但是要保证使用时与authority保持一致,推荐applicationId.fileprovider,以免定义重复)。设置android:exported属性为false;FileProvider不需要公开。设置android:grantUriPermissions属性为true,为了允许你进行临时访问文件的授权。

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.youga.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths"/>
</provider>

一个FileProvider只能生成一个content URI 对应你事先指定目录下的文件。对于指定一个目录,使用<paths>元素的子元素,在XML中指定它的存储区域和路径。例如,下面的paths元素告诉FileProvider你打算请求你的私有文件区域的 images/ 子目录的content URIs

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="my_images" path="Android/data/com.youga.capturingphotos/files/Pictures/" />
    <external-path name="images" path="Pictures/" />
</paths>

file-path 表示你应用内部存储区域的文件的子目录。这个子目录和getFilesDir()的返回值一样。external-path 表示你应用外部存储区域的文件的子目录。这个子目录和getExternalFilesDir()的返回值一样。cache-path 表示你应用内部存储区域的缓存子目录。这个子目录的根目录和getCacheDir()的返回值一样。(如果你修改了provider和paths中的值,需要把应用卸载重装或者开关机一下才能看到变化。)

照片添加到图库

上述保存全尺寸图片时,创建图片临时文件在目录getExternalFilesDir()中,图库无法访问到,我们可以直接创建文件在Environment.getExternalStorageDirectory()目录下;然后发送一个广播让图库更新就好了。当然也可以直接创建文件在图库目录下(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)),即DCIM。此时需要SD卡读写权限。

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
File path = Environment.getExternalStoragePublicDirectory(
        Environment.DIRECTORY_DCIM);
// Create an image file name
Log.i(TAG, "path:" + path.getAbsolutePath());
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date());
String imageFileName = "JPEG_" + timeStamp;
File image = File.createTempFile(
        imageFileName,  /* 前缀 */
        ".jpg",         /* 后缀 */
        path      /* 文件夹 */
);
mPublicPhotoPath = image.getAbsolutePath();

同时发送广播

Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(mPublicPhotoPath);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
sendBroadcast(mediaScanIntent);

源码放在github上,https://github.com/YougaKing/CapturingPhotos

© 著作权归作者所有

共有 人打赏支持
YougaKing
粉丝 6
博文 7
码字总数 6795
作品 0
西安
程序员
私信 提问
加载中

评论(4)

YougaKing
YougaKing

引用来自“小白白转小牛牛”的评论

有没有详细一点的源码可以看看 上面的链接打不开@YougaKing 多谢了 小白一个
源码在github上,github一般不会被强,多试几次就好了。https://github.com/YougaKing/CapturingPhotos
小白白转小牛牛
有没有详细一点的源码可以看看 上面的链接打不开@YougaKing 多谢了 小白一个
YougaKing
YougaKing

引用来自“Hideeee”的评论

非常好。 居然没人评论。
多谢支持,:laughing:
Hideeee
Hideeee
非常好。 居然没人评论。
Android 调用系统拍照 笔记

由于临时需要做个简单的Android程序,其中涉及调用系统拍照并保存照片。之前没有任何Java和Android经验,coding中遇到不少问题,特记录以供参考。 Google一下能找到不少现成的调用系统拍照的...

会说话的哑巴
2012/09/07
0
0
项目需求讨论 - WebView下拍照及图片选择功能

前言: 如果觉得掘金上看图片放大看不清楚,可以跳到另外的同步发布的链接看,放大图片下部有个可以查看原图功能,很清楚:项目需求讨论 - WebView下拍照及图片选择功能 现在很多app里面,都...

青蛙要fly
06/23
0
0
组长问我几天能开发一个人见人爱的百万量级Android相机,我是这样回答的...

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由QQ空间开发团队发表于云+社区专栏 最近我负责开发了一个跟Android相机有关的需求,新功能允许用户使用手机摄像头,快速拍摄...

腾讯云+社区
09/19
0
0
关于调用Android照相功能获取图片

最近在项目中调用相机,使用了别人写好的文件,但发现获取的照片没真正使用系统照相拍照再查看那么清晰,于是研究了一下,发现通常调用照相功能获取的图片都是被压缩的,如果要获取原照,那得...

tyronejw
2015/08/18
0
0
Android 使用摄像头拍照

1、布局main.xml android:id="@+id/mySurfaceView"android:gravity="center_horizontal" android:id="@+id/btnOpen"android:textSize="18px"...

veidy
2013/05/25
0
0

没有更多内容

加载失败,请刷新页面

加载更多

(三)Honghu Cloud云架构一定时调度平台

2018-11-16 14:45:08 产品简介 鸿鹄云架构是一个完全由Java编写的开源任务调度框架,为企业在任务调度提供了简单却强大的机制。开发人员根据业务规则,使用调度平台简单配置,就可以让任务在...

itcloud
5分钟前
0
0
护航Lazada双11购物节 阿里云CDN全球化火力全开

摘要: Lazada是东南亚最大B2C平台,业务范围覆盖印度尼西亚、马来西亚、菲律宾、新加坡、泰国和越南六个东南亚国家,覆盖大约6亿消费者。在双11期间,阿里云CDN为Lazada电商内容加速,并且通...

阿里云官方博客
5分钟前
0
0
常用设计模式之代理模式解析

1. 简介 代理模式(Proxy Pattern)是常用设计模式之一。代理模式的定义:Provide a surrogate or placeholder for another object to controlaccess to it(为其他对象提供一种代理以控制对这个...

老道士
5分钟前
0
0
Vue瀑布流插件的使用示例

我自己写的一个的Vue瀑布流插件,列数自适应,不用设置每个卡片的高度。 测试页面:Page.vue 模板页面:WaterFollow.vue 和 WFColumn.vue 在Page.vue中,修改itemW的值,设置每列的最小宽度。...

peakedness丶
6分钟前
0
0
多种负载均衡算法及其Java代码实现【网络上较好的转载】

首先给大家介绍下什么是负载均衡(来自百科) 负载均衡 建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展 网络设备和 服务器的带宽、增加 吞吐量、加强网络数据处理能力、提高网...

stys352
10分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部