← All extensions

Native extension

KlugGallery

com.klug.gallery

NO APM NEEDED. Download and enjoy. It can’t get any simpler. Just update the Adobe AIR SDK. If you need help, we are here.

Save photos and videos from your AIR app to the gallery of the device, on iOS and Android, with the smallest permission the system offers.

iOS Android In production From €19 / year · Buy

Overview

KlugGallery saves pictures and videos from your AIR app to the photo gallery of the device: a BitmapData such as a snapshot, or a photo or video file your app has recorded or downloaded.

It only asks for what saving needs. On iPhone and iPad it requests add-only access, so your app never sees the user's library. On Android 10 and later saving needs no permission at all; on Android 6 to 9 KlugGallery asks for storage access at runtime.

Files land where users look for them: in Photos on iOS, and in Pictures/<app name> or Movies/<app name> on Android.

KlugGallery is in daily use in our apps on iOS and Android, our proof of concept.

Features

  • Self-contained: one ANE, no core library or dependency ANEs to add
  • Save a BitmapData as PNG or JPEG, with quality and file name
  • Copy a photo or video file into the gallery (mp4, mov and m4v are saved as videos)
  • iOS: add-only photo access, the user's library stays private
  • Android 10 and later: no permission needed; Android 6 to 9: runtime storage permission
  • Own album folder per app on Android
  • Permission status and a shortcut to the app settings after a denial
  • One event per result, with the error message when something fails

Supported platforms

iOS iPhone · iPad · Photos, add-only access
Android phones · tablets · foldables · MediaStore

On other platforms isSupported returns false, so the same code can stay in a cross-platform app.

Getting started

Add the extension to your application descriptor:

app.xml
<extensions>
    <extensionID>com.klug.gallery</extensionID>
</extensions>

iOS: explain in the InfoAdditions why your app saves to Photos:

app.xml · iPhone InfoAdditions
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Saves your snapshots and videos to Photos.</string>

Android: only needed for Android 6 to 9; newer versions ignore it.

app.xml · Android manifest
<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>

Code examples

Three complete flows, taken from the API that runs in our apps. Every call returns at once; the result arrives as a GalleryEvent. Full documentation →

1 · Save a snapshot
Snapshot.as
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" );
}
2 · Save a recorded video
Video.as
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 );
3 · Ask for permission only when it is needed
Permission.as
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;
});

API overview

Gallery.getInstance()Returns the single instance.
isSupportedTrue on iOS and Android, false elsewhere.
authorisationStatus()AUTHORISED, DENIED, NOT_DETERMINED, SHOULD_EXPLAIN, RESTRICTED, LIMITED or UNKNOWN.
requestAuthorisation()Shows the system prompt while the user has not decided yet. The answer arrives as GalleryEvent.AUTHORISATION.
addBitmapData(bitmapData, format, quality, filename)Saves the picture as "png" or "jpg". Result: ADD_COMPLETE or ADD_ERROR.
addFile(file)Copies a photo or video file (File or native path) into the gallery. Result: ADD_FILE_COMPLETE or ADD_FILE_ERROR.
canOpenDeviceSettingsTrue where the app settings can be opened.
openDeviceSettings()Opens the settings page of your app.

Events

GalleryEvent: the type names what happened, status carries the details.

GalleryEvent.AUTHORISATIONstatus = the new permission status
GalleryEvent.ADD_COMPLETEthe picture was saved
GalleryEvent.ADD_ERRORstatus = the error message
GalleryEvent.ADD_FILE_COMPLETEthe file was saved
GalleryEvent.ADD_FILE_ERRORstatus = the error message

Buy KlugGallery

A yearly licence for one AIR application, with all updates for 12 months. After payment you receive the extension, the ActionScript library and the documentation by e-mail, usually within one business day. Licence and terms

Simple
€19 / year
  • Licence for one AIR application
  • All updates for 12 months
  • No support
Buy Simple
Standard
€149 / year
  • Licence for one AIR application
  • All updates for 12 months
  • Answer by e-mail within 7 days
Buy Standard
Priority
€299 / year
  • Licence for one AIR application
  • All updates for 12 months
  • Answer by e-mail within 48 hours
Buy Priority
Taxes are calculated at checkout by Link (Stripe). You enter the application ID of your AIR app during checkout.

Requirements

AIR SDK51.x (HARMAN)
iOSiOS 13 or later (add-only access from iOS 14)
AndroidAndroid 6.0 (API 23) or later
iOS descriptorNSPhotoLibraryAddUsageDescription in InfoAdditions
Android descriptorPermission activity; storage permission for Android 6 to 9