11月份Google發通知上架的應用必須適配到Android30,要不然提交到google play的app不能發布更新,用戶就只能使用舊版本,
CameraX適配Android11的整個流程圖如下:

1.我們來看看Google的通知說明:

自 2021 年 11 月 1 日起,針對 Google Play 上的應用和游戲的更新必須以 Android 11(API 級別 30)或更高版本為目標運行環境,此日期過后,您將無法上傳 targetSdkVersion 低于 30 的新 app bundle 和 APK,
請注意,Wear OS 應用不受關于 API 級別 30 的要求限制,
將您的應用配置為使用新近的 API 級別能使安全性和性能上的顯著改進惠及用戶,同時仍然允許您的應用在較低版本的 Android(低至 minSdkVersion)上運行,
查看遷移指南
2.目標版本:

3.我們把sdk的版本改為30之后出現的錯誤如下:

以上錯誤資訊具體意思就是在Android11及以上的手機讀寫檔案失敗
4.先看沒有適配Android11之前的代碼:

5.適配之后的正確代碼:

6.適配步驟:
6.1 初始化檔案和圖片輸出路徑

6.2.創建一個檔案:

6.3.檔案創建成功后把圖片插入媒體庫:
val metadata = ImageCapture.Metadata().apply {
// Mirror image when using the front camera
isReversedHorizontal = lensFacing == CameraSelector.LENS_FACING_FRONT
}
6.4.構建圖片輸出物件outputOptions:
val outputOptions =
ImageCapture.OutputFileOptions.Builder(photoFile).setMetadata(metadata).build()
6.5.拍照成功后通過MediaScannerConnection.scanFile重繪圖庫照片

7.拍照成功后的日志如下:

拍照成功后的截圖:

8.拍照適配Android11步驟:
8.1 請求檔案讀寫權限,這里在首頁已經請求過了直接上代碼,實際專案根據需要每個界面都要動態請求權限
if (allPermissionsGranted()) {
// ImageCapture
startCamera()
} else {
ActivityCompat.requestPermissions(
this, REQUIRED_PERMISSIONS, Constants.REQUEST_CODE_PERMISSIONS
)
}
private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
ContextCompat.checkSelfPermission(baseContext, it) == PackageManager.PERMISSION_GRANTED
}
override fun onRequestPermissionsResult(
requestCode: Int, permissions: Array<String>, grantResults:
IntArray
) {
if (requestCode == Constants.REQUEST_CODE_PERMISSIONS) {
if (allPermissionsGranted()) {
startCamera()
} else {
ToastUtils.shortToast("請您打開必要權限")
finish()
}
}
}
8.2 調起系統相機拍照
/**
* 調起系統相機拍照
*/
private fun startSystemCamera() {
val takeIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
val values = ContentValues()
//根據uri查詢圖片地址
photoUri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
Log.w("lzq", "photoUri:" + photoUri?.authority + ",photoUri:" + photoUri?.path)
//放入拍照后的地址
takeIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri)
//調起拍照
startActivityForResult(
takeIntent,
REQUEST_CODE_CAMERA
)
}
8.3 拍照和裁剪回呼,由于加了系統裁剪,所以在拍照成功后會呼叫裁剪方法
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_OK) {
if (requestCode == REQUEST_CODE_CAMERA) {//拍斬訓呼
workCropFun(photoUri)
} else if (requestCode == REQUEST_CODE_CROP) {//裁剪回呼
setAvatar()
}
}
}
8.4 圖片裁剪方法,適配Android11
/**
* 系統裁剪方法
*/
private fun workCropFun(imgPathUri: Uri?) {
mUploadImageUri = null
mUploadImageFile = null
if (imgPathUri != null) {
val imageObject: Any = FileUtil.getHeadJpgFile()
if (imageObject is Uri) {
mUploadImageUri = imageObject
}
if (imageObject is File) {
mUploadImageFile = imageObject
}
val intent = Intent("com.android.camera.action.CROP")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
intent.run {
setDataAndType(imgPathUri, "image/*")// 圖片資源
putExtra("crop", "true") // 裁剪
putExtra("aspectX", 1) // 寬度比
putExtra("aspectY", 1) // 高度比
putExtra("outputX", 150) // 裁剪框寬度
putExtra("outputY", 150) // 裁剪框高度
putExtra("scale", true) // 縮放
putExtra("return-data", false) // true-回傳縮略圖-data,false-不回傳-需要通過Uri
putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()) // 保存的圖片格式
putExtra("noFaceDetection", true) // 取消人臉識別
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
putExtra(MediaStore.EXTRA_OUTPUT, mUploadImageUri)
} else {
val imgCropUri = Uri.fromFile(mUploadImageFile)
putExtra(MediaStore.EXTRA_OUTPUT, imgCropUri)
}
}
startActivityForResult(
intent, REQUEST_CODE_CROP
)
}
}

從上圖紅框內容可以看到當系統版本為Android11及以上時裁剪后直接獲取url和檔案路徑的方式會報錯,提示讀寫失敗,解決方法為在Android11及以上的手機上通過MediaStore把uri插入到file中,從而得到檔案路徑.

8.5 裁剪成功后設定用戶頭像,這里需要注意一下裁剪完之后這個路徑在Android11上面是不能直接獲取到的,也是需要MediaStore查詢媒體庫然后轉為file,最后才能把路徑設定為用戶頭像

/**
* 設定用戶頭像
*/
private fun setAvatar() {
val file: File? = if (mUploadImageUri != null) {
FileManager.getMediaUri2File(mUploadImageUri)
} else {
mUploadImageFile
}
Glide.with(this).load(file).into(iv_avatar)
Log.d("filepath", file!!.absolutePath)
}
8.6 列印拍照成功后的圖片路徑為:

總結:
在Google11月份要求必須適配到30后,我們查閱很多資料,第一時間進行了適配,但是一路坎坷,所有檔案權限可以解決檔案讀寫問題,但是這個權限若應用不是殺毒或檔案管理類這個權限是不允許隨便申請的,即使你申請了上架google play的時候審核也會被拒絕,Android11外部檔案不允許隨便讀寫和洗掉,今天只是講解了拍照和錄像時適配內外部存盤權限,還有應用可見性、Toast、后臺運行權限等等一些列的適配,在后面會寫一篇文章全面總結一下最近的Android11適配作業,
最后給出最新的demo地址:感興趣的同學可以看看,如有問題及時提出,一起成長.
CameraXApp: Android CameraX相機Api的使用實體
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/398712.html
標籤:其他
