拍照和选择相册(兼容高版本)

说明

本文章是为了满足,调用系统应用图库或者调用相机应用来得到图片的做法,
从根本上将就是从前面两个应用中提取文件路径(应用间通信),如果想完成二维码扫描之类的自定义相机,可以SufaceView+Camera类来完成。

拍照做法

简单来讲,先保证读写文件权限与打开相机权限,传递Uri对象(7.0以上通过FileProvider提供,别的通过Uri.fromFile就可以了)到相机中,然后就等拍照结果返回就可以了,如果裁剪的话,将新的Uri传递进去Crop系统裁剪界面。最后将返回结果处理就行了,具体看下面方法。

打开相机准备工作

 申请权限,需要下面两个权限:
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
     <uses-permission android:name="android.permission.CAMERA"/>
 在Android 6.0系统下,可以选择在清单文件中静态注册,在Android 6.0以上需要代码中动态申请,关于代
 码中动态申请,可以参照:
 http://blog.csdn.net/thanksforandroid/article/details/75105002

打开相机

File tempFile = new File(MineStudentFragment.this.getContext().getExternalCacheDir()
       , PHOTO_FILE_NAME);
/**生成一个文件,放在内置SD卡上,PHOTO_FILE_NAME是自己取的名字。*/
                    if (Build.VERSION.SDK_INT >= 24) {
                        uriP = FileProvider.getUriForFile(MineStudentFragment.this.getContext()
                                , "mooc.zhihuiyuyi.com.mooc.provider"
                                , tempFile);
                    } else {
                        uriP = Uri.fromFile(tempFile);
                    }
/**http://blog.csdn.net/thanksforandroid/article/details/76512616*/

                    if (uriP != null) {
  ForOpenCamera(uriP, REQUEST_PERMISSION_GALLERY_FIRST,Manifest.permission.WRITE_EXTERNAL_STORAGE);
                    } else {
                    ToastUtils.showShort(MineStudentFragment.this.getContext(), "未找到可用文件路径");
                    }
/**下面这个if - else 是为了给6.0网上系统动态申请写SD卡权限,ForOpenCamera()方法是自己写的*/

ForOpenCamera()方法

private void ForOpenCamera(Uri uriP, int permissionCode, String permission) {
        if (Build.VERSION.SDK_INT >= 23) {
            if (ContextCompat.checkSelfPermission(getContext(), permission) != PackageManager.PERMISSION_GRANTED) {
                MineStudentFragment.this.requestPermissions(new String[]{permission}, permissionCode);//没有就去申请,这里是因为当时是在Fragment中使用的,
                return;
            } else {
                startCamera(uriP);
            }
        } else {
            startCamera(uriP);
        }
    }
    /**参数说明,这里传进来一个Uri,是为了有权限时候直接去调用startCamera,permissionCode是权限
    申请码,方便动态申请权限之后,在权限回调中判断,permission,是你要申请的权限*/

假设用户没有权限,那么就回去申请,申请结果的回调如下:

 @Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {

    switch(requestCode){
            case REQUEST_PERMISSION_GALLERY_FIRST:
             /**这里之展示了一种case*/
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    //表示给了权限了
                    startCamera(uriP); 
                } else {
                    //表示没有权限,不能下一步
ToastUtils.showLong(MineStudentFragment.this.getContext(), "您把数据访问禁止了,你将不能享受服务。修改权限可以去设置中修改!");
                }
                break;
        }
    }
接下来看看startCamera()方法
public void startCamera(Uri uriP) {
        // 激活相机
        mIntent1 = new Intent("android.media.action.IMAGE_CAPTURE");
        mIntent1.putExtra(MediaStore.EXTRA_OUTPUT, uriP);
        requestPermissions(mIntent1,
                REQUEST_PERMISSION_CAREMA,
                Manifest.permission.CAMERA,
                PHOTO_REQUEST_CAREMA);
    }
    /**在这里获取打开相机的intent,然后调用自定义的requestPermissions()这个自定义方法*/
requestPermissions()方法:
private void requestPermissions(Intent intent, int permissionCode,
                                String permission, int requestCode) {
if (Build.VERSION.SDK_INT >= 23) {
            if (ContextCompat.checkSelfPermission(getContext(), permission) != PackageManager.PERMISSION_GRANTED) {
                MineStudentFragment.this.requestPermissions(new String[]{permission}, permissionCode);
                return;
            } else {
                startActivityForResult(intent, requestCode);
            }
        } else {
            startActivityForResult(intent, requestCode);
        }
    }
/***也是检查有没有打开相机权限,如果没有的话,就去申请,有的话,就去打开相机了,requestCode是为了
得到相机的返回值*/

假设用户也没有打开相机权限,那么权限回调如下,这里也只取关于相机权限部分:

public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {

        switch (requestCode) {
            case REQUEST_PERMISSION_CAREMA:
            /**这里只截取了一部分*/
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    startActivityForResult(mIntent1, PHOTO_REQUEST_CAREMA);
                } else {
 ToastUtils.showLong(MineStudentFragment.this.getContext(), "您把相机权限禁止了,您将不能享受服务。修改权限可以去设置中修改!");

                }
                break;
           }
}

正常走到现在,用户会进行拍照,当结果返回的时候:

@Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
   /**这里为了理解,只展示相机结果的回调*/     
  if (requestCode == PHOTO_REQUEST_CAREMA) {
            tempFile = new File(MineStudentFragment.this.getContext().getExternalCacheDir()
                    , PHOTO_FILE_NAME);
            if (Build.VERSION.SDK_INT >= 24) {
                if (getImageContentUri(MineStudentFragment.this.getContext(), tempFile) != null) {
      crop(getImageContentUri(MineStudentFragment.this.getContext(), tempFile));
                } else {
       ToastUtils.showShort(MineStudentFragment.this.getContext(), "拍照失败,稍后重试!");
                }
            } else {
                if (Uri.fromFile(tempFile) != null) {
                    crop(Uri.fromFile(tempFile));
                } else {
                    ToastUtils.showShort(MineStudentFragment.this.getContext(), "拍照失败,稍后重试!");
                }
            }
}
/**这里加了这么多层的嵌套,是为了避免空指针。下一步进行剪切,调用自定义的crop方法,它需要传一个Uri路
径,但是这里又存在问题,在Android 7.0网上版本,所需要的路径,不能直接同过Uri.fromFile来获得,
所以这里又多了一个判断*/
看看图片剪切的方法:
private void crop(Uri uri) {
        // 裁剪图片意图
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(uri, "image/*");
        intent.putExtra("crop", "true");
        // 裁剪框的比例,1:1
        intent.putExtra("aspectX", 1);
        intent.putExtra("aspectY", 1);
        // 裁剪后输出图片的尺寸大小
        intent.putExtra("outputX", 250);
        intent.putExtra("outputY", 250);

        intent.putExtra("outputFormat", "JPEG");// 图片格式
        intent.putExtra("noFaceDetection", true);// 取消人脸识别
        intent.putExtra("return-data", true);
        // 开启一个带有返回值的Activity,请求码为PHOTO_REQUEST_CUT
        startActivityForResult(intent, PHOTO_REQUEST_CUT);
    }

这里也是有一个startActivityForResult,接下来看看裁剪图片的返回结果的处理

public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
       if (requestCode == PHOTO_REQUEST_CUT) {
            // 返回剪切后的数据,这里为了展示,也只是保留一部分需要的一部分
            if (data != null && data.getParcelableExtra("data") != null) {
                mStream = new ByteArrayOutputStream();
                mBitmap = data.getParcelableExtra("data");
                mBitmap.compress(Bitmap.CompressFormat.PNG, 100, mStream);
                /**图片可以应用了*/
                /**接下来就是上传到服务器*/
                File files = creatFile(mBitmap);//变成文件
                putNET_Photo(files);
            } else {
                ToastUtils.showShort(MineStudentFragment.this.getContext(), "未知的错误发生了");
            }
        }
    }

createFile()方法是将Bitmap转换成文件的方法,这里多说一下,其实到这里拍照已经结束了

 private File creatFile(Bitmap bitmap) {
        File cache = new File(getActivity().getCacheDir() + File.separator + CACHE_DIR);
        BufferedOutputStream bos = null;
        File file = null;
        if (!cache.exists()) {
            cache.mkdirs();
        }
        try {
            file = new File(cache, USER_ICON_NAME);
            bos = new BufferedOutputStream(new FileOutputStream(file));
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
            bos.flush();
            bos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return file;
    }


相册

简单来讲, 就是先打开相册,选择完之后传递会数据过来 ,生成图片就好了。

准备工作

需要权限如下:

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

打开系统相册

mIntent2 = new Intent(Intent.ACTION_PICK);
                mIntent2.setType("image/*");
                requestPermissions(mIntent2,
                        REQUEST_PERMISSION_GALLERY,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE,
                        PHOTO_REQUEST_GALLERY);

针对于7.0以上,所以还是有动态获取权限,requestPermissions方法,

  private void requestPermissions(Intent intent, int permissionCode,
                                    String permission, int requestCode) {
 if (Build.VERSION.SDK_INT >= 23) {
if(ContextCompat.checkSelfPermission(getContext(), permission)!= PackageManager.PERMISSION_GRANTED) {
      MineStudentFragment.this.requestPermissions(new String[]{permission}, permissionCode);
                return;
            } else {
                startActivityForResult(intent, requestCode);
            }
        } else {
            startActivityForResult(intent, requestCode);
        }
    }
    /**此方法和上述相机哪里申请第二个权限的时候一样,不需要重写,只需要调用即可*/
权限申请结果
 @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {

        switch (requestCode) {
       
            case REQUEST_PERMISSION_GALLERY:
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    startActivityForResult(mIntent2, PHOTO_REQUEST_GALLERY); 
                } else {
                    ToastUtils.showLong(MineStudentFragment.this.getContext(), "您把数据访问禁止了,你将不能享受服务。修改权限可以去设置中修改!");

                }
                break;
           }
    }
/**这里直截取了一部分。*/

用户选完相片之后,看看对于结果的处理:

 @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == PHOTO_REQUEST_GALLERY) {
            // 从相册返回的数据
            if (data != null && data.getData() != null) {
                // 获取图片的全路径
                Uri uri_1 = data.getData();
                LogUtils.d("MineStudentFragment", "得到图片的全路径是:" + uri_1.toString());
                crop(uri_1);
            } else {
                ToastUtils.showShort(MineStudentFragment.this.getContext(), "选择相册失败,稍后重试!");
            }
        } 
    }
/**接下来就是调用crop方法,然后的处理就是和前面拍照一样了*/

####说明:
前面的权限结果回调方法还有Activity结果的回调方法,其实是在一块的,这里为了好理解,而分开了,这里也涉及到了权限动态申请还有FileProvider,这些 可以参考博客,
http://blog.csdn.net/thanksforandroid/article/details/75105002
http://blog.csdn.net/thanksforandroid/article/details/76512616

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值