Seize the day

POST : Android Dev Study

ScopedStorage 모드 테스트

ScopedStoage 모드에서 아무런 권한이 없어도 MediaStore api를 사용하지 않고도, Pictures 폴더에 이미지 저장이 가능한가? 

App Target sdk 31
Android 11 에서 테스트
AndroidManifest에 어떤한 권한이나, element 수정이 없이 기본 값으로 테스트

@RequiresApi(Build.VERSION_CODES.Q)
private fun onClickButton1(v: View) {
    val dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
    val filename = System.currentTimeMillis().toString() + ".jpg"
    val file = File(dir, filename)
    val bitmap = viewToBitmap(binding.text1)
    saveBitmap(bitmap, file)
    scanMediaFile(file)
    Toast.makeText(requireContext(), "isScopedStorage=${!Environment.isExternalStorageLegacy()}", Toast.LENGTH_SHORT).show()
}

private fun viewToBitmap(view: View): Bitmap {
    val bitmap = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)
    val canvas = Canvas(bitmap)
    view.layout(view.left, view.top, view.right, view.bottom)
    view.draw(canvas)
    return bitmap
}

private fun saveBitmap(bitmap: Bitmap, file: File) {
    val fos = FileOutputStream(file)
    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos)
    fos.flush();
    fos.close();
}

private fun scanMediaFile(file: File) {
    val mediaScanIntent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)
    val contentUri: Uri = Uri.fromFile(file)
    mediaScanIntent.data = contentUri
    requireContext().sendBroadcast(mediaScanIntent)
}

결과는
isScopedStorage=true, 이미지 저장도 잘 되고, OS 갤러리에 이미지도 잘 표시된다.
관련 기술 문서는 :
Storage updates in Android 11  |  Android Developers

Access files using direct file paths and native libraries

To help your app work more smoothly with third-party media libraries, Android 11 allows you to use APIs other than the MediaStore API to access media files from shared storage using direct file paths. These APIs include the following:
  • The File API.
  • Native libraries, such as fopen().

Access media files from shared storage  |  Android Developers

Direct file paths

To help your app work more smoothly with third-party media libraries, Android 11 (API level 30) and higher allow you to use APIs other than the MediaStore API to access media files from shared storage. You can instead access media files directly using either of the following APIs:
  • The File API.
  • Native libraries, such as fopen().
If you don't have any storage-related permissions, you can access files in your app-specific directory, as well as media files that are attributed to your app, using the File API.
If your app tries to access a file using the File API and it doesn't have the necessary permissions, a FileNotFoundException occurs.
To access other files in shared storage on a device that runs Android 10 (API level 29), it's recommended that you temporarily opt out of scoped storage by setting requestLegacyExternalStorage to true in your app's manifest file. In order to access media files using native files methods on Android 10, you must also request the READ_EXTERNAL_STORAGE permission.



WRITE_EXTERNAL_STORAGE  퍼미션은 어떻게 응답하는가?

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
private val permissions = arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)

private fun onClickFav(v: View) {
    ActivityCompat.requestPermissions(this, permissions, 100)
}

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (requestCode == 100) {
        permissions.forEachIndexed { index, permission ->
            val isGranted = grantResults[index] == PackageManager.PERMISSION_GRANTED
            Log.e("__T", "$permission -> isGranted = $isGranted")
        }
    }
}

결과는 두 개다 isGranted = true, 그렇다고 sd카드 root에 폴더를 만들수 있는 것은 아니다. 그럴려면 MANAGE_EXTERNAL_STORAGE  권한이 필요. 어쨌든 WRITE_EXTERNAL_STORAGE 퍼미션에 android:maxSdkVersion=" "을  추가해 놓은 예제를 봐서.. maxSdk SDK_INT에 따라서 WRITE_EXTERNAL_STORAGE를 제외하지 않아도 될 것 같다. 
관련 기술 문서는: 
Storage updates in Android 11  |  Android Developers

Target any version

The following changes take effect in Android 11, regardless of your app's target SDK version:
  • The Storage runtime permission is renamed to Files & Media.
  • If your app hasn't opted out of scoped storage and requests the READ_EXTERNAL_STORAGE permission, users see a different dialog compared to Android 10. The dialog indicates that your app is requesting access to photos and media, as shown in Figure 1.
    Users can see which apps have the READ_EXTERNAL_STORAGE permission in system settings. On the Settings > Privacy > Permission manager > Files and media page, each app that has the permission is listed under Allowed for all files. If your app targets Android 11, keep in mind that this access to "all files" is read-only. To read and write to all files in shared storage using this app, you need to have the all files access permission.

Target Android 11

If your app targets Android 11, both the WRITE_EXTERNAL_STORAGE permission and the WRITE_MEDIA_STORAGE privileged permission no longer provide any additional access.
Keep in mind that, on devices that run Android 10 (API level 29) or higher, your app can contribute to well-defined media collections such as MediaStore.Downloads without requesting any storage-related permissions. Learn more about how to request only the necessary permissions when working with media files in your app.
top

posted at

2022. 2. 5. 21:28


CONTENTS

Seize the day
BLOG main image
김대정의 앱 개발 노트와 사는 이야기
RSS 2.0Tattertools
공지
아카이브
최근 글 최근 댓글
카테고리 태그 구름사이트 링크