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

来源:互联网 发布:电脑印章的软件 编辑:程序博客网 时间:2024/05/17 01:50

1.使用摄像头拍照

  代码中getExternalCacheDir()方法,获取的是应用关联缓存目录。我们要使用此目录来存放图片,为什么不用SD卡的其他目录,因为从Android 6.0开始,读写sd卡为危险权限,使用其他目录则需要运行时权限。代码中有一处判断系统版本,是因为从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=""/></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