为了实现点击按钮,从相册中获取选取图片显示在ImageView这个功能可谓是一波多折。。。。。
最初是无法实现此功能,在网上找到了如下代码。
第一版
/**
* 从本地选择文件
*
* @param view
*/
public void chooseLocalImage(View view) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
startActivityForResult(intent, ACTION_CHOOSE_IMAGE);
}
实现将图片显示在ImageView中。
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ACTION_CHOOSE_IMAGE) {
if (data == null || data.getData() == null) {
Toast.makeText(this, R.string.get_picture_failed, Toast.LENGTH_SHORT).show();
return;
}
try {
mBitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), data.getData());
} catch (IOException e) {
e.printStackTrace();
return;
}
if (mBitmap == null) {
Toast.makeText(this, R.string.get_picture_failed, Toast.LENGTH_SHORT).show();
return;
}
Glide.with(ivShow.getContext())
.load(mBitmap)
.into(ivShow);
}
}
这个功能在相册中选择图片时,有的图片是经过旋转的,然后,又是各种搜百度,最后知道,问题的根源在于存储在手机相册里面的图片的方向有了角度导致显示不正。
第二版
最后的解决方案是:(添加如下代码)
int degree = util.readPictureDegree(getRealPathFromURI(data.getData()));
mBitmap = util.rotaingImageView(degree, mBitmap);
添加之后的代码如下:
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ACTION_CHOOSE_IMAGE) {
if (data == null || data.getData() == null) {
Toast.makeText(this, R.string.get_picture_failed, Toast.LENGTH_SHORT).show();
return;
}
try {
mBitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), data.getData());
//新加的代码
int degree = util.readPictureDegree(getRealPathFromURI(data.getData()));
mBitmap = util.rotaingImageView(degree, mBitmap);
} catch (IOException e) {
e.printStackTrace();
return;
}
if (mBitmap == null) {
Toast.makeText(this, R.string.get_picture_failed, Toast.LENGTH_SHORT).show();
return;
}
Glide.with(ivShow.getContext())
.load(mBitmap)
.into(ivShow);
}
}
图中有阴影的地方,就是新增的代码
其中readPictureDegree方法和rotaingImageView方法以及getRealPathFromURI方法如下:
/**
* 读取图片属性:旋转的角度
* @param path 图片绝对路径
* @return degree旋转的角度
**/
public static int readPictureDegree(String path) {
int degree = 0;
try {
ExifInterface exifInterface = new ExifInterface(path);
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
degree = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
degree = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
degree = 270;
break;
}
} catch (IOException e) {
e.printStackTrace();
}
return degree;
}
/**
* 旋转图片
* @param angle
* @param bitmap
* @return Bitmap
**/
public static Bitmap rotaingImageView(int angle , Bitmap bitmap) {
//旋转图片 动作
Matrix matrix = new Matrix();
matrix.postRotate(angle);
System.out.println("angle2=" + angle);
// 创建新的图片
Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
return resizedBitmap;
}
/**
* 根据Uri获取图片的真实路径
*
* @param contentURI 图片的Uri
* @return 图片的在手机中存储路径
*/
String getRealPathFromURI(Uri contentURI) {
String result;
Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
//不能直接调用contentprovider的接口函数,需要使用contentresolver对象,通过URI间接调用contentprovider
if (cursor == null) {
// Source is Dropbox or other similar local file path
result = contentURI.getPath();
} else {
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
result = cursor.getString(idx);
cursor.close();
}
return result;
}
第三版
然后用了一段时间后,当我想完善这个功能的时候,发现此功能又出现问题了。。。。在第二版中获取到的角度都是0,并且报错
java.io.FileNotFoundException:此处是图片路径 (Permission denied)
是无法获取手机内存的权限。在手机上安装的app的应用权限上也显示未获取到存储空间的权限,如下图所示。
之后冷静下来才想到,在出现问题后,在调用显示图片的activity时,手机不在出现有关存储空间权限的询问。又是一顿找度娘,最后找到了如下解决方案:
(实现询问用户是否授予此软件拥有操作存储空间的权限)
util.isGrantExternalRW(SingleImageActivity.this);
使用例子如图所示:(我是在页面完成刚完成初始化后,就开始询问用户)
isGrantExternalRW方法如下:
/**
* 解决安卓6.0以上版本不能读取外部存储权限的问题
* @param activity
* @return
*/
public static boolean isGrantExternalRW(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && activity.checkSelfPermission(
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
activity.requestPermissions(new String[]{
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
}, 1);
return false;
}
return true;
}
终于算是成功的完成此功能了,有点啰嗦,但是很实用,希望遇到此问题的小伙伴们可以认真的看完这篇博客,也希望此篇博客能帮助一些和我遇到相同困难的小伙伴们。。。