Android相机使用心得
最近在开发的项目中使用到了相机拍照和裁剪上传头像,由于手机的兼容性和网上一些博客的代码很不完整,发现总是出现一些问题,所以乘着最近有时间就把这些知识整理一下,欢迎提意见。
因为相机在Android6.0以后需要添加动态权限,在这里先给大家介绍一下一个好用的动态权限库
https://github.com/hotchemi/PermissionsDispatcher
在这里我先贴出调用相机的代码:
//注解请求打开相机的动态权限
@NeedsPermission(Manifest.permission.CAMERA)
public void takePhoto(Activity activity, int takePhotoCode) {
//由于在某些手机上,onActivityResult中的data是null,根本拿不到拍完照的图片路径,所以在这里我们为了解决这个问题会从新创建一个新的路径来存放拍下来的图片。
mPath = getSDPath() + "/" + "tempPath";
File tempFile = new File(mPath);
if (!tempFile.exists()) {
try {
tempFile.createNewFile();//创建新文件
} catch (IOException e) {
e.printStackTrace();
}
}
//开启相机
Intent getImageByCamera= new Intent("android.media.action.IMAGE_CAPTURE");
getImageByCamera.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));
activity.startActivityForResult(getImageByCamera, takePhotoCode);
}
//获取路径
public static String getSDPath() {
File sdDir = null;
boolean sdCardExist = Environment.getExternalStorageState().equals(android.os.En vironment.MEDIA_MOUNTED);
//判断sd卡是否存在
if (sdCardExist) {
//获取跟目录,这个是外部存储的根目录,当程序卸载的时候,对应的数据不会消失,如果想让其消失可以使用getExternalCacheDir()和 getExternalFilesDir()这两个方法,具体看你的需求。
sdDir = Environment.getExternalStorageDirectory();
}else{
//有人多在这里有很多不明白的,感觉为什么网上调用相机的很多资料为什么在这里不写清楚,在获取不到sdCard挂载的时候,应该把图片路径改掉,在这里我介绍一下,在Android4.1以上的手机都会发现手机的sdCard是挂载的(无论你手机有没有安装sdCard),所以很多网上基本上没有处理不挂载的情况。如果你想尝试你可以使用低版本手机尝试。
}
return sdDir.toString();
}
在这里我先贴出调用相册的代码
public static boolean pickPhoto() {
Intent getImage = new Intent(Intent.ACTION_GET_CONTENT);
getImage.addCategory(Intent.CATEGORY_OPENABLE);
getImage.setType("image/*");
activity.startActivityForResult(getImage, imageCode);
return true;
}
在这里我再贴出动态权限的请求
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
//只需要调用这个放就行了
MainActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
}
拍完照片后处理返回结果
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQ_TAKE_CODE:// 拍照完成之后会来到这个地方
if (resultCode == RESULT_OK){
//为了适配更多手机我们需要获取图片角度,例如三星手机拍照的图片就是横着的
int degree = getBitmapDegree(mTempPath);
Bitmap bitmap = BitmapFactory.decodeFile(mPath,null);
if (bitmap != null){
if(degree != 0){
//不是0度,将图片旋转到0度
bitmap = rotateBitmap(mBitmap, degree );
}
PhotoUtilChange.cutPicture(this, REQ_ZOOM_CODE,bitmap, mPath);
}
}
break;
case REQ_PICK_CODE:// 从相册选择好之后的结果
Log.d("BBBBB","从相册选好了回来,拍照后回来");
if (resultCode == RESULT_OK){
PhotoUtilChange.onPhotoFromPick(this, REQ_ZOOM_CODE, mTempPath, data, 1, 1);
}
break;
case REQ_ZOOM_CODE:// 缩放完成之后会来到这个地方
Log.d("BBBBB","裁剪后回来");
if (resultCode == RESULT_OK){
//mPath是从相册中选择照片的临时路径,mTempPath是刚才调用相机我们拍照的图片路径
Bitmap zoomBitMap = BitmapFactory.decodeFile(mPath);
/*Bitmap zoomBitMap = BitmapFactory.decodeFile(mTempPath);*/
mCiv.setImageBitmap(zoomBitMap);
}
//Bitmap bitmap = BitmapFactory.decodeFile(mTempPath);
/*Bundle bundle = data.getExtras();
Log.d("BBBBB",bundle.toString());*/
/*Bitmap bitmap = BitmapFactory.decodeFile(mPath,null);
if (bitmap != null){
mImageView.setImageBitmap(bitmap);
mCiv.setImageBitmap(bitmap);
}*/
//Bitmap zoomBitMap = PhotoUtilChange.getZoomBitMap(data, this);
//每次结束删掉路径
/*
if (mPhotoFileUri != null) {
File file = new File(mPhotoFileUri.getPath());
if (file != null && file.exists()) {
file.delete();
}
}
mPhotoFileUri = null;*/
break;
default:
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
####
public static void cutPicture(final Activity context,final int zoomCode, Bitmap bitmap,final String temppath){
try {
compressImage(bitmap, new File(temppath + "temp.jpg"), 30);
startPhotoZoom(context, Uri.fromFile(new File(temppath + "temp.jpg")),
Uri.fromFile(new File(temppath)), zoomCode);
} catch (Exception e) {
Toast.makeText(context, "图片加载失败", Toast.LENGTH_SHORT).show();
}
}
####
###
public static void compressImage(Bitmap bm, File f, int compress) {
if (bm == null)
return;
File file = f;
try {
if (file.exists()) {
file.delete();
}
file.createNewFile();
OutputStream outStream = new FileOutputStream(file);
bm.compress(android.graphics.Bitmap.CompressFormat.JPEG, compress, outStream);
outStream.flush();
outStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
###
###
private static void startPhotoZoom(Activity activity, Uri uri, Uri outUri, int photoResoultCode) {
Intent intent= new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri,"image/*");
//下面这个crop=true是设置在开启的Intent中设置显示的view可裁剪
intent.putExtra("crop","true");
// aspectX aspectY 是宽高的比例
intent.putExtra("aspectX",1);
intent.putExtra("aspectY",1);
// outputX outputY 是裁剪图片宽高
intent.putExtra("outputX", 800);
intent.putExtra("outputY", 800);
//是否将数据保留在Bitmap中返回
intent.putExtra("return-data", false);
// 当图片的宽高不足时,会出现黑边,去除黑边
intent.putExtra("scale", true);
intent.putExtra("scaleUpIfNeeded", true);
intent.putExtra(MediaStore.EXTRA_OUTPUT,outUri);
intent.putExtra("outputFormat", "JPEG");// 返回格式
activity.startActivityForResult(intent,photoResoultCode);
}
###
###
public static int getBitmapDegree(String path) {
int degree = 0;
try {
// 从指定路径下读取图片,并获取其EXIF信息
ExifInterface exifInterface = new ExifInterface(path);
if (exifInterface == null) return 0;
// 获取图片的旋转信息
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) {
}
return degree;
}
###
###
public static Bitmap rotateBitmap(Bitmap bmp, float degree) {
Matrix matrix = new Matrix();
matrix.postRotate(degree);
return Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
}
###