赞
踩
拍照功能在应用开发中几乎已成为标配,例如用户通过拍照上传头像。实现拍照功能的方式有两种。第一种是使用相机API(即Camera类)来自定义拍照,第二种是使用Intent调用系统相机来拍照。其中最常见的方式是直接调用系统相机拍照来获取照片。
调用系统相机获取照片的流程如下,这里省去了声明权限和动态权限申请:
private String mFilePath;// 需要初始化,路径自定义
private static final int REQUEST_CODE_CAMERA = 1;
// 启动系统相机
private void startCamareActivity() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.parse("file://" + mFilePath));
startActivityForResult(intent, REQUEST_CODE_CAMERA);
}
// 拿到照片
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_CAMERA && resultCode == RESULT_OK) {
// mFilePath即是拍照完成后的图片
// 这里可以进入裁剪页面了
}
}
通过Action为MediaStore.ACTION_IMAGE_CAPTURE的隐式Intent启动拍照,使用MediaStore.EXTRA_OUTPUT指定照片路径,成功返回后即可获取到照片的完整路径。
下面进入填坑阶段。
一.拍摄的照片被旋转了
明明在拍摄时照片是正的,进入裁剪页面发现照片竟然是被旋转的。这个现象在不同的设备上,表现会不一样,可能正常也可能被旋转,而且旋转的角度也不同。要解决这个问题,需要首选获取照片的旋转角度,再反转回去就可以了。
ExifInterface接口提供了多媒体文件比如JPG格式图片的一些附加信息,比如文件的旋转,gps,拍摄时间等。如下代码展示了使用ExifInterface获取图片的旋转角度。
/**
* 获取图片的旋转角度
* @param path 图片的绝对路径
*/
private int getBitmapDegree(String imagePath) {
int degree = 0;
try {
// 从指定路径下读取图片,并获取其EXIF信息
ExifInterface exifInterface = new ExifInterface(imagePath);
// 获取图片的旋转信息
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;
}
进行图形变换如旋转、缩放、移动的操作,可以使用Matrix类来完成。如下代码展示了使用Matrix对图片旋转,生成新的Bitmap。
/**
* 将图片按照某个角度进行旋转
* @param bitmap 需要旋转的图片
* @param degree 旋转角度
*/
public static Bitmap rotateBitmapByDegree(Bitmap bitmap, int degree) {
Bitmap result = null;
// 根据旋转角度,生成旋转矩阵
Matrix matrix = new Matrix();
matrix.postRotate(degree);
try {
// 将原始图片按照旋转矩阵进行旋转,并得到新的图片
result = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
} catch (Exception e) {
}
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.recycle();
bitmap = null;
}
return result;
}
二.拍照完成后应用闪退
这个现象相对少见,目前在廉价的低端手机上出现过。启动拍照时正常,当在拍照界面点击确认按钮,拍照界面消失返回我们的应用时,直接闪退。更让人崩溃的是,Logcat里面没有相应的日志信息。无奈只能借助搜索,发现原来是手机厂商对系统做了修改(为了在低端硬件上能够运行Android系统...),当我们的应用程序的Activity启动拍照,进入系统相机时,我们的Activity被销毁了。这个情况在测试时也不是必现。测试机在使用一段时间后很容易出现,但如果将设备重启后开启我们的应用来拍照又没有问题(这是我们遇到的情况,可能不是必现规则)。
Activity被回收时保存数据,可以在onSaveInstanceState()生命周期方法中处理,将图片路径保存到Bundle中。
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putString("file_path", mFilePath);
super.onSaveInstanceState(outState);
}
然后在onCreate()方法里,判断savedInstanceState不为空时,取出图片路径的值。
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
if (savedInstanceState != null) {
mFilePath = savedInstanceState.getString("file_path");
// your code here
}
}
网上看到另外一种恢复的方法。Activity没有重新创建,而是成员变量被回收了,当拍照返回时,在onActivityResult()方法中mFilePath为空。解决方法是从onRestoreInstanceState()方法恢复数据。这种情况暂时没遇到,做个记录。
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
if (TextUtils.isEmpty(mFilePath)) {
mFilePath = savedInstanceState.getString("file_path");
}
super.onRestoreInstanceState(savedInstanceState);
}
————————————————
版权声明:本文为CSDN博主「ruancoder」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ruancoder/article/details/54344171
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。