Resumen
KlugGallery guarda imágenes y vídeos de tu app AIR en la galería de fotos del dispositivo: un BitmapData, como una captura, o un archivo de foto o vídeo que tu app ha grabado o descargado.
Solo pide lo que necesita para guardar. En iPhone y iPad solicita acceso de solo añadir, así que tu app nunca ve la fototeca del usuario. En Android 10 y posteriores, guardar no requiere ningún permiso; en Android 6 a 9, KlugGallery solicita acceso al almacenamiento en tiempo de ejecución.
Los archivos van a parar donde los usuarios los buscan: en Fotos en iOS, y en Pictures/<app name> o Movies/<app name> en Android.
KlugGallery se usa a diario en nuestras apps en iOS y Android, nuestra prueba de concepto.
Funciones
- Autónoma: una ANE, sin biblioteca central ni ANE de dependencias que añadir
- Guardar un BitmapData como PNG o JPEG, con calidad y nombre de archivo
- Copiar un archivo de foto o vídeo en la galería (mp4, mov y m4v se guardan como vídeos)
- iOS: acceso a fotos de solo añadir, la fototeca del usuario sigue siendo privada
- Android 10 y posteriores: no requiere permisos; Android 6 a 9: permiso de almacenamiento en tiempo de ejecución
- Carpeta de álbum propia para cada app en Android
- Estado de los permisos y acceso directo a los ajustes de la app tras una denegación
- Un evento por resultado, con el mensaje de error cuando algo falla
Plataformas compatibles
En otras plataformas isSupported devuelve false, por lo que el mismo código puede permanecer en una app multiplataforma.
Primeros pasos
Añade la extensión al descriptor de tu aplicación:
<extensions>
<extensionID>com.klug.gallery</extensionID>
</extensions>
iOS: explica en InfoAdditions por qué tu app guarda en Fotos:
<key>NSPhotoLibraryAddUsageDescription</key> <string>Saves your snapshots and videos to Photos.</string>
Android: solo es necesario para Android 6 a 9; las versiones más recientes lo ignoran.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28"/>
<application>
<activity android:name="com.klug.gallery.KlugGalleryPermissionActivity" android:exported="false"
android:theme="@android:style/Theme.Translucent.NoTitleBar"/>
</application>
Ejemplos de código
Tres flujos completos, tomados de la API que funciona en nuestras apps. Cada llamada devuelve de inmediato; el resultado llega como un GalleryEvent. Documentación completa →
import com.klug.gallery.Gallery; import com.klug.gallery.GalleryEvent; import flash.display.BitmapData; var gallery:Gallery = Gallery.getInstance(); gallery.addEventListener( GalleryEvent.ADD_COMPLETE, function( e:GalleryEvent ):void { showToast( "Saved to your gallery" ); // your app function }); gallery.addEventListener( GalleryEvent.ADD_ERROR, function( e:GalleryEvent ):void { trace( "could not save: " + e.status ); // the error message }); function saveSnapshot( picture:BitmapData ):void { if ( !gallery.isSupported ) return; // "png" or "jpg"; quality 0..1 counts for jpg gallery.addBitmapData( picture, "jpg", 0.9, "snapshot.jpg" ); }
import flash.filesystem.File; gallery.addEventListener( GalleryEvent.ADD_FILE_COMPLETE, function( e:GalleryEvent ):void { showToast( "Video saved" ); }); gallery.addEventListener( GalleryEvent.ADD_FILE_ERROR, function( e:GalleryEvent ):void { trace( "could not save the video: " + e.status ); }); // a File or a native path; mp4, mov and m4v are saved as videos, everything else as a photo var clip:File = File.applicationStorageDirectory.resolvePath( "clips/last.mp4" ); gallery.addFile( clip );
var pending:BitmapData; function save( picture:BitmapData ):void { var status:String = gallery.authorisationStatus(); if ( status == Gallery.AUTHORISED || status == Gallery.LIMITED ) gallery.addBitmapData( picture, "png" ); else if ( status == Gallery.DENIED || status == Gallery.RESTRICTED ) askToOpenSettings(); // your dialog, then gallery.openDeviceSettings() else { pending = picture; // not asked yet: show the system prompt gallery.requestAuthorisation(); } } gallery.addEventListener( GalleryEvent.AUTHORISATION, function( e:GalleryEvent ):void { if ( e.status == Gallery.AUTHORISED && pending != null ) gallery.addBitmapData( pending, "png" ); pending = null; });
Resumen de la API
| Gallery.getInstance() | Devuelve la instancia única. |
| isSupported | Verdadero en iOS y Android, falso en el resto. |
| authorisationStatus() | AUTHORISED, DENIED, NOT_DETERMINED, SHOULD_EXPLAIN, RESTRICTED, LIMITED o UNKNOWN. |
| requestAuthorisation() | Muestra el aviso del sistema mientras el usuario aún no ha decidido. La respuesta llega como GalleryEvent.AUTHORISATION. |
| addBitmapData(bitmapData, format, quality, filename) | Guarda la imagen como "png" o "jpg". Resultado: ADD_COMPLETE o ADD_ERROR. |
| addFile(file) | Copia un archivo de foto o vídeo (File o ruta nativa) en la galería. Resultado: ADD_FILE_COMPLETE o ADD_FILE_ERROR. |
| canOpenDeviceSettings | Verdadero donde se pueden abrir los ajustes de la app. |
| openDeviceSettings() | Abre la página de ajustes de tu app. |
Eventos
GalleryEvent: el type indica lo que ocurrió y status contiene los detalles.
| GalleryEvent.AUTHORISATION | status = el nuevo estado de permisos |
| GalleryEvent.ADD_COMPLETE | la imagen se guardó |
| GalleryEvent.ADD_ERROR | status = el mensaje de error |
| GalleryEvent.ADD_FILE_COMPLETE | el archivo se guardó |
| GalleryEvent.ADD_FILE_ERROR | status = el mensaje de error |
Compra KlugGallery
Una licencia anual para una aplicación AIR, con todas las actualizaciones durante 12 meses. Tras el pago recibes la extensión, la biblioteca ActionScript y la documentación por e-mail, normalmente en un día hábil. Licencia y términos
- Licencia para una aplicación AIR
- Todas las actualizaciones durante 12 meses
- Sin soporte
- Licencia para una aplicación AIR
- Todas las actualizaciones durante 12 meses
- Respuesta por e-mail en un plazo de 7 días
- Licencia para una aplicación AIR
- Todas las actualizaciones durante 12 meses
- Respuesta por e-mail en un plazo de 48 horas
Requisitos
| AIR SDK | 51.x (HARMAN) |
| iOS | iOS 13 o posterior (acceso de solo añadir desde iOS 14) |
| Android | Android 6.0 (API 23) o posterior |
| Descriptor de iOS | NSPhotoLibraryAddUsageDescription en InfoAdditions |
| Descriptor de Android | Activity de permisos; permiso de almacenamiento para Android 6 a 9 |