今天在写一个Demo的时候,需要调用系统相机和相册,虽然之前写过类似的代码,但是还是无从下手,所以准备用这篇博客记录一下如何调用,以后再遇到这个功能的实现,就直接过来调用就行
这里的代码基本时模板代码,直接使用就行,细节地方根据自己的需求改动一下
一、系统相机:
1. 声明权限:
<!--相机权限-->
<uses-permission android:name="android.permission.CAMERA" />
2. 检查权限:如果没有权限,则去申请权限,若有权限就直接打开系统相机
/**
* 检查权限并拍照。
* 调用相机前先检查权限。
*/
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);
}
}
3. 调用系统相机:
/**
* 调起相机拍照
*/
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);
}
}
}
4. 创建保存文件的图片的路径,这里根据Android不同的版本进行了不同的处理
/**
* 创建图片地址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;
}
5. 调用相机后返回结果,注:如果mCameraImagePath
要用这个变量去保存图片地址时,必须将其设置为static
属性,不然当结果返回时,他为null(因为返回结果时,相当于重新进入了这个Activity)
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Intent intent = new Intent(MainActivity.this,YourActivity.class);
if (requestCode == CAMERA_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
//将拍照后的图片设置给imageview
// if (isAndroidQ) {
// // Android 10 使用图片uri加载
// ivPhoto.setImageURI(mCameraUri);
// } else {
// // 使用图片路径加载
// ivPhoto.setImageBitmap(BitmapFactory.decodeFile(mCameraImagePath));
// }
//将拍照后,文件的路径传给下一个Activity
intent.putExtra("mPicPath",mCameraImagePath);
startActivity(intent);
}
}
}
6. 变量名:
// 申请相机权限的requestCode
private static final int PERMISSION_CAMERA_REQUEST_CODE = 0x00000012;
//用于保存拍照图片的uri
private Uri mCameraUri;
// 用于保存图片的文件路径,Android 10以下使用图片路径访问图片
//如果不加static,当跳转之后再回来,这个变量就为null了,但不是长久之计
private static String mCameraImagePath;
// 是否是Android 10以上手机
private boolean isAndroidQ = Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q;
private static final int CAMERA_REQUEST_CODE = 200;
7. 在Manifest
中,声明provider
<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>
8. 对于provider
中的android:resource="@xml/file_paths"
需要在res
下面创建一个xml
的目录,然后创建一个xml文件file_paths
<?xml version="1.0" encoding="utf-8"?>
<resource xmlns:android="http://schemas.android.com/apk/res/android">
<paths>
<!-- 这个是保存拍照图片的路径,必须配置。 -->
<external-files-path
name="images"
path="Pictures" />
</paths>
</resource>
二、系统相册
1.声明权限:
<!--SD卡权限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
2.打开相册:
//从相册中选择照片
private void openAlbum() {
Intent intent = new Intent("android.intent.action.GET_CONTENT");
intent.setType("image/*");
startActivityForResult(intent,CHOOSE_PHOTO);
}
3. 处理返回的结果,注:这里我对不同的Android版本进行了处理
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Intent intent = new Intent(MainActivity.this,PuzzleMain.class);
if (requestCode == CHOOSE_PHOTO){
if (requestCode != RESULT_OK) {
String path;
//判断手机的版本号
if (Build.VERSION.SDK_INT >= 19) {
//4.4及以上的系统使用的这个方法处理图片
path = handleImageOnKitKat(data);
}else {
//4.4以下的系统使用的图片处理方法
path = handleImageBeforeKitKat(data);
}
intent.putExtra("mPicPath", path);
startActivity(intent);
}
}
}
4. 根据不同的版本对data
进行不同的处理
private String handleImageOnKitKat(Intent data) {
String imagePath = null;
Uri uri = data.getData();
if (DocumentsContract.isDocumentUri(this,uri)) {
//如果document类型的Uri,则通过document id处理
String docId = DocumentsContract.getDocumentId(uri);
if ("com.android.providers.media.documents".equals(uri.getAuthority())) {
String id = docId.split(":")[1];//解析出数字格式的id
String selection = MediaStore.Images.Media._ID+"="+id;
imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,selection);
}else if("com.android.providers.downloads.documents".equals(uri.getAuthority())){
Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://" +
"downloads//public_downloads"),Long.valueOf(docId));
imagePath = getImagePath(contentUri,null);
}
}else if("content".equalsIgnoreCase(uri.getScheme())){
//如果是普通content类型的uri,则使用普通的方法处理
imagePath = getImagePath(uri,null);
}else if("file".equalsIgnoreCase(uri.getScheme())){
//如果使用file类型的uri,直接获取图片的路径即可
imagePath = uri.getPath();
}
return imagePath;
}
private String handleImageBeforeKitKat(Intent data) {
Uri uri = data.getData();
String imagePath = getImagePath(uri,null);
return imagePath;
}
5. 解析Url,得到路径
private String getImagePath(Uri externalContentUri, String selection) {
String path = null;
//通过Uri和selection来获取真实的图片路径
Cursor cursor = getContentResolver().query(externalContentUri,
null,selection,null,null);
if (cursor != null) {
if (cursor.moveToFirst()) {
path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
}
cursor.close();
}
return path;
}
6. 调用相册使用的变量:
//相册
private static final int CHOOSE_PHOTO = 100;
网友评论