相机在当前应用中的地位越来越重要,在开发的时候经常遇到相机相关的问题.
权限
使用相机需要我们给与APP调用权限,一般根据APP的targetApi来区分.
API<=19
直接在清单文件中添加相加权限即可
<uses-permission android:name="android.permission.CAMERA" />
通常情况下我们还需要配合本地存储,保存拍摄的照片等等,因此针对需求添加读写本地存储的权限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
API>19
在Android6.0+的系统上,我们需要动态申请权限,以保证当前APP拥有调用相机的权限,通常情况下我们可以这样写.
if (ContextCompat.checkSelfPermission(context,
Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions((Activity) context,
new String[]{Manifest.permission.CAMERA},
TAKE_PHOTO_REQUEST_CODE);
} else {
//调用相机进行某些操作
}
但是国内厂商定制化系统会对Android系统进行各种各样的魔改,因此有可能你通过上述代码校验的时候返回了true,但是真正使用的使用相机无法正常调用,甚至APP崩溃.
有什么办法能够避免吗?
当然,个人比较推荐严大的AndPermission,很早就开始用了,权限管理比较方便(具体使用我就不多赘述了),对于国产机兼容也比较优秀,但是也会有兼顾不到的地方.
比如在魅族手机上,我们申请了权限,也回调了true,但是真正调用的时候却又显示没有相机权限,或者干脆相机无法打开.
/**
* 判断摄像头是否可用
* 主要针对6.0 之前的版本,现在主要是依靠try...catch... 报错信息,感觉不太好,
* 以后有更好的方法的话可适当替换
*
* @return
*/
public static boolean isCameraCanUse() {
boolean canUse = true;
Camera mCamera = null;
try {
mCamera = Camera.open();
// setParameters 是针对魅族MX5 做的。MX5 通过Camera.open() 拿到的Camera
// 对象不为null
Camera.Parameters mParameters = mCamera.getParameters();
mCamera.setParameters(mParameters);
} catch (Exception e) {
canUse = false;
}
if (mCamera != null) {
mCamera.release();
}
return canUse;
}
魅族手机需要单独判断相机是否可用.
通过上面的操作,基本上相机可以正常调用了.
调用系统相机
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra("android.intent.extras.CAMERA_FACING_FRONT", 1); // 调用前置摄像头
intent.putExtra("autofocus", true); // 自动对焦
intent.putExtra("fullScreen", false); // 全屏
intent.putExtra("showActionIcons", false);
startActivityForResult(intent, REQUESTCODE_照相机);
上面就是调用系统前置摄像头的方法,部分前置摄像头不支持自动对焦,需要去掉自动对焦的代码,相机全屏看个人喜好,当然调用后置的话更改android.intent.extras.CAMERA_FACING_FRONT为0就行了.
如果我们需要获取拍摄的图片路径
/**
* Create a File Uri for saving a photo
*/
private Uri getOutputPhotoFileUri(String suffix) {
//get the mobile Pictures directory
File picDir = new File(DownloadManager.UPLOAD_FLODER);
if (!picDir.exists()) {
picDir.mkdirs();
}
//get the current time
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File photoFile = new File(picDir.getPath() + File.separator + timeStamp + suffix);
currentUri = null;
currentUri = Uri.fromFile(photoFile);
return currentUri;
}
在调用相机的intent中加入
intent.putExtra(MediaStore.EXTRA_OUTPUT, getOutputPhotoFileUri(".jpg"));
然后在onActivityResult
方法中获取当前拍摄的状态
resultCode == Activity.RESULT_OK
Activity.RESULT_OK的值是-1,然而有时候返回的resultCode为0,这个时候可能是当前的缓存路径没有创建成功.
前面我们创建目录的时候使用的是
picDir.mkdirs();
这个方法是创建路径,当多级路径中某些不存在时会自动生成.
picDir.mkdir();
这个方法也是生成路径,但是只能生成单级路径,多级路径会创建失败,因此导致先前返回的resultCode=0.
部分手机默认调用前置无效
相机确实是一个比较麻烦的适配点
魅族相机确实很坑爹