而适配条件之多,经常让Android程序员
为之头疼。
来看看相机
、相册
相关的适配历程:
-
Android 6 权限适配
-
Android 7 文件适配
-
Android 10/11 存储适配
ok,接下来以一个更换头像
的小例子来讲解一下。
示例
=============================================================
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jUG37fCY-1651629141749)(h 《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》无偿开源 徽信搜索公众号【编程进阶路】 ttps://img-blog.csdnimg.cn/20210128160207111.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3llY2hhb2E=,size_16,color_FFFFFF,t_70#pic_center)]
点击头像,然后弹窗,给出不同的选项,执行不同的操作。
mBinding.llImg.setOnClickListener {
TakeImageDialog {
when (it) {
TakeImageDialog.ALBUM -> {
openAlbum()
}
TakeImageDialog.CAMERA -> {
checkPermission()
}
}
}.show(supportFragmentManager, “TakeImageDialog”)
}
定义后面会用到的一些参数变量
:
//相机拍照保存的位置
private lateinit var photoUri: Uri
companion object {
private const val REQUEST_CODE_PERMISSIONS = 1000 //权限
private const val REQUEST_CODE_ALBUM = 1001 //相册
private const val REQUEST_CODE_CAMERA = 1002 //相机
}
打开相册
===============================================================
选择图片
private fun openAlbum() {
val intent = Intent()
intent.type = “image/*”
intent.action = “android.intent.action.GET_CONTENT”
intent.addCategory(“android.intent.category.OPENABLE”)
startActivityForResult(intent, REQUEST_CODE_ALBUM)
}
固定写法,大差不差。
既然是startActivityForResult
启动方式,来看看onActivityResult
回调
回调
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_OK) {
when (requestCode) {
REQUEST_CODE_ALBUM -> {
doCrop(data?.data!!)
}
…
}
}
}
在requestCode
是REQUEST_CODE_ALBUM
的情况下:
doCrop(data?.data!!)
data?.data!!
即是选择图片返回的Uri
,可以直接使用,这里进行了下一步操作,剪裁
剪裁
private fun doCrop(sourceUri: Uri) {
Intrinsics.checkParameterIsNotNull(sourceUri, “资源为空”)
UCrop.of(sourceUri, getDestinationUri())//当前资源,保存目标位置
.withAspectRatio(1f, 1f)//宽高比
.withMaxResultSize(500, 500)//宽高
.start(this)
}
为了方便,这里使用了一个三方库[UCrop]((),使用简单方便。
getDestinationUri()
是当前资源裁剪后保存的目标位置
private fun getDestinationUri(): Uri {
val fileName = String.format(“fr_crop_%s.jpg”, System.currentTimeMillis())
val cropFile = File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), fileName)
return Uri.fromFile(cropFile)
}
UCrop
的回调同样也在onActivityResult
中
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_OK) {
when (requestCode) {
REQUEST_CODE_ALBUM -> {
doCrop(data?.data!!)
}
UCrop.REQUEST_CROP -> {
val resultUri: Uri = UCrop.getOutput(data!!)!!
val bitmap = BitmapFactory.decodeStream(contentResolver.openInputStream(resultUri))
// todo
}
UCrop.RESULT_ERROR -> {
val error: Throwable = UCrop.getError(data!!)!!
ToastUtil.show(“图片剪裁失败” + error.message)
}
}
}
}
UCrop.getOutput(data!!)!!
,即是返回的Uri,可以直接操作,也可以转成bitmap
。
ok,到这里打开相册就介绍完了。
接下来看重点,打开相机。
打开相机
===============================================================
打开相机的流程就要稍微复杂一点了。
权限
第一步不是打开,而是先检查是否有相机权限
,这个在某些手机上是必须的,比如华为。
- 配置文件添加:
- 代码:
private fun checkPermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
openCamera()
} else {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), REQUEST_CODE_PERMISSIONS)
}
}
- 回调:
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == REQUEST_CODE_PERMISSIONS) {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
openCamera()
} else {
ToastUtil.show(“拒绝会导致无法使用相机”)
}
}
stPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == REQUEST_CODE_PERMISSIONS) {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
openCamera()
} else {
ToastUtil.show(“拒绝会导致无法使用相机”)
}
}