都把权限写完了,该来做个小整理,这次我们整合Android 6
到Android 11
,没有Android 5
是因为太老旧,是该淘汰,没有Android 12
则是我没有实机可以测试。
版本名称 | 版号 | 上版日期 | SDK版本 | 官方支援 |
---|---|---|---|---|
Lollipop | 5.0 – 5.1.1 | 2014年11月12日 | 21 - 22 | 不支援 |
Marshmallow | 6.0 – 6.0.1 | 2015年10月05日 | 23 | 不支援 |
Nougat | 7.0 – 7.1.2 | 2016年08月22日 | 24 - 25 | 不支援 |
Oreo | 8.0 – 8.1 | 2017年08月21日 | 26 - 27 | 支援 |
Pie | 9 | 2018年08月06日 | 28 | 支援 |
Q | 10 | 2019年09月03日 | 29 | 支援 |
R | 11 | 2020年09月08日 | 30 | 支援 |
S | 12 | 2021年??月??日 | 31 | 支援 |
AndroidManifest.xml
要记得新增权限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
因为会重复呼叫,所以把拍照改成函式,主要是以Android 9
为分水岭,Android 9
以下才需要权限,Android 10
以上就使用MediaStore
,所以不用权限;符合官方规范所说,不要随便跟使用者要求权限
private fun startTakePicture() {
var uri: Uri? = null
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
val permissionList = arrayOf(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE
)
if (!EasyPermissions.hasPermissions(this, *permissionList)) {
EasyPermissions.requestPermissions(
this,
"请提供读写档案权限",
BaseConstants.READ_WRITE_PERMISSIONS,
*permissionList
)
return
}
if (!isCreateFolder(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES))) {
Log.d("maho", "资料夹建立失败")
return
}
val phoneFile = File(
Environment.getExternalStoragePublicDirectory("${Environment.DIRECTORY_PICTURES}/AndroidSystem"),
"004.jpg"
)
uri = getPictureUri(phoneFile)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val contentValue = ContentValues().apply {
this.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, "004.jpg")
this.put(MediaStore.Images.ImageColumns.MIME_TYPE, "image/jpeg")
this.put(
MediaStore.Images.ImageColumns.RELATIVE_PATH,
"${Environment.DIRECTORY_PICTURES}/AndroidSystem"
)
)
}
uri = contentResolver.insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
contentValue
)
}
createVersionCheckResultLauncher.launch(uri)
}
是点击的部份
aclMbCreateVersionCheckPicture.setOnClickListener {
startTakePicture()
}
使用者同意权限的部份
override fun onPermissionsGranted(requestCode: Int, perms: MutableList<String>) {
if (BaseConstants.READ_WRITE_PERMISSIONS == requestCode) {
startTakePicture()
}
}
启动器的部份
private val createVersionCheckResultLauncher =
registerForActivityResult(ActivityResultContracts.TakePicture()) { isTakePicture ->
if (!isTakePicture) {
Log.d("maho", "拍照建立档案失败")
return@registerForActivityResult
}
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
val phoneFile = File( Environment.getExternalStoragePublicDirectory("${Environment.DIRECTORY_PICTURES}/AndroidSystem"),
"004.jpg"
)
MediaScannerConnection.scanFile(this, arrayOf(phoneFile.toString()), null) { _, _ ->
}
aclIvVersionCheckPicture.setImageURI(getPictureUri(phoneFile))
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val selection = "${MediaStore.Images.ImageColumns.DISPLAY_NAME} = '004.jpg'"
val orderBy = "${MediaStore.Images.ImageColumns.DATE_ADDED} DESC"
val uriQuery = contentResolver.query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
null,
selection,
null,
orderBy
) ?: return@registerForActivityResult
uriQuery.moveToFirst()
val pictureId =
uriQuery.getLong(uriQuery.getColumnIndex(MediaStore.Images.ImageColumns._ID))
val uri = ContentUris.withAppendedId(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
pictureId
)
MediaScannerConnection.scanFile(this, arrayOf(uri.toString()), null) { _, _ ->
}
aclIvVersionCheckPicture.setImageURI(uri)
}
}
这样的话,就能顺利的在Andoird 6
到Android 11
执行,拍照後会在Pictures/应用程序名称资料夹
中建立档案,虽然应用程序移除後照片还是会留在手机中,但也符合官方建议。
>>: Re: 新手让网页 act 起来: Day16 - 探索 useState (2)
一日客语:中文:蛋 客语:唇 ES6语法 是constructor function 一种语法糖 函...
本篇搭配 LeetCode 1.Two Sum 题目: Given an array of inte...
惯例在最後一天做个总结啦,不过回头看第一天条列的内容清单,发现还漏掉一个建构周期任务的介绍没写到,没...
GKE 应用 经过昨天说的建立GKE想必应该已经有了自己的丛集了,那如何在GCP上去使用GKE呢?可...
昨天我们已经将制作好的版型,套用到 Angular 的根元件 AppComponent,今天,我们就...