Android调用系统相机拍照

拍照功能在应用开发中几乎已成为标配,例如用户通过拍照上传头像。实现拍照功能的方式有两种。第一种是使用相机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

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值