今天写的博客是关于Android调用手机相机拍照并显示图片。这是一个很经常使用的功能,而且这个功能在Android6.0、7.0、10.0等版本上实现都有所不一样,须要对Android各个版本进行兼容适配,目前最新的Android版本是Android 10,因此这篇博客适配到Android 10。我本身也写了个demo,方便之后要使用的时候直接拿来。php
调用相机,首先须要申请相机权限。android
<uses-permission android:name="android.permission.CAMERA" />
复制代码
android 6.0之后,相机权限须要动态申请。git
// 申请相机权限的requestCode
private static final int PERMISSION_CAMERA_REQUEST_CODE = 0x00000012;
/**
* 检查权限并拍照。
* 调用相机前先检查权限。
*/
private void checkPermissionAndCamera() {
int hasCameraPermission = ContextCompat.checkSelfPermission(getApplication(),
Manifest.permission.CAMERA);
if (hasCameraPermission == PackageManager.PERMISSION_GRANTED) {
//有调起相机拍照。
openCamera();
} else {
//没有权限,申请权限。
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CAMERA},
PERMISSION_CAMERA_REQUEST_CODE);
}
}
/**
* 处理权限申请的回调。
*/
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == PERMISSION_CAMERA_REQUEST_CODE) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//容许权限,有调起相机拍照。
openCamera();
} else {
//拒绝权限,弹出提示框。
Toast.makeText(this,"拍照权限被拒绝",Toast.LENGTH_LONG).show();
}
}
}
复制代码
申请权限后,就能够调起相机拍照了。调用相机只须要调用startActivityForResult传一个Intent就能够了,可是这个Intent须要传递一个uri,用于保存拍出来的图片,建立这个uri时,各个Android版本有所不一样,须要进行版本兼容。github
//用于保存拍照图片的uri
private Uri mCameraUri;
// 用于保存图片的文件路径,Android 10如下使用图片路径访问图片
private String mCameraImagePath;
// 是不是Android 10以上手机
private boolean isAndroidQ = Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q;
/**
* 调起相机拍照
*/
private void openCamera() {
Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// 判断是否有相机
if (captureIntent.resolveActivity(getPackageManager()) != null) {
File photoFile = null;
Uri photoUri = null;
if (isAndroidQ) {
// 适配android 10
photoUri = createImageUri();
} else {
try {
photoFile = createImageFile();
} catch (IOException e) {
e.printStackTrace();
}
if (photoFile != null) {
mCameraImagePath = photoFile.getAbsolutePath();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//适配Android 7.0文件权限,经过FileProvider建立一个content类型的Uri
photoUri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", photoFile);
} else {
photoUri = Uri.fromFile(photoFile);
}
}
}
mCameraUri = photoUri;
if (photoUri != null) {
captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
captureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
startActivityForResult(captureIntent, CAMERA_REQUEST_CODE);
}
}
}
/**
* 建立图片地址uri,用于保存拍照后的照片 Android 10之后使用这种方法
*/
private Uri createImageUri() {
String status = Environment.getExternalStorageState();
// 判断是否有SD卡,优先使用SD卡存储,当没有SD卡时使用手机存储
if (status.equals(Environment.MEDIA_MOUNTED)) {
return getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new ContentValues());
} else {
return getContentResolver().insert(MediaStore.Images.Media.INTERNAL_CONTENT_URI, new ContentValues());
}
}
/**
* 建立保存图片的文件
*/
private File createImageFile() throws IOException {
String imageName = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
if (!storageDir.exists()) {
storageDir.mkdir();
}
File tempFile = new File(storageDir, imageName);
if (!Environment.MEDIA_MOUNTED.equals(EnvironmentCompat.getStorageState(tempFile))) {
return null;
}
return tempFile;
}
复制代码
接收拍照结果和显示图片bash
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
if (isAndroidQ) {
// Android 10 使用图片uri加载
ivPhoto.setImageURI(mCameraUri);
} else {
// 使用图片路径加载
ivPhoto.setImageBitmap(BitmapFactory.decodeFile(mCameraImagePath));
}
} else {
Toast.makeText(this,"取消",Toast.LENGTH_LONG).show();
}
}
}
复制代码
这两须要说明一下,Android 10因为文件权限的关系,显示手机储存卡里的图片不能直接使用图片路径,须要使用图片uri加载。关于在Android 10显示手机图片的适配能够看个人另一篇博客:Android 10加载手机本地图片app
另外虽然我在这篇博客里对Android 10和10如下的手机使用了不一样的方式建立uri 和加载图片,但其实Android 10建立uri的方式和使用uri加载图片的方式在10如下的手机是一样适用的。ide
android 7.0须要配置文件共享。post
<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" />
</provider>
复制代码
在res目录下建立文件夹xml ,放置一个文件file_paths.xml(文件名能够随便取),配置须要共享的文件目录,也就是拍照图片保存的目录。ui
<?xml version="1.0" encoding="utf-8"?>
<resources>
<paths>
<!-- 这个是保存拍照图片的路径,必须配置。 -->
<external-files-path name="images" path="Pictures" />
</paths>
</resources>
复制代码
若是想把图片放在手机的共享储存区,好比Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)文件夹下,还须要申请文件读写权限。this
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
复制代码
文件读写权限一样须要动态申请,申请权限的方式跟上面申请相机权限同样,这里就再也不重复了。
完整的demo请看个人Github。