本篇Blog记录从相册选择照片或拍照实现更换头像及上传功能的实现
功能实现分为上下两篇。上篇记录照片的选择及拍照,下篇记录上传功能的实现
先上效果图
下面就来说一下相册选择图片和相机拍照的实现
相册选择图片
相册选择图片很简单,只需要通过Intent设置拉起就可以了
- Intent拉起相册
/**
* 打开相册
*
* @param type 打开类型区分码(type是我用来区分回调的)
*/
private void openGallery(int type) {
Intent gallery = new Intent(Intent.ACTION_PICK);
gallery.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
startActivityForResult(gallery, type);
}
- onActivityResult回调处理
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// 这里没有判断是否匹配,data为空
Glide.with(this).load(data.getData()).skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE).into(helpBinding.ivHelpImageFirst);
}
就这几行代码,就可以实现拉起相册选择图片,下面实现拍照
相机拍照图片
准备工作
因为我们要读取存储给拍照图片一个存储位置,所以我们需要先创建FileProvider,为什么要用FileProvider而不直接用File是因为,从Android N 7.0之后,为了保证App间传输文件的安全性,不在允许直接用file://传递,会Crash并抛出FileUriExposedException,所以要临时授予权限通过URI访问。(Ps:可能理解不到位,深入了解可自行查询,这里简单说明下)
所以,在正式写相机拍照之前,我们先搞一下FileProvider。
FileProvider
FileProvider的使用也比较简单。分为三步。
- AndroidManifest.xml中定义FileProvider
- 创建XML文件说明临时授予权限的路径
- 使用FileProvider
下面作简单说明
第一步:
<!-- 应用共享Provider -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="你的包名.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
分别说明下含义
name:FileProvider继承自ContentProvider,原来是v4下的包,现在都在androidx下了。
authorities:作用是用来标识,命名方式是APP包名+provider名的形式
exported:是否公开
grantUriPermissions:是否授予临时权限
然后是meta-data,由于我们不能直接使用File,而要使用URI,那么就需要配置文件对真实存储位置做一个映射。这个resource就是我们的映射配置文件,也就是哪些路径要授权写在这文件中。
第二步:
在res目录下创建xml文件夹再创建file_paths.xml文件。位置:res/xml/file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_path_root" path="."/>
</paths>
因为我比较懒,就直接从根目录授权,用 . 表示。
第三步:
最后就在代码中使用了
// 直接通过该方法就可以得到URI
Uri uri = FileProvider.getUriForFile(this, "在AndroidManifest.xml中声明的标识", file));
OK,简单了解FileProvider后,继续正题。
相机正文
- 创建拍照存储路径
- 拉起相机拍照
- onActivityResult回调处理
第一步:
我们要给拍出的照片一个存储路径才能存储
// 创建照片存储目录 ScreenUtils.getFilePath方法是一个工具类,下面有具体代码
File imgDir = new File(ScreenUtils.getFilePath(this, null));
// 创建照片
String photoName = System.currentTimeMillis() + ".png";
File picture = new File(imgDir, photoName);
if (!picture.exists()) {
try {
picture.createNewFile();
} catch (IOException e) {
Log.e(TAG, "choosePictureTypeDialog: 创建图片失败", e);
}
}
// 该路径在回调时获取图片用到
imgPath = picture.getAbsolutePath();
第二步:
创建Intent拉起相机
// 调用相机拍照
Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
camera.putExtra(MediaStore.EXTRA_OUTPUT, FileProvider.getUriForFile(this, "AndroidManifest中声明的fileprovider标识", picture));
startActivityForResult(camera, type);
第三步:
回调逻辑处理
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// 拉起相机回调data为null,打开相册回调不为null,这里没有判空
Glide.with(this).load(imgPath).skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE).into(imageView);
}
到此,从相册选择图片和从相机拍照都已经完成了。
下篇Blog实现上传功能。