项目用到了选择系统相机拍照和系统相册,裁剪图片并设置头像,找了找网上大神们的博客,解决了选取相册在android4.4崩溃和升级到android7.0后系统选取照片路径的不同。(用的是Fresco设置圆形头像)第一次做分享,不喜勿喷。代码有点乱....
首先在建立相机存储的缓存的路径,在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里面设置的包名 }使用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