Mise à jour vers la nouvelle version de l'API Android conformément aux instructions de Google

Android 12 arrive bientôt, mais en août, à partir de la version 11, les développeurs devront utiliser de nouvelles normes pour accéder aux applications aux fichiers externes. Si auparavant vous pouviez simplement mettre un indicateur indiquant que votre application ne prend pas en charge les innovations, elles deviendront bientôt obligatoires pour tout le monde. L’objectif principal est d’améliorer la sécurité.





API — , . . 





, — .





Android Internal Storage (IS) External Storage (ES). SD-, ES , . — IS, ES , , . ES , , , .





IS, . . ES , , (, ).





. IS, ES — , .





Android 10- , 11- .





Google Scoped Storage (SS) ES. , — . IS 10- .





Android 11 Google SS — - SDK 30- API, SS, , . Android , . , 11, , , . , Android 11, . 





SS ( 10- ), . Media Content, Storage Access Framework , 11- Android, Datasets . , . , . — . , , . , , .





Media Content, SAF Datasets Shared Storage (ShS). . , .





SS — FileProvider . , .





— , . best practice ( , ), - , . , . 





. , , , , .





— , , . — , .





.





iFunny . , .





, API. 





interface FilesManipulator {
    fun createVideoFile(fileName: String, copy: Copier): Uri
    fun createImageFile(fileName: String, copy: Copier): Uri
    fun createFile(fileName: String, copy: Copier): Uri
    fun getPath(uri: Uri): String
    fun deleteFile(uri: Uri)
}
      
      



FilesManipulator , , API . Copier — , , . , , , . 10- Android FilesManipulator File API, 10- ( ) — MediaStore API.





.





fun getContentValuesForImageCreating(fileName: String): ContentValues {
    return ContentValues().apply {
        put(MediaStore.Images.Media.DISPLAY_NAME, fileName)
        put(MediaStore.Images.Media.IS_PENDING, FILE_WRITING_IN_PENDING)
        put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + File.separator + appFolderName)
    }
}

fun createImageFile(fileName: String, copy: Copier): Uri {
    val contentUri = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
    val contentValues = getContentValuesForImageCreating(fileName)
    val uri = contentResolver.insert(contentUri, contentValues)
              ?: throw IllegalStateException("New image file insert error")
    downloadContent(uri, copy)
    return uri

}

fun downloadContent(uri: Uri, copy: Copier) {
    try {
        contentResolver.openFileDescriptor(uri, FILE_WRITE_MODE)
                .use { pfd ->
                    if (pfd == null) {
                        throw IllegalStateException("Got nullable file descriptor")
                    }
                    copy.copyTo(FileOutputStream(pfd.fileDescriptor))
                }
        contentResolver.update(uri, getWriteDoneContentValues(), null, null)
    } catch (e: Throwable) {
        deleteFile(uri)
        throw e
    }
}

fun getWriteDoneContentValues(): ContentValues {
    return ContentValues().apply {
        put(MediaStore.Images.Media.IS_PENDING, FILE_WRITING_DONE)
    }
}
      
      



, MediaStore.Images.Media.IS_PENDING



, 0 , . 





, . URI . SDK, File API . External Storage FileProvider API.





, 30- API, . iFunny , . , query, , SDK.





, , . , .





<manifest … >
<queries>
<intent>
    <action android:name="android.intent.action.SENDTO" />
    <data android:scheme="smsto, mailto" />
</intent>
    <package android:name="com.twitter.android" />
    <package android:name="com.snapchat.android" />
    <package android:name="com.whatsapp" />
    <package android:name="com.facebook.katana" />
    <package android:name="com.instagram.android" />
    <package android:name="com.facebook.orca" />
    <package android:name="com.discord" />
    <package android:name="com.linkedin.android" />
</queries>
</manifest>
      
      



UI- API 29-30 , .





LogCat , Orchestrator java.lang.RuntimeException: Cannot connect to androidx.test.orchestrator.OrchestratorService.







, <package android:name="androidx.test.orchestrator" />



.





, — Allure , .





- Scoped Storage , , . , , , .





, . ShellCommandExecutor, adb shell appops set --uid PACKAGE_NAME MANAGE_EXTERNAL_STORAGE allow



.





Android 11 . 





10- Android , Allure . issue Allure, , , 11- . adb shell appops set --uid PACKAGE_NAME LEGACY_STORAGE allow



. , . 





— . , WRITE_EXTERNAL_STORAGE



28 API, . (, debug) Allure . 





debug-.





<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="29"
    tools:node="replace" />
      
      



, targetSdkVersion 30, Google Play , .








All Articles