{"id":3803,"date":"2025-11-27T18:25:57","date_gmt":"2025-11-27T10:25:57","guid":{"rendered":"https:\/\/imastudio.com\/?p=3803"},"modified":"2025-11-27T18:25:58","modified_gmt":"2025-11-27T10:25:58","slug":"android-storage-permission-adaptation-guide","status":"publish","type":"post","link":"https:\/\/imastudio.com\/es\/blog\/android-storage-permission-adaptation-guide","title":{"rendered":"Gu\u00eda de adaptaci\u00f3n de permisos de almacenamiento de Android para Android 11+"},"content":{"rendered":"<p class=\"wp-block-paragraph\">Cuando intent\u00e9 implementar un requisito muy simple \u2014 <strong>Descarga una imagen y gu\u00e1rdala en el almacenamiento local.<\/strong> \u2014 Al principio todo parec\u00eda estar bien.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Honor (Android 10) \u2013 funciona<\/li>\n\n\n\n<li>Redmi (Android 11) \u2013 funciona<\/li>\n\n\n\n<li>Xiaomi (Android 13) \u2013 funciona<\/li>\n\n\n\n<li><strong>Samsung (Android 13)<\/strong> \u2013 Fall\u00f3 por completo: el cuadro de di\u00e1logo de permisos de almacenamiento nunca aparec\u00eda.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Mismo c\u00f3digo, misma funci\u00f3n, pero un dispositivo en Android 13 simplemente se neg\u00f3 a mostrar la solicitud de permiso. As\u00ed es como esta peque\u00f1a tarea de &quot;descargar imagen&quot; se convirti\u00f3 en una inmersi\u00f3n profunda en <strong>Almacenamiento con alcance<\/strong> y <strong>GESTIONAR_ALMACENAMIENTO_EXTERNO<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Esta publicaci\u00f3n resume c\u00f3mo adapt\u00e9 los permisos de almacenamiento para <strong>Android 11 y versiones posteriores<\/strong>, y c\u00f3mo manejo los diferentes comportamientos en las distintas versiones.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">1. El error: El di\u00e1logo de permisos de almacenamiento nunca aparece (Samsung Android 13)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">El requisito es sencillo:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Descarga una imagen y gu\u00e1rdala en el dispositivo para que aparezca en la galer\u00eda.<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">En mis tres dispositivos de prueba:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Honor \u2013 Android 10 \u2192 OK<\/li>\n\n\n\n<li>Redmi \u2013 Android 11 \u2192 OK<\/li>\n\n\n\n<li>Xiaomi \u2013 Android 13 \u2192 OK<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Pero en un <strong>Dispositivo Samsung con Android 13<\/strong>, el sistema <strong>Nunca se mostr\u00f3 el cuadro de di\u00e1logo de permisos de almacenamiento.<\/strong>, sin importar c\u00f3mo lo solicitara.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"184\" src=\"https:\/\/imastudio.com\/wp-content\/uploads\/2025\/11\/20251127-182134-1024x184.jpeg\" alt=\"\" class=\"wp-image-3810\" srcset=\"https:\/\/imastudio.com\/wp-content\/uploads\/2025\/11\/20251127-182134-1024x184.jpeg 1024w, https:\/\/imastudio.com\/wp-content\/uploads\/2025\/11\/20251127-182134-300x54.jpeg 300w, https:\/\/imastudio.com\/wp-content\/uploads\/2025\/11\/20251127-182134-768x138.jpeg 768w, https:\/\/imastudio.com\/wp-content\/uploads\/2025\/11\/20251127-182134-18x3.jpeg 18w, https:\/\/imastudio.com\/wp-content\/uploads\/2025\/11\/20251127-182134.jpeg 1277w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1024\" height=\"168\" src=\"https:\/\/imastudio.com\/wp-content\/uploads\/2025\/11\/20251127-182139-1024x168.jpeg\" alt=\"\" class=\"wp-image-3811\" srcset=\"https:\/\/imastudio.com\/wp-content\/uploads\/2025\/11\/20251127-182139-1024x168.jpeg 1024w, https:\/\/imastudio.com\/wp-content\/uploads\/2025\/11\/20251127-182139-300x49.jpeg 300w, https:\/\/imastudio.com\/wp-content\/uploads\/2025\/11\/20251127-182139-768x126.jpeg 768w, https:\/\/imastudio.com\/wp-content\/uploads\/2025\/11\/20251127-182139-1536x253.jpeg 1536w, https:\/\/imastudio.com\/wp-content\/uploads\/2025\/11\/20251127-182139-18x3.jpeg 18w, https:\/\/imastudio.com\/wp-content\/uploads\/2025\/11\/20251127-182139.jpeg 1806w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1024\" height=\"174\" src=\"https:\/\/imastudio.com\/wp-content\/uploads\/2025\/11\/20251127-182150-1024x174.jpeg\" alt=\"\" class=\"wp-image-3808\" srcset=\"https:\/\/imastudio.com\/wp-content\/uploads\/2025\/11\/20251127-182150-1024x174.jpeg 1024w, https:\/\/imastudio.com\/wp-content\/uploads\/2025\/11\/20251127-182150-300x51.jpeg 300w, https:\/\/imastudio.com\/wp-content\/uploads\/2025\/11\/20251127-182150-768x131.jpeg 768w, https:\/\/imastudio.com\/wp-content\/uploads\/2025\/11\/20251127-182150-1536x262.jpeg 1536w, https:\/\/imastudio.com\/wp-content\/uploads\/2025\/11\/20251127-182150-18x3.jpeg 18w, https:\/\/imastudio.com\/wp-content\/uploads\/2025\/11\/20251127-182150.jpeg 1879w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Al principio pens\u00e9 que se trataba simplemente de otra peculiaridad del fabricante, pero despu\u00e9s de comprobar los cambios en los permisos de almacenamiento en las distintas versiones de Android, me di cuenta de que estaba utilizando un comportamiento que, en la pr\u00e1ctica, hab\u00eda quedado obsoleto en Android 13 al usar el SDK 33.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">2. Causa ra\u00edz: Las funciones WRITE\/READ_EXTERNAL_STORAGE est\u00e1n obsoletas en Android 13 (SDK 33).<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">En versiones anteriores de Android, pod\u00edamos simplemente declarar estos dos permisos en el manifiesto:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>LECTURA_ALMACENAMIENTO_EXTERNO<\/code><\/li>\n\n\n\n<li><code>ESCRIBIR_ALMACENAMIENTO_EXTERNO<\/code><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">y luego solicitarlas en tiempo de ejecuci\u00f3n cuando sea necesario.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En Android 13 (SDK 33) con <strong>targetSdkVersion = 33<\/strong>, Ese enfoque empieza a fallar:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>ESCRIBIR_ALMACENAMIENTO_EXTERNO<\/code> es <strong>obsoleto y pr\u00e1cticamente in\u00fatil<\/strong> en versiones recientes de Android<\/li>\n\n\n\n<li>Si a\u00f1ades <code>maxSdkVersion=32<\/code> Estos permisos siguen funcionando en Android 11\/12.<br>pero lo son <strong>ignorado<\/strong> en Android 13 al apuntar a 33<\/li>\n\n\n\n<li>Al mismo tiempo, Play Store exige que las nuevas aplicaciones tengan como objetivo al menos el SDK 33.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Por lo tanto, para Android 11+ debemos adaptarnos a:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Almacenamiento con alcance<\/strong><\/li>\n\n\n\n<li>Y en algunos casos, el permiso especial: <code>GESTIONAR_ALMACENAMIENTO_EXTERNO<\/code><\/li>\n<\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>GESTIONAR_ALMACENAMIENTO_EXTERNO<\/strong> otorga a una aplicaci\u00f3n un amplio acceso a todo el contenido del almacenamiento compartido (incluidos los archivos que no son multimedia). <strong>no<\/strong> Permite el acceso a los directorios privados de otras aplicaciones, pero Google Play a\u00fan lo considera un permiso altamente sensible.<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">Para dar soporte a diferentes versiones de Android, termin\u00e9 dividiendo el manejo de permisos en:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Antes de Android 11 (API &lt; 30)<\/strong> \u2013 Permisos de almacenamiento externo de estilo antiguo<\/li>\n\n\n\n<li><strong>Android 11 y versiones posteriores<\/strong> \u2013 Almacenamiento delimitado + manipulaci\u00f3n especial con <code>GESTIONAR_ALMACENAMIENTO_EXTERNO<\/code> donde sea estrictamente necesario<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">3. Adaptaci\u00f3n paso a paso<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">3.1 Declarar MANAGE_EXTERNAL_STORAGE en el manifiesto<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">En el <code>AndroidManifest.xml<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;uses-permission\n    android:name=\"android.permission.MANAGE_EXTERNAL_STORAGE\"\n    tools:ignore=\"ScopedStorage\" \/><\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">\u26a0\ufe0f Nota: Porque <code>GESTIONAR_ALMACENAMIENTO_EXTERNO<\/code> Es un permiso delicado, est\u00e1 restringido en Google Play. Hablar\u00e9 de alternativas m\u00e1s adelante si solo quieres guardar im\u00e1genes.<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">3.2 Comprobar si se ha concedido el permiso<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yo us\u00e9 <strong>Permisos f\u00e1ciles<\/strong> para simplificar las comprobaciones de permisos.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>private fun checkPer(activity: PreViewActivity): Boolean { return if (Build.VERSION.SDK_INT &gt;= 30) { EasyPermissions.hasPermissions( activity, android.Manifest.permission.MANAGE_EXTERNAL_STORAGE ) } else { EasyPermissions.hasPermissions( activity, android.Manifest.permission.WRITE_EXTERNAL_STORAGE ) } }\n<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>En <strong>Android 11+ (API &gt;= 30)<\/strong>: Yo reviso <code>GESTIONAR_ALMACENAMIENTO_EXTERNO<\/code><\/li>\n\n\n\n<li>En <strong>Android 10 y versiones anteriores<\/strong>: Todav\u00eda reviso <code>ESCRIBIR_ALMACENAMIENTO_EXTERNO<\/code><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Esta divisi\u00f3n es crucial, porque <code>ESCRIBIR_ALMACENAMIENTO_EXTERNO<\/code> Ya no se comporta como lo hac\u00eda en las versiones m\u00e1s recientes.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">3.3 Solicitar permiso cuando no est\u00e9 disponible<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Si no se concede el permiso, lo solicito de forma diferente seg\u00fan la versi\u00f3n del sistema.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>private fun requestStoragePermission(activity: PreViewActivity, curImg: Int) { if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.R) { \/\/ Android 11+ \u2013 redirigir a la p\u00e1gina de configuraci\u00f3n del sistema &quot;Acceso a todos los archivos&quot; val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION) intent.data = Uri.parse(&quot;package:&quot; + activity.packageName) activity.startActivityForResult(intent, 200) } else { \/\/ Android 10 y versiones anteriores \u2013 permiso de tiempo de ejecuci\u00f3n normal val perm = android.Manifest.permission.WRITE_EXTERNAL_STORAGE PaperThreeVariable.isToRequestPer = true EasyPermissions.requestPermissions( PermissionRequest.Builder( activity, 200, perm ).build() ) } }\n<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>En <strong>Android 11+<\/strong>: no puedes simplemente \u201cabrir\u201d un di\u00e1logo de tiempo de ejecuci\u00f3n normal para <code>GESTIONAR_ALMACENAMIENTO_EXTERNO<\/code><br>Debe enviar al usuario a la p\u00e1gina de configuraci\u00f3n del sistema donde deber\u00e1 otorgar manualmente el &quot;Acceso a todos los archivos&quot;.<\/li>\n\n\n\n<li>En <strong>Android 10 y versiones anteriores<\/strong>: El di\u00e1logo cl\u00e1sico de permisos en tiempo de ejecuci\u00f3n sigue funcionando.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">3.4 Manejo de devoluciones de llamada de permisos<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">EasyPermissions ayuda a conectar la funci\u00f3n de devoluci\u00f3n de llamada de la actividad con nuestra propia l\u00f3gica:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>override fun onRequestPermissionsResult( requestCode: Int, permissions: Array , grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) } override fun onPermissionsGranted(requestCode: Int, perms: MutableList ) { AppInitUtils().saveFreshAppImageToGallery(this, curImg) PaperThreeVariable.isToRequestPer = false } override fun onPermissionsDenied(requestCode: Int, perms: MutableList ) { PaperThreeVariable.isToRequestPer = false if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) { AppSettingsDialog.Builder(this) .setRationale(&quot;Esta funci\u00f3n requiere que se habilite el permiso de almacenamiento&quot;) .setNegativeButton(&quot;No&quot;) .setPositiveButton(&quot;S\u00ed&quot;) .build() .show() } }\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Por qu\u00e9 utilizo EasyPermissions aqu\u00ed:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Los usuarios pueden <strong>negar permanentemente<\/strong> permisos, lo que provoca que las solicitudes repetidas fallen silenciosamente<\/li>\n\n\n\n<li>EasyPermissions facilita lo siguiente:\n<ul class=\"wp-block-list\">\n<li>Detectar estado de \u201cdenegaci\u00f3n permanente\u201d<\/li>\n\n\n\n<li>Mostrar un cuadro de di\u00e1logo que gu\u00ede a los usuarios a <strong>Configuraci\u00f3n del sistema \u2192 Permisos de la aplicaci\u00f3n<\/strong> para habilitar el acceso al almacenamiento manualmente<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Una vez concedido el permiso, llamo:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>AppInitUtils().saveFreshAppImageToGallery(this, curImg)\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">para guardar la imagen y actualizar la galer\u00eda.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Tras esta adaptaci\u00f3n, el dispositivo Samsung con Android 13 finalmente se comport\u00f3 igual que los dem\u00e1s.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Nota al margen: Mi dispositivo Xiaomi se identificaba como Android 13, pero la secci\u00f3n &quot;Dispositivos conectados hist\u00f3ricos&quot; de Android Studio lo reconoc\u00eda como Android 12. Esto podr\u00eda explicar por qu\u00e9 segu\u00eda funcionando en algunos casos, pero precisamente por eso es importante gestionar los permisos teniendo en cuenta la versi\u00f3n del sistema.<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">4. Acerca de MANAGE_EXTERNAL_STORAGE y las restricciones de Google Play<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><code>GESTIONAR_ALMACENAMIENTO_EXTERNO<\/code> es poderoso:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Otorga acceso de lectura\/escritura a <strong>todo el almacenamiento compartido<\/strong> en el dispositivo.<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">Debido a esto, Google Play lo trata como un <strong>permiso altamente confidencial<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Est\u00e1 destinado principalmente a <strong>administrador de archivos \/ copia de seguridad \/ antivirus<\/strong> aplicaciones de tipo<\/li>\n\n\n\n<li>Debes presentar una justificaci\u00f3n para usarlo.<\/li>\n\n\n\n<li>Si tu aplicaci\u00f3n es solo una aplicaci\u00f3n de consumo t\u00edpica (por ejemplo, guardar im\u00e1genes, descargas simples), lo m\u00e1s probable es que tu solicitud sea <strong>rechazado<\/strong><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Entonces, si su \u00fanico requisito es:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">\u201cGuarda una imagen en la galer\u00eda y hazla visible para el usuario.\u201d<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">entonces deber\u00edas <strong>Considere seriamente evitar<\/strong> <code>GESTIONAR_ALMACENAMIENTO_EXTERNO<\/code> y en su lugar:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Usar <strong>MediaStore<\/strong> para insertar im\u00e1genes en la biblioteca de medios del sistema<\/li>\n\n\n\n<li>O bien, utilice API que puedan guardar im\u00e1genes sin necesidad de acceder al archivo completo.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Existen varios patrones para:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Guarda una imagen en el directorio Pictures\/DCIM.<\/li>\n\n\n\n<li>Notifica al esc\u00e1ner de medios o conf\u00eda en MediaStore para que la galer\u00eda pueda detectarlo.<\/li>\n\n\n\n<li>Haz todo esto <strong>sin solicitar MANAGE_EXTERNAL_STORAGE<\/strong><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Para la distribuci\u00f3n interna o fuera de Play Store (por ejemplo, tiendas de aplicaciones internas empresariales), t\u00e9cnicamente a\u00fan puede usar <code>Entorno.getExternalStorageDirectory()<\/code>, pero no recomiendo dise\u00f1ar una nueva aplicaci\u00f3n basada en esto en 2025.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">5. Resumen versi\u00f3n por versi\u00f3n (Android 9 \u2192 13)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Para tenerlo todo claro, aqu\u00ed ten\u00e9is un resumen general de c\u00f3mo se comportan el almacenamiento externo y los permisos en las distintas versiones.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Android 9 y versiones anteriores (API 28 y anteriores)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Permisos<\/strong>:\n<ul class=\"wp-block-list\">\n<li><code>LECTURA_ALMACENAMIENTO_EXTERNO<\/code><\/li>\n\n\n\n<li><code>ESCRIBIR_ALMACENAMIENTO_EXTERNO<\/code><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Comportamiento<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Las aplicaciones pueden acceder libremente <code>\/tarjeta sd<\/code> y sus subdirectorios<\/li>\n\n\n\n<li>Los archivos creados por la aplicaci\u00f3n permanecen en el dispositivo incluso despu\u00e9s de desinstalarla.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Enfoque t\u00edpico<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Lectura\/escritura directa en rutas de almacenamiento externas.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Android 10 (API 29) \u2013 Introducci\u00f3n del almacenamiento con \u00e1mbito<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Permisos<\/strong>:\n<ul class=\"wp-block-list\">\n<li><code>LECTURA_ALMACENAMIENTO_EXTERNO<\/code> Todav\u00eda funciona<\/li>\n\n\n\n<li><code>ESCRIBIR_ALMACENAMIENTO_EXTERNO<\/code> Todav\u00eda existe, pero su alcance efectivo se ha reducido.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Comportamiento<\/strong>:\n<ul class=\"wp-block-list\">\n<li><strong>Almacenamiento con alcance<\/strong> se presenta:\n<ul class=\"wp-block-list\">\n<li>Las aplicaciones est\u00e1n limitadas a su propio directorio espec\u00edfico de aplicaciones en<br><code>Android\/datos\/nombre.de.tu.paquete\/<\/code><\/li>\n\n\n\n<li>El acceso directo a los archivos de otras aplicaciones est\u00e1 restringido.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Se debe acceder a los archivos multimedia (im\u00e1genes, v\u00eddeos, audio) a trav\u00e9s de <strong>MediaStore<\/strong><\/li>\n\n\n\n<li><code>requestLegacyExternalStorage=true<\/code> podr\u00eda mantener temporalmente el comportamiento anterior<br>(pero esta bandera se ignora a partir de Android 11)<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Enfoque recomendado<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Para im\u00e1genes\/v\u00eddeos\/audio: utilice <strong>MediaStore<\/strong><\/li>\n\n\n\n<li>Para archivos privados: utilice <code>obtenerDirectorioDeArchivosExternos()<\/code> o <code>obtenerDirectorioDeDatos()<\/code><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Android 11 (API 30) \u2013 Almacenamiento con \u00e1mbito restringido (aplicado)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Permisos<\/strong>:\n<ul class=\"wp-block-list\">\n<li><code>LECTURA_ALMACENAMIENTO_EXTERNO<\/code> Funciona, pero solo para contenido multimedia gestionado por MediaStore.<\/li>\n\n\n\n<li><code>ESCRIBIR_ALMACENAMIENTO_EXTERNO<\/code> es efectivamente <strong>obsoleto<\/strong> para almacenamiento externo general<\/li>\n\n\n\n<li><code>GESTIONAR_ALMACENAMIENTO_EXTERNO<\/code> Introducido para casos de uso especiales de \u201cacceso a todos los archivos\u201d.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Comportamiento<\/strong>:\n<ul class=\"wp-block-list\">\n<li><code>requestLegacyExternalStorage=true<\/code> ya no funciona; Almacenamiento con \u00e1mbito es <strong>siempre encendido<\/strong><\/li>\n\n\n\n<li>Acceso a <code>\/tarjetas SD\/<\/code> La ra\u00edz est\u00e1 bloqueada<\/li>\n\n\n\n<li>Las aplicaciones solo pueden:\n<ul class=\"wp-block-list\">\n<li>Acceda a sus propios directorios privados<\/li>\n\n\n\n<li>Acceda a los medios compartidos a trav\u00e9s de <strong>MediaStore<\/strong><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Enfoque recomendado<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Para aplicaciones t\u00edpicas:\n<ul class=\"wp-block-list\">\n<li>Utilice MediaStore o <strong>Fuerzas Armadas de Singapur<\/strong> (<code>ACCI\u00d3N_ABRIR_DOCUMENTO<\/code>, <code>ACCI\u00d3N_CREAR_DOCUMENTO<\/code>) para archivos seleccionados por el usuario<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Solo considere <code>GESTIONAR_ALMACENAMIENTO_EXTERNO<\/code> si tu aplicaci\u00f3n es realmente un administrador de archivos, una herramienta de copia de seguridad, una aplicaci\u00f3n de seguridad, etc.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Android 13 (API 33) \u2013 Divisi\u00f3n de permisos multimedia<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Permisos<\/strong>:\n<ul class=\"wp-block-list\">\n<li><code>LEER_IM\u00c1GENES_MEDIA<\/code> \u2013 acceder a las im\u00e1genes<\/li>\n\n\n\n<li><code>LEER_VIDEO_MEDIA<\/code> \u2013 acceder a los v\u00eddeos<\/li>\n\n\n\n<li><code>LEER_MEDIA_AUDIO<\/code> \u2013 acceso al audio<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Comportamiento<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Los permisos de los medios son <strong>de grano fino<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Los usuarios pueden otorgar acceso solo a im\u00e1genes, solo a v\u00eddeos, etc.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Las reglas de almacenamiento con \u00e1mbito de Android 11 siguen vigentes.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Enfoque recomendado<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Solicita los permisos de medios espec\u00edficos que necesitas:\n<ul class=\"wp-block-list\">\n<li>Por ejemplo, si solo trabaja con im\u00e1genes, solicite solo <code>LEER_IM\u00c1GENES_MEDIA<\/code><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Hacer <strong>no<\/strong> pedido <code>LECTURA_ALMACENAMIENTO_EXTERNO<\/code> en Android 13+, ya que se reemplaza por los nuevos permisos de medios<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Matriz r\u00e1pida (conceptual)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Android 9 y versiones anteriores<\/strong>\n<ul class=\"wp-block-list\">\n<li>El acceso al almacenamiento externo es amplio y est\u00e1 controlado por READ\/WRITE_EXTERNAL_STORAGE.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Android 10<\/strong>\n<ul class=\"wp-block-list\">\n<li>Se ha introducido el almacenamiento con \u00e1mbito, pero existen v\u00edas de escape (<code>solicitudAlmacenamientoExternoLegado<\/code>)<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Android 11<\/strong>\n<ul class=\"wp-block-list\">\n<li>Se aplica el almacenamiento con \u00e1mbito restringido y se eliminan los conmutadores heredados.<\/li>\n\n\n\n<li><code>GESTIONAR_ALMACENAMIENTO_EXTERNO<\/code> aparece, pero est\u00e1 muy restringido.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Android 13<\/strong>\n<ul class=\"wp-block-list\">\n<li>El acceso a los medios se dividi\u00f3 en <code>LEER_MEDIOS_*<\/code> permisos<\/li>\n\n\n\n<li>Las mismas reglas de almacenamiento con \u00e1mbito definido, pero con un control de usuario m\u00e1s preciso.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">6. Conclusiones<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>No des por sentado que &quot;funciona en un dispositivo Android 13&quot; significa que funciona en todas partes; los fabricantes de equipos originales y los informes del sistema pueden ser inconsistentes.<\/li>\n\n\n\n<li>Para <strong>Android 11+<\/strong>, Piensa en t\u00e9rminos de:\n<ul class=\"wp-block-list\">\n<li><strong>Directorios privados de la aplicaci\u00f3n + MediaStore + SAF<\/strong>, no \u201ccrudo\u201d <code>\/tarjeta sd<\/code> acceso&quot;\u201d<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Tratar <code>GESTIONAR_ALMACENAMIENTO_EXTERNO<\/code> como un <strong>\u00faltimo recurso<\/strong> Para tipos de aplicaciones muy espec\u00edficos, especialmente si planeas publicarlas en Google Play.<\/li>\n\n\n\n<li>Siempre prueba en <strong>M\u00faltiples dispositivos y versiones de Android<\/strong>, especialmente en lo que respecta a permisos y almacenamiento.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Este art\u00edculo surge de mi propia experiencia depurando y adaptando el texto en proyectos reales de Android (incluido un dispositivo Samsung con Android 13). GPT solo colabor\u00f3 en la traducci\u00f3n y el perfeccionamiento de la redacci\u00f3n; todo el contenido t\u00e9cnico y las decisiones son responsabilidad m\u00eda.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n<\/blockquote>","protected":false},"excerpt":{"rendered":"<p>When I tried to implement a very simple requirement \u2014 download an image and save it to local storage \u2014 everything looked fine at first. Same code, same feature, but one device on Android 13 simply refused to show the permission prompt. That\u2019s how this small \u201cdownload image\u201d task turned into a deep dive into [&hellip;]<\/p>","protected":false},"author":10,"featured_media":3804,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"rank_math_title":"","rank_math_description":"","footnotes":""},"categories":[35],"tags":[],"class_list":["post-3803","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-knowledge-hub"],"_links":{"self":[{"href":"https:\/\/imastudio.com\/es\/wp-json\/wp\/v2\/posts\/3803","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/imastudio.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/imastudio.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/imastudio.com\/es\/wp-json\/wp\/v2\/users\/10"}],"replies":[{"embeddable":true,"href":"https:\/\/imastudio.com\/es\/wp-json\/wp\/v2\/comments?post=3803"}],"version-history":[{"count":4,"href":"https:\/\/imastudio.com\/es\/wp-json\/wp\/v2\/posts\/3803\/revisions"}],"predecessor-version":[{"id":3812,"href":"https:\/\/imastudio.com\/es\/wp-json\/wp\/v2\/posts\/3803\/revisions\/3812"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/imastudio.com\/es\/wp-json\/wp\/v2\/media\/3804"}],"wp:attachment":[{"href":"https:\/\/imastudio.com\/es\/wp-json\/wp\/v2\/media?parent=3803"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/imastudio.com\/es\/wp-json\/wp\/v2\/categories?post=3803"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/imastudio.com\/es\/wp-json\/wp\/v2\/tags?post=3803"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}