android选择系统相机拍照和系统相册,裁剪图片并保存和设置头像

项目用到了选择系统相机拍照和系统相册,裁剪图片并设置头像,找了找网上大神们的博客,解决了选取相册在android4.4崩溃和升级到android7.0后系统选取照片路径的不同。(用的是Fresco设置圆形头像)第一次做分享,不喜勿喷。代码有点乱....

  1. 首先在建立相机存储的缓存的路径,在onCreate()方法里面设置:
    SimpleDraweeView mSimpleDraweeView =(SimpleDraweeView)findViewById(R.id.user_avatar) ;
    file = new File(FileUtil.getCachePath(this), "user-avatar.jpg");
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
    uri = Uri.fromFile(file);
    } else {
    //通过FileProvider创建一个content类型的Uri(android 7.0需要这样的方法访问)
    uri = FileProvider.getUriForFile(TTApplication.getApp(), "com.yf.toutiao", file);//使用在manifest里面设置的包名
    }

  2. 使用FileProvider要在在manifest中添加provider,参考来至:(http://www.jianshu.com/p/3f9e3fc38eae

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

    还要在资源文件下创建相应的xml文件(如上:则创建filepaths.xml)。
    <?xml version="1.0" encoding="utf-8"?>
    <paths>
    <external-path path="" name="camera_photos" />
    </paths>
    3.按钮点击响应系统相机和选取相册
    case R.id.take_camera:
    if (PermissionUtil.hasCameraPermission(UserEditActivity.this)) {
    uploadAvatarFromPhotoRequest();
    }
    break;
    case R.id.take_photo:
    uploadAvatarFromAlbumRequest();
    break;

     调用相机和相册的方法
    
       /**
        *  camera
        */
       private void uploadAvatarFromPhotoRequest() {
         Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
         intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
         intent.putExtra(MediaStore.Images.Media.ORIENTATION, 0);
         intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
         startActivityForResult(intent, REQUEST_CODE_TAKE_PHOTO);
       }
    
       /**
        *  album
        */
         private void uploadAvatarFromAlbumRequest() {
         Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
         photoPickerIntent.setType("image/*");
         startActivityForResult(photoPickerIntent, REQUEST_CODE_ALBUM);
       }
    

4.回调方法里面裁剪照片(调用系统的裁剪方法)

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode != -1) {
        return;
    }
    if (requestCode == REQUEST_CODE_ALBUM && data != null) {
        Uri newUri;
          //android7.0和7.0以下的不同的uri
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
            newUri = Uri.parse("file:///" + CropUtils.getPath(this, data.getData()));
        } else {
            newUri = data.getData();
        }
        if (newUri != null) {
            startPhotoZoom(newUri);
        } else {
            ToastUtil.showToast(this, "没有得到相册图片", 0);
        }
    } else if (requestCode == REQUEST_CODE_TAKE_PHOTO) {
            //调用系统裁剪方法进行裁剪
            startPhotoZoom(uri);
    } else if (requestCode == REQUEST_CODE_CROUP_PHOTO) {
            //获取图片路径进行设置
            compressAndUploadAvatar(file.getPath());
    }
}
/**
 * 裁剪方法
 *
 * @param uri
 */
public void startPhotoZoom(Uri uri) {
    Intent intent = new Intent("com.android.camera.action.CROP");
    intent.setDataAndType(uri, "image/*");
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    intent.putExtra("crop", "true");// crop=true 有这句才能出来最后的裁剪页面.
    intent.putExtra("aspectX", 1);// 这两项为裁剪框的比例.
    intent.putExtra("aspectY", 1);// x:y=1:1
    // intent.putExtra("outputX", Constants.USER_AVATAR_MAX_SIZE);//图片输出大小,可以不需要
    //intent.putExtra("outputY", Constants.USER_AVATAR_MAX_SIZE);
    //注意这里的输出的是上面的文件路径的Uri格式,这样在才能获取图片
    intent.putExtra("output", Uri.fromFile(file));
    intent.putExtra("outputFormat", "JPEG");// 返回格式
    startActivityForResult(intent, REQUEST_CODE_CROUP_PHOTO);
}

5.设置头像和上传服务器(用Retrofit,代码没有展示)

  private void compressAndUploadAvatar(String fileSrc) {
    //压缩图片
    final File cover = FileUtil.getSmallBitmap(this, fileSrc);
    //利用Fresco进行缓存图片和设置圆形图片
    GenericDraweeHierarchyBuilder builder = new GenericDraweeHierarchyBuilder(getResources());
    GenericDraweeHierarchy hierarchy = builder
            .setDesiredAspectRatio(1.0f)
            .setFailureImage(R.mipmap.user_avatar_bg)//失败设置的图片
            .setRoundingParams(RoundingParams.fromCornersRadius(100f))
            .build();

    //加载本地图片,设置头像
    Uri uri = Uri.fromFile(cover);
    DraweeController controller = Fresco.newDraweeControllerBuilder()
            .setOldController(mSimpleDraweeView.getController())
            .setUri(uri)
            .build();
    mSimpleDraweeView.setHierarchy(hierarchy);
    mSimpleDraweeView.setController(controller);
}

6.存储文件方法

 public class FileUtil {
/**
 * 获取缓存路径
 * @param context
 * @return
 */
public static String getCachePath(Context context) {
    String cachePath = null;
    if (Environment.MEDIA_MOUNTED.equals(Environment
            .getExternalStorageState())
            || !Environment.isExternalStorageRemovable()) {
        cachePath = context.getExternalCacheDir().getPath();
    } else {
        cachePath = context.getCacheDir().getPath();
    }
    return cachePath;
  }

* 压缩图片方法
 *
 * @param context
 * @param fileSrc
 * @return
 */
public static File getSmallBitmap(Context context, String fileSrc) {
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(fileSrc, options);
    options.inSampleSize = calculateInSampleSize(options, 480, 800);
    DebugUtil.i(DebugUtil.TAG_YF, "options.inSampleSize-->" + options.inSampleSize);
    options.inJustDecodeBounds = false;
    Bitmap img = BitmapFactory.decodeFile(fileSrc, options);
    DebugUtil.i(DebugUtil.TAG_YF, "file size after compress-->" + img.getByteCount() / 256);
    String filename = context.getFilesDir() + File.separator + "video-" + img.hashCode() + ".jpg";
    saveBitmap2File(img, filename);
    return new File(filename);
}
/**
 * 设置压缩的图片的大小设置的参数
 *
 * @param options
 * @param reqWidth
 * @param reqHeight
 * @return
 */
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
    int height = options.outHeight;
    int width = options.outWidth;
    int inSampleSize = 1;
    if (height > reqHeight || width > reqWidth) {
        int heightRatio = Math.round(height) / reqHeight;
        int widthRatio = Math.round(width) / reqWidth;
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
      }
    return inSampleSize;
    }
 }

 /**
 * 保存bitmap到文件
 *
 * @param bmp
 * @param filename
 * @return
 */
public static boolean saveBitmap2File(Bitmap bmp, String filename) {
    Bitmap.CompressFormat format = Bitmap.CompressFormat.JPEG;
    int quality = 50;//压缩50% 100表示不压缩
    OutputStream stream = null;
    try {
        stream = new FileOutputStream(filename);
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return bmp.compress(format, quality, stream);
}

android4.4获取相册路径的方法(参考:http://blog.csdn.net/tempersitu/article/details/20557383

public class CropUtils {
@SuppressLint("NewApi")
public static String getPath(final Context context, final Uri uri) {

    final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

// DocumentProvider
      if (isKitKat && DocumentsContract.isDocumentUri(context, uri))   {
        // ExternalStorageProvider
        if (isExternalStorageDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];

            if ("primary".equalsIgnoreCase(type)) {
                return Environment.getExternalStorageDirectory() + "/" + split[1];
            }
        }
        // DownloadsProvider
        else if (isDownloadsDocument(uri)) {

            final String id = DocumentsContract.getDocumentId(uri);
            final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
            return getDataColumn(context, contentUri, null, null);
        }
        // MediaProvider
        else if (isMediaDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];
            Uri contentUri = null;
            if ("image".equals(type)) {
                contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            } else if ("video".equals(type)) {
                contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
            } else if ("audio".equals(type)) {
                contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
            }

            final String selection = "_id=?";
            final String[] selectionArgs = new String[]{split[1]};

            return getDataColumn(context, contentUri, selection, selectionArgs);
        }
    }
    // MediaStore (and general)
    else if ("content".equalsIgnoreCase(uri.getScheme())) {
        return getDataColumn(context, uri, null, null);
    }
    // File
    else if ("file".equalsIgnoreCase(uri.getScheme())) {
        return uri.getPath();
    }
    return null;
}
/**
 * Get the value of the data column for this Uri. This is useful for
 * MediaStore Uris, and other file-based ContentProviders.
 *
 * @param context       The context.
 * @param uri           The Uri to query.
 * @param selection     (Optional) Filter used in the query.
 * @param selectionArgs (Optional) Selection arguments used in the query.
 * @return The value of the _data column, which is typically a file path.
 */
private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
    Cursor cursor = null;
    final String column = "_data";
    final String[] projection = {column};
    try {
        cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
        if (cursor != null && cursor.moveToFirst()) {
            final int column_index = cursor.getColumnIndexOrThrow(column);
            return cursor.getString(column_index);
        }
    } finally {
        if (cursor != null)
            cursor.close();
    }
    return null;
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is ExternalStorageProvider.
 */
private static boolean isExternalStorageDocument(Uri uri) {
    return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is DownloadsProvider.
 */
private static boolean isDownloadsDocument(Uri uri) {
    return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is MediaProvider.
 */
private static boolean isMediaDocument(Uri uri) {
    return "com.android.providers.media.documents".equals(uri.getAuthority());
  }
}

7.当然需要权限处理(部分文件未写)

    @Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    switch (requestCode) {
        case PermissionUtil.REQUEST_SHOWCAMERA:
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Permission Granted
                uploadAvatarFromPhotoRequest();
            } else {
                if (!SharedPreferenceMark.getHasShowCamera()) {
                    SharedPreferenceMark.setHasShowCamera(true);
                    new DialogPermission(this, "关闭摄像头权限影响扫描功能");//自定义Dialog
                } else {
                    Toast.makeText(this, "未获取摄像头权限", Toast.LENGTH_SHORT)
                            .show();
                }
            }
            break;
        default:
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

PS:部分代码没有上传,(小米4.4系统上选取系统相册有报图库停止,但不影响选取图片,未找到解决办法,有大神解决了求留言告知),还有一个就是在裁剪方法里面设置输出的大小会让图片变得更清晰,不过图片大小也会变大。喜欢的请关注。有错请指出,不吝赐教。
源码: https://github.com/yangfang521314/UserAvatar
如果你喜欢文章希望能顺手在Github点个star哦!谢谢!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容