項目用到了選擇系統(tǒng)相機(jī)拍照和系統(tǒng)相冊机隙,裁剪圖片并設(shè)置頭像纽谒,找了找網(wǎng)上大神們的博客证膨,解決了選取相冊在android4.4崩潰和升級到android7.0后系統(tǒng)選取照片路徑的不同。(用的是Fresco設(shè)置圓形頭像)第一次做分享鼓黔,不喜勿噴央勒。代碼有點亂....
首先在建立相機(jī)存儲的緩存的路徑,在onCreate()方法里面設(shè)置:
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創(chuàng)建一個content類型的Uri(android 7.0需要這樣的方法訪問)
uri = FileProvider.getUriForFile(TTApplication.getApp(), "com.yf.toutiao", file);//使用在manifest里面設(shè)置的包名
}-
使用FileProvider要在在manifest中添加provider澳化,參考來至:(http://www.reibang.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>
還要在資源文件下創(chuàng)建相應(yīng)的xml文件(如上:則創(chuàng)建filepaths.xml)订歪。
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path path="" name="camera_photos" />
</paths>
3.按鈕點擊響應(yīng)系統(tǒng)相機(jī)和選取相冊
case R.id.take_camera:
if (PermissionUtil.hasCameraPermission(UserEditActivity.this)) {
uploadAvatarFromPhotoRequest();
}
break;
case R.id.take_photo:
uploadAvatarFromAlbumRequest();
break;調(diào)用相機(jī)和相冊的方法 /** * 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.回調(diào)方法里面裁剪照片(調(diào)用系統(tǒng)的裁剪方法)
@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) {
//調(diào)用系統(tǒng)裁剪方法進(jìn)行裁剪
startPhotoZoom(uri);
} else if (requestCode == REQUEST_CODE_CROUP_PHOTO) {
//獲取圖片路徑進(jìn)行設(shè)置
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.設(shè)置頭像和上傳服務(wù)器(用Retrofit肆捕,代碼沒有展示)
private void compressAndUploadAvatar(String fileSrc) {
//壓縮圖片
final File cover = FileUtil.getSmallBitmap(this, fileSrc);
//利用Fresco進(jìn)行緩存圖片和設(shè)置圓形圖片
GenericDraweeHierarchyBuilder builder = new GenericDraweeHierarchyBuilder(getResources());
GenericDraweeHierarchy hierarchy = builder
.setDesiredAspectRatio(1.0f)
.setFailureImage(R.mipmap.user_avatar_bg)//失敗設(shè)置的圖片
.setRoundingParams(RoundingParams.fromCornersRadius(100f))
.build();
//加載本地圖片刷晋,設(shè)置頭像
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);
}
/**
* 設(shè)置壓縮的圖片的大小設(shè)置的參數(shù)
*
* @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.當(dāng)然需要權(quán)限處理(部分文件未寫)
@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, "關(guān)閉攝像頭權(quán)限影響掃描功能");//自定義Dialog
} else {
Toast.makeText(this, "未獲取攝像頭權(quán)限", Toast.LENGTH_SHORT)
.show();
}
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
PS:部分代碼沒有上傳,(小米4.4系統(tǒng)上選取系統(tǒng)相冊有報圖庫停止慎陵,但不影響選取圖片眼虱,未找到解決辦法,有大神解決了求留言告知)席纽,還有一個就是在裁剪方法里面設(shè)置輸出的大小會讓圖片變得更清晰捏悬,不過圖片大小也會變大。喜歡的請關(guān)注润梯。有錯請指出过牙,不吝賜教。
源碼: https://github.com/yangfang521314/UserAvatar
如果你喜歡文章希望能順手在Github點個star哦纺铭!謝謝寇钉!