Android读书笔记(五)使用摄像头、从相册获取图片

1.使用摄像头拍照

  代码中getExternalCacheDir()方法,获取的是应用关联缓存目录。我们要使用此目录来存放图片,为什么不用SD卡的其他目录,因为从Android 6.0开始,读写sd卡为危险权限,使用其他目录则需要运行时权限。(在android 7.1.1中使用getExternalCacheDir()目录,创建文件被禁止,应该也是需要运行时权限。使用geCacheDir()目录,创建文件不会被禁止。)
  代码中有一处判断系统版本,是因为从Android 7.0系统开始,直接使用本地真实路径Uri被认为是不安全的,为了解决这个问题我们需要使用FileProvider。

 take_photo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //用来存放拍摄的照片
                File outputImage = new File(getExternalCacheDir(), "output_image.jpg");
                //文件存在就删除
                if (outputImage.exists()) {
                    outputImage.delete();
                }
                try {
                    outputImage.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                //判断系统版本是否高于7.0
                if (Build.VERSION.SDK_INT >= 24) {

                    //getUriForFile(),参数一:context、参数二:任意的唯一字符、参数三:file对象
                    imageUri = FileProvider.getUriForFile(Main6Activity.this
                            ,"cn.xd.study.a6", outputImage);
                } else {
                    //获取uri
                    imageUri = Uri.fromFile(outputImage);
                }
                //进行拍照
                Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
                //设置输出路径
                intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
                startActivityForResult(intent, TAKE_PHOTO);
            }
        });

  拍完照片后,我们在onActivityResult()中进行处理。

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            try {
                //读取刚拍的照片,显示出来
                Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver()
                        .openInputStream(imageUri));
                picture.setImageBitmap(bitmap);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

  实现拍照功能的代码已经写完了,接下来还需要配置一下provider。编辑AndroidManifest.xml文件,在application下添加provider。

        <provider
            <!--name为固定值-->
            android:name="android.support.v4.content.FileProvider"
             <!--authorities的值要与FileProvider.getUriForFile()中参数二相同-->
            android:authorities="cn.xd.study.a6"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                <!--name为固定值-->
                android:name="android.support.FILE_PROVIDER_PATHS"
                <!--resource引用了a.xml文件,a.xml中设置了共享的路径-->
                android:resource="@xml/a" />
        </provider>

  创建a.xml文件,在project目录方式下,项目名→app→src→main→res,在res文件下创建xml文件目录和a.xml文件。a.xml文件如下:

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <!--name 任意,path 共享的具体路径,path为空表示共享整个sd卡-->
    <external-path name="my_images" path=""/>
       <!--使用getCacheDir()对应cache-path-->
   <cache-path name="cache" path="" />
</paths>

基本完成了,还有个小尾巴,兼容android 4.4系统之前的版本,访问sd卡需要声明权限。

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

2.从相册中选择照片

  为了更好的兼容性,下面的程序运行之前,需要使用运行时权限,运行时权限就不展示了(读写权限)。

    //打开相册
    private void openAlbum() {
        Intent intent = new Intent("android.intent.action.GET_CONTENT");
        intent.setType("image/*");
        startActivityForResult(intent, CHOOSE_PHOTO);//CHOOSE_PHOTO=2
    }

  选择照片完成后,需要使用onActivityResult()方法来处理。

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == CHOOSE_PHOTO) {
            //判断版本是否大于4.4并且是否选择了照片,从而执行不同的方法
            //这是由于从4.4版本开始,选取相册中的图片不再返回真实的uri,需要对uri进行解析
            if (Build.VERSION.SDK_INT >= 19 && resultCode != 0) {
                handleImageOnKitKat(data);
            } else if (resultCode != 0) {
                handleImageBeforeKitKat(data);
            }
        }
    }
    //4.4及版本以上,要对uri进行处理,才能获取到真实的路径
    @TargetApi(19)//指定该方法用于4.4版本及以上版本
    private void handleImageOnKitKat(Intent data) {

        String imagesPath = null;
        Uri uri = data.getData();
        if (DocumentsContract.isDocumentUri(Main7Activity.this, uri)) {
            //从android 7.0操作,
            //content://com.android.providers.media.documents/document/image:40
            //getDocumentId()获取的是ID,40
            String docId = DocumentsContract.getDocumentId(uri);
            //从相册选取图片,uri中的Authority为com.android.providers.media.documents。
            if ("com.android.providers.media.documents".equals(uri.getAuthority())) {
                String id = docId.split(":")[1];
                String selection = MediaStore.Images.Media._ID + "=" + id;
                imagesPath = getImagesPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI
                        , selection);
                //没能测试
            } else if ("com.android.providers.downloads.documents".equals(
                        uri.getAuthority())) {
                Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads")
                                        , Long.valueOf(docId));
                imagesPath = getImagesPath(contentUri, null);
            }
            //4.4模拟器选择图片,content://media/external/images/media/12
        } else if ("content".equalsIgnoreCase(uri.getScheme())) {
            imagesPath = getImagesPath(uri, null);
            //在4.4系统红米1s选择图片的uri
            //file:///storage/sdcard1/DCIM/Camera/IMG_20170623_105806.jpg
        } else if ("file".equalsIgnoreCase(uri.getScheme())) {
            imagesPath = uri.getPath();
        }
        displayImage(imagesPath);
    }
    private void handleImageBeforeKitKat(Intent data) {
        Uri uri = data.getData();
        String imagePath = getImagesPath(uri, null);
        displayImage(imagePath);
    }
    //获取真实的路径
    private String getImagesPath(Uri uri, String selection) {
        String path = null;
        Cursor cursor = getContentResolver().query(uri, null, selection, null, null);
        if (cursor != null) {
            if (cursor.moveToFirst()) {
                path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
            }
            cursor.close();
        }
        return path;
    }

  displayImage()方法用来展示图片。选取照片所需权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值