android7.0调用相机拍照,相册选择以及剪切功能

最近开发新项目,头像上传问题因为一些问题浪费了一些时间,因为这个功能基本所有的APP都有,所以决定写个工具类,并说明一下我在写这个功能的时候遇到的问题,这也是我的第一篇个人博客

话不多说,步入正题

关键是Android7.0以后,获取Uri权限发生了变化,过去是Uri uri=Uri.fromfile(file), 现在是FileProvider.getUriForFile()

先来说一些解决步骤  

1.在res文件夹下面建立资源文件夹file_path(资源文件夹名字随便取)  //注意每个path代表的不同的路径,后面我会说为什么

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!--        xml文件是唯一设置分享的目录 ,不能用代码设置

         1.<files-path>        getFilesDir()  /data/data//files目录
         2.<cache-path>        getCacheDir()  /data/data//cache目录
         3.<external-path>     Environment.getExternalStorageDirectory()
         SDCard/Android/data/你的应用的包名/files/ 目录
         4.<external-files-path>     Context#getExternalFilesDir(String) Context.getExternalFilesDir(null).
         5.<external-cache-path>      Context.getExternalCacheDir().
     -->
    <!--    path :代表设置的目录下一级目录 eg:<external-path path="images/"
                整个目录为Environment.getExternalStorageDirectory()+"/images/"
            name: 代表定义在Content中的字段 eg:name = "myimages" ,并且请求的内容的文件名为default_image.jpg
                则 返回一个URI   content://com.example.myapp.fileprovider/myimages/default_image.jpg
    -->
    <!--当path 为空时 5个全配置就可以解决-->
    <!--下载apk-->
    <external-path path="." name="sdcard_files" />
 
</paths>
2.在清单文件中注册Provider
<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="(包名,其实可以自定义,我用包名)xxx.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <!--提供共享路径-->
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths"/>
</provider>
3.准备工作做好了,现在就开始写代码了
 一.Android6.0以后的动态权限准备,可以用原生获取,我用的EasyPermissions
   用法也很简单,我就说一下基本用法,想要了解具体用法的可以看最后的链接  
  在build.gladle中添加
  dependencies {    compile 'pub.devrel:easypermissions:1.0.1'}
 代码用法:
final int RC_CAMERA_CODE=998;//相机权限申请
final int RC_PHOTO_CODE=997;//相册权限申请
case R.id.tv_takephoto_id://拍照
    String[] perms={Manifest.permission.CAMERA,
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE};
    if (EasyPermissions.hasPermissions(this,perms)){
          //直接调用工具类实现拍照、
        headPicUtils.takephoto();
    }else{
        //申请拍照需要的权限
        EasyPermissions.requestPermissions(this,"拍照需要摄像头权限",RC_CAMERA_CODE,perms);
    }
    photoPopWindow.dissmiss();
    break;
case R.id.tv_gallery_id://从相册选择
    String[] perm={Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE};
    if (EasyPermissions.hasPermissions(this,perm)){
        headPicUtils.seletPhoto();
    }else{
        EasyPermissions.requestPermissions(this,"读取相册需要读取SD卡权限",RC_PHOTO_CODE,perm);
    }
    break;

 
//回调方法 
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    EasyPermissions.onRequestPermissionsResult(requestCode,permissions,grantResults,this);
}
//权限获取成功
@Override
public void onPermissionsGranted(int requestCode, List<String> perms) {
    switch (requestCode){
        case RC_CAMERA_CODE:
            //执行拍照
            headPicUtils.takephoto();
            break;
        case RC_PHOTO_CODE:
            headPicUtils.seletPhoto();
            break;
    }
}
//权限获取失败
@Override
public void onPermissionsDenied(int requestCode, List<String> perms) {
    switch (requestCode){
        case RC_CAMERA_CODE:
            ToastUtils.showToast(this,"拍照权限获取失败");
            break;
        case RC_PHOTO_CODE:
            ToastUtils.showToast(this,"相册读取权限获取失败");
            break;
    }
}
//工具类方法
/**
 * Created by 李浩 on 2018/6/8.
 * 适配7.0以上的头像更替功能
 * 剪切用到了UCrop,并且用到了EasyPermissions做动态权限申请
 *
 * 重点注意:path的路径需要和file_path中的path属性一致
 */

public class HeadPicUtils {
    //图片的存储路径,注意这里的路径需要和file_path文件中的一致,不然会出现midirs失败的问题
    final public static String path= Environment.getExternalStorageDirectory()+"/yixiuPro/photos/";
    final public static String authoritys="com.jiankangli.knowledge.jiankang_yixiupro.fileprovider";
    public static File file;
    Activity context;
    final int OPEN_CAMERA_CODE=112;
    final int OPEN_PHOTOALBUM_CODE=113;
    public HeadPicUtils(Activity context){
        this.context=context;
    }
    //拍照
    //Android 7.0以上的拍照
    public void takephoto(){
        //存储对象
        file = new File(path,System.currentTimeMillis()+".png");
        if (!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }
        Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        Uri imguri=getFileProviderUri();
        if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.N){//7.0以上
            //临时授权
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        }
        intent.putExtra(MediaStore.EXTRA_OUTPUT,imguri);
        context.startActivityForResult(intent,OPEN_CAMERA_CODE);
    }
    //相册
    public void seletPhoto() {
        if (hasSdcard()){
            Intent mOpenGalleryIntent=new Intent(Intent.ACTION_PICK);
            mOpenGalleryIntent.setType("image/*");
            context.startActivityForResult(mOpenGalleryIntent,OPEN_PHOTOALBUM_CODE);
        }else{
            ToastUtils.showToast(context,"设备没有SD卡");
        }
    }
    //7.0以上的地址获取Uri
    public Uri getFileProviderUri(){
        Uri uri;
        if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.N){
            uri= FileProvider.getUriForFile(context,authoritys,file);
        }else{
            uri=Uri.fromFile(file);
        }
        return uri;
    }
    //剪切方法,我用到了Ucorp,具体用法看文章末尾的链接
    public void cropRawPhoto(Uri uri) {
        // 修改配置参数(我这里只是列出了部分配置,并不是全部)
        UCrop.Options options = new UCrop.Options();
        // 修改标题栏颜色
        options.setToolbarColor(context.getResources().getColor(R.color.colorPrimary));
        // 修改状态栏颜色
        options.setStatusBarColor(context.getResources().getColor(R.color.colorPrimaryDark));
        // 隐藏底部工具
        options.setHideBottomControls(true);
        // 图片格式
        options.setCompressionFormat(Bitmap.CompressFormat.PNG);
        // 设置图片压缩质量
        options.setCompressionQuality(100);
        // 是否让用户调整范围(默认false),如果开启,可能会造成剪切的图片的长宽比不是设定的
        // 如果不开启,用户不能拖动选框,只能缩放图片
        options.setFreeStyleCropEnabled(true);

        Uri desUri=Uri.fromFile(new File(path,System.currentTimeMillis()+".png"));

        Log.i("TAG", "desUri: "+desUri);
        Log.i("TAG", "uri: "+uri);
        // 设置源uri及目标uri
        UCrop.of(uri,desUri)
                // 长宽比
                .withAspectRatio(1, 1)
                // 图片大小
                .withMaxResultSize(200, 200)
                // 配置参数
                .withOptions(options)
                .start(context);
    }
    //验证是否有SD卡
    public static boolean hasSdcard(){
        String state = Environment.getExternalStorageState();
        if(state.equals(Environment.MEDIA_MOUNTED)){
            return true;
        }else{
            return false;
        }
    }
}
在Activity中的回调方法

final int OPEN_CAMERA_CODE=112;
final int OPEN_PHOTOALBUM_CODE=113;
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == UCrop.RESULT_ERROR){
        ToastUtils.showToast(this,"图片剪裁失败");
        return;
    }
    if (resultCode == RESULT_OK) {
        switch (requestCode) {
            case OPEN_CAMERA_CODE://拍照
                //开始裁剪功能
                headPicUtils.cropRawPhoto(headPicUtils.getFileProviderUri());
                break;
            case OPEN_PHOTOALBUM_CODE:
                headPicUtils.cropRawPhoto(data.getData());
                break;
            case UCrop.REQUEST_CROP:
                //显示出来,并提交服务器
                Uri Cropuri=UCrop.getOutput(data);
                Log.i("TAG", "onActivityResult: "+Cropuri);
                Bitmap bitmap=BitmapFactory.decodeFile(Cropuri.getPath());
                fileImage.setImageBitmap(bitmap);
                File file=new File(Cropuri.getPath());
                //提交服务器
                //submithead(file);//这步不用看,自己去上传
                break;
        }
    }
}
 
大概就是这些了,最后放出UCrop 和EasyPermissions的我觉得写得不错的文章
EasyPermissions:https://blog.csdn.net/hexingen/article/details/78504814
UCrop:https://blog.csdn.net/little_soybean/article/details/52460222
第一次写博客,排版有点乱,大家有问题,可以在下面留言,我会在第一时间回复的

 


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值