Android开发 调用系统相机相册图片功能,解决小米手机拍照或者图片横竖相反问题,及小米手机相册图片路径问题
1.调用相机,兼容7.0
AndroidManifest配置
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="xxx.xxx.xxx"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
authorities="applicationId.fileprovider"
如果有其他第三方包配置过provider,可以自定义继承FileProvider例如
public class MyFileProvider extends FileProvider {
}
<provider
android:name=".MyFileProvider"
android:authorities="${applicationId}.provider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
在资源文件中 新建xml文件夹,然后对应上面的resource 文件名 filepaths
<?xml version="1.0" encoding="utf-8"?>
<resources>
<paths>
<external-path
name="image"
path="" />
</paths>
</resources>
file-path 表示你应用内部存储区域的文件的子目录。这个子目录和getFilesDir()的返回值一样。external-path 表示你应用外部存储区域的文件的子目录。这个子目录和getExternalFilesDir()的返回值一样。cache-path 表示你应用内部存储区域的缓存子目录。这个子目录的根目录和getCacheDir()的返回值一样。(如果你修改了provider和paths中的值,需要把应用卸载重装或者开关机一下才能看到变化。)
FileProvider 是 ContentProvider 的一个特殊的子类,它有利于安全地分享应用相关的文件,通过对一个文件创建content:// Uri而不是file:/// Uri。
由于FileProvider的默认功能包括文件的content URI的生成,你并不需要在代码中定义一个子类。相反,你可以在你的应用中包含一个FileProvider通过在XML文件中指定它。对于指定FileProvider,添加一个元素在你应用的清单文件中。设置android:name属性为android.support.v4.content.FileProvider。根据你控制的域名设置android:authorities属性为一个URI authority(authorities可以随意填写,但是要保证使用时与authority保持一致,推荐applicationId.fileprovider,以免定义重复)。设置android:exported属性为false;FileProvider不需要公开。设置android:grantUriPermissions属性为true,为了允许你进行临时访问文件的授权。
一个FileProvider只能生成一个content URI 对应你事先指定目录下的文件。对于指定一个目录,使用元素的子元素,在XML中指定它的存储区域和路径。例如,下面的paths元素告诉FileProvider你打算请求你的私有文件区域的 images/ 子目录的content URIs
<files-path
name="name"
path="path"/> <!--相当 Context.getFilesDir() + path, name是分享url的一部分-->
<cache-path
name="name"
path="path"/> <!--getCacheDir()-->
<external-path
name="name"
path="path"/> <!--Environment.getExternalStorageDirectory()-->
<external-files-path
name="name"
path="path"/><!--getExternalFilesDir(String) Context.getExternalFilesDir(null)-->
<external-cache-path
name="name"
path="path"/> <!--Context.getExternalCacheDir()-->
拍照
/**
* 拍照
*/
protected void takePic() {
Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File file = new File(FileConstanse.getCacheImagePath(), FileConstanse.IMAGE_CACHE);
tempUri = Uri.fromFile(file);
// 指定照片保存路径(SD卡)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//7.0及以上使用FileProvider获取Uri
openCameraIntent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
String authority = getPackageName()+".provider";
Uri contentUri = FileProvider.getUriForFile(mContext, authority,file);
openCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);
} else {
openCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, tempUri);
}
startActivityForResult(openCameraIntent, TAKE_PICTURE);
}
打开相册 以下两种方法即可
/**
* 选择相册
*/
protected void selectPic() {
Intent intentFromGallery;
// 当sdk版本低于19时使用此方法
if (Build.VERSION.SDK_INT < 19) {
intentFromGallery = new Intent(Intent.ACTION_GET_CONTENT);
intentFromGallery.setType("image/*");
} else {
intentFromGallery = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
}
// Intent intentFromGallery = new Intent(Intent.ACTION_PICK);
// intentFromGallery.setType("image/*");//相片类型
startActivityForResult(intentFromGallery, CHOOSE_PICTURE);
}
然后 onActivityResult
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (RESULT_OK == resultCode) {
switch (requestCode) {
case TAKE_PICTURE://相机
File file = new File(FileConstanse.getCacheImagePath(), FileConstanse.IMAGE_CACHE_NEW);
if (rotaImg(tempUri.getPath(),file)){
tempUri = Uri.fromFile(file);
}
crop(102, 37);//进行裁剪
break;
case CHOOSE_PICTURE://相册
File filePic = new File(FileConstanse.getCacheImagePath(), FileConstanse.IMAGE_CACHE_NEW);
tempUri = data.getData();
String path = ImageUtils.getRealPathFromUri(mContext, tempUri);
if (rotaImg(path,filePic)){
tempUri = Uri.fromFile(filePic);
}
crop(102, 37);
break;
case Crop.REQUEST_CROP://裁剪
ImageLoadConfig.loadNomalPicWithoutChache(mContext, outPutUri, ivPic);
break;
}
}
}
如愿一切如愿的话,就不会有这篇文章了,奇葩的小米手机出现了图片横竖不分,如果是拍照或者从相册拿出来以前拍照的图片,竖着拍照的图片是横向的。这个想到的方法是将图片按照之前的角度给他再旋转回去。
/**
* 获取图片的旋转角度
* @param imgPath 图片路径
* @return 返回旋转角度
*/
public static int getBitmapRotateAngle(String imgPath) {
// 判断图片方向
int digree = 0;
ExifInterface exif = null;
try {
exif = new ExifInterface(imgPath);
} catch (IOException e) {
e.printStackTrace();
exif = null;
}
if (exif != null) {
int ori = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED);
switch (ori) {
case ExifInterface.ORIENTATION_ROTATE_90:
digree = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
digree = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
digree = 270;
break;
default:
digree = 0;
break;
}
}
return digree;
}
/**
*
* @param path 图片路径
* @param digree 旋转角度
* @return
*/
public static Bitmap creatBitmap(String path,int digree){
Bitmap bitmap = BitmapFactory.decodeFile(path);
Bitmap bitmapRe;
// 旋转图片
Matrix m = new Matrix();
m.postRotate(digree);
bitmapRe = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), m, true);
if (bitmap!=bitmapRe){
bitmap.recycle();
}
return bitmapRe;
}
/**
* 将bitmap作为一张图片存入到指定路径
*
* @param bitmap
* @param file
*/
public static void storeImage(Bitmap bitmap, File file) {
FileOutputStream os;
try {
os = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
os.flush();
os.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
相册拿到的uri要转换成path,才能得到图片的旋转角度
public static String getRealPathFromUri(Context context, Uri contentUri) {
Cursor cursor = null;
try {
String[] proj = { MediaStore.Images.Media.DATA };
cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
} finally {
if (cursor != null) {
cursor.close();
}
}
}
至此完成。