Introduction
KlugTorch switches the camera light of a phone or tablet on and off from an AIR app: the LED next to the back camera, often called torch or flashlight. Typical uses are a pet or baby camera in a dark room, a document scanner, or a video call at night.
Before you offer a light button, KlugTorch tells you whether the device has a usable camera light at all. Many tablets and some phones have none, so the app can hide the button there.
KlugTorch does not open a camera of its own. On iOS it switches the light of the back camera directly, also while the camera is streaming. On Android it uses the system torch control, which works as long as no other part of the app holds the camera open (see Using the light while streaming).
| Extension ID | com.klug.torch.Torch |
| Version | 1.0.0 |
| Platforms | iOS, Android |
| ActionScript package | com.klug.torch, one class: Torch |
| Delivery | The extension file com.klug.torch.Torch.ane, the ActionScript library KlugTorch.swc and this documentation |
Requirements
| AIR SDK | 51.x (HARMAN) |
| iOS | iOS 17 or later, iPhone and iPad |
| Android | Android 6.0 (API 23) or later. On older versions isSupported returns false. |
| Hardware | A camera light next to the back camera. A light that only belongs to a front camera is not used. |
| Permissions | None of its own. KlugTorch does not open the camera, so it does not ask for camera access. If your app streams video, the camera permission belongs to that part of the app. |
| Other platforms | macOS, Windows and the AIR simulator: the extension can stay in the build; isSupported returns false and the calls do nothing. |
Add the extension
1 · Copy the files
Copy com.klug.torch.Torch.ane into your project's extension folder, for example extensions/. In your IDE add the .ane as a native extension of the project. When you build on the command line, compile against KlugTorch.swc as an external library and give adt the extension folder:
amxmlc -external-library-path+=lib/KlugTorch.swc -output Main.swf src/Main.as adt -package -target ipa-app-store ... -extdir extensions adt -package -target aab ... -extdir extensions
2 · Declare it in the application descriptor
<extensions>
<extensionID>com.klug.torch.Torch</extensionID>
</extensions>
3 · Platform settings
KlugTorch needs no further entries in the application descriptor:
- iOS: no InfoAdditions keys and no entitlements. KlugTorch does not show a camera prompt.
- Android: no permissions, features, activities or services in <manifestAdditions>. The system torch control needs no permission.
- macOS and desktop: nothing to add; the extension does nothing there.
If your app also streams the camera, keep the camera settings that your streaming code needs, for example the camera usage description on iOS and the camera permission on Android. They are not required by KlugTorch.
Getting started
Torch is a singleton: always use Torch.getInstance(). Check isSupported first, then call on() or off(). Both return at once. The result arrives as an Event.CHANGE; the event carries no detail, so read mode to see whether the light is on.
import com.klug.torch.Torch; import flash.events.Event; var torch:Torch = Torch.getInstance(); if ( torch.isSupported ) { torch.addEventListener( Event.CHANGE, onTorchChange ); torch.on(); // returns at once } function onTorchChange( e:Event ):void { trace( "light is on: " + torch.mode ); // true or false }
Where the extension is not available (desktop, simulator) isSupported is false, so the same code can stay in every build.
Guides
Show the light button only where there is a light
isSupported asks the device each time you read it. It is true only when there is a light you can switch from the app:
- iOS: the default camera (the back camera) has a torch.
- Android: Android 6.0 or later, and a back-facing camera with a flash. A device whose only flash belongs to the front camera reports false.
- Other platforms: always false.
import com.klug.torch.Torch; var torch:Torch = Torch.getInstance(); // lightButton: your app's toggle button lightButton.visible = torch.isSupported; lightButton.selected = torch.isSupported && torch.mode;
Switch the light and follow the result
on() and off() return immediately. Afterwards KlugTorch dispatches one Event.CHANGE, whether the switch succeeded or not. Compare mode with what you asked for to detect a failure.
import com.klug.torch.Torch; import flash.events.Event; var torch:Torch = Torch.getInstance(); var wantLight:Boolean = false; torch.addEventListener( Event.CHANGE, onTorchChange ); function setLight( on:Boolean ):void { if ( !torch.isSupported ) return; wantLight = on; if ( on ) torch.on(); else torch.off(); } function onTorchChange( e:Event ):void { lightButton.selected = torch.mode; // the real state after the call if ( torch.mode != wantLight ) // the light could not be switched showMessage( "The light is not available right now." ); // your app }
How mode is read: on iOS it reads the current torch state of the camera, so it also reflects changes made elsewhere. On Android it reports the state of the last successful on() or off() of this extension; a failed call leaves it unchanged.
Using the light while streaming
Camera apps usually want the light while the camera is running. The two platforms behave differently:
- iOS: KlugTorch switches the light of the back camera directly and does not start a camera session, so it works alongside a running camera stream without interrupting it. The light belongs to the back camera: while the front camera is in use, the light may not switch on, and mode stays false.
- Android: the system does not switch the light while another component holds the camera open, in your app or in another app. on() then ends with a change event and mode stays false. Only the component that owns the camera can switch the light in that situation.
If your app streams with KlugMedia, KlugMedia owns the camera: switch the light through its setTorch() while it is streaming, and use KlugTorch when the camera is not open.
import com.klug.torch.Torch; import com.klug.petcam.camera.CameraStreamANE; var streaming:Boolean = false; // your app sets this while KlugMedia publishes function setLight( on:Boolean ):void { if ( streaming ) { // the camera owner switches the light while the camera is open var media:CameraStreamANE = CameraStreamANE.instance; if ( media.hasTorch ) media.setTorch( on ); return; } var torch:Torch = Torch.getInstance(); if ( !torch.isSupported ) return; if ( on ) torch.on(); else torch.off(); }
Background, return and stream stop
The light is a shared device resource. The system or another app can switch it off while your app is in the background, for example when the camera is opened elsewhere. Switch it off yourself when it is no longer needed, and set it again when your app returns.
import com.klug.torch.Torch; import flash.desktop.NativeApplication; import flash.events.Event; var torch:Torch = Torch.getInstance(); var wantLight:Boolean = false; // what the user asked for NativeApplication.nativeApplication.addEventListener( Event.DEACTIVATE, onDeactivate ); NativeApplication.nativeApplication.addEventListener( Event.ACTIVATE, onActivate ); function onDeactivate( e:Event ):void { if ( torch.isSupported ) torch.off(); // do not leave the light on in the background } function onActivate( e:Event ):void { // set the wanted state again: on Android mode only knows this extension's last call if ( torch.isSupported && wantLight ) torch.on(); } function stopStreaming():void { if ( torch.isSupported ) torch.off(); // first the light, then the camera stopCamera(); // your app's stream shutdown }
On Android, mode does not see changes made by the system or other apps. After returning to the foreground, call on() or off() once to bring the light and mode back to a known state.
Error handling
KlugTorch never throws from on(), off(), isSupported or mode because of a missing or busy light. A failure is reported the same way as a success: one Event.CHANGE, after which mode has not changed. Common reasons:
- The device has no usable camera light (check isSupported first).
- Android: another component holds the camera open.
- iOS: the light is temporarily unavailable, for example when the device is too warm, or the front camera is in use.
- Android 5.x: the light cannot be switched from the app.
Where the extension is not available at all (desktop, simulator), on() and off() return without doing anything and no event follows. isSupported and mode return false.
function onTorchChange( e:Event ):void { if ( torch.mode == wantLight ) return; // success if ( wantLight && cameraIsStreaming() ) // your app: Android, camera busy switchLightThroughCameraOwner( true ); // your app, see the streaming guide else lightButton.selected = torch.mode; // show the real state }
API reference
Package com.klug.torch. Torch extends flash.events.EventDispatcher, so addEventListener() and removeEventListener() are available as usual.
class Torch
| Member | Description |
| static getInstance():Torch | Returns the single instance and creates it on the first call. Use this instead of the constructor. All platforms. |
| Torch() | Constructor. Do not call it directly: a second instance throws an Error ("Torch is a singleton, use Torch.getInstance()"). |
| isSupported:Boolean | Read-only. True if the device has a usable camera light: iOS, the default (back) camera has a torch; Android 6.0 or later, a back-facing camera has a flash. False on devices without a light and on other platforms. |
| mode:Boolean | Read-only. True while the light is on. iOS: the current torch state of the camera. Android: the state after the last successful on() / off() of this extension. False on other platforms. |
| on():void | Switches the camera light on. Returns at once; an Event.CHANGE follows on iOS and Android, also when the light could not be switched. Does nothing on other platforms. |
| off():void | Switches the camera light off. Returns at once; an Event.CHANGE follows on iOS and Android, also when it fails. Does nothing on other platforms. |
Events
KlugTorch dispatches one event type on the Torch instance.
| Event | When and payload |
| Event.CHANGE ("change") | Dispatched once after every on() and off() on iOS and Android, on success and on failure. A plain flash.events.Event without detail: read mode for the result. It arrives asynchronously, shortly after the call returned. Not dispatched on platforms where the extension is not available. |
There are no separate success or error events. Compare mode with the state you asked for.
Troubleshooting
The change event does not tell me whether it worked.
That is by design. Read mode in the handler: if it differs from what you asked for, the light could not be switched.
On Android the light does not switch on while my app streams.
The system refuses the light while another component holds the camera open, for example a stream from AIR's flash.media.Camera. mode stays false after the change event. Switch the light through the component that owns the camera; with KlugMedia use its setTorch().
isSupported is false on a device that has a flash.
On Android the flash has to belong to a back-facing camera and the device needs Android 6.0 or later; a flash on the front camera only is not counted. On iOS the default camera must have a torch. On desktop and in the simulator it is always false.
On Android the light is on, but mode says false (or the other way round).
On Android mode remembers the last successful call of this extension. If the system, the quick settings or another app changed the light, mode does not know. Call on() or off() again to get a known state. On iOS mode reads the camera directly.
The light went off by itself.
The light is shared with the system. It can be switched off when another app or component opens the camera, when the app goes to the background, or on iOS when the device gets too warm. Set it again when your app returns (see Background, return and stream stop).
The light does not help the picture.
The light sits next to the back camera. If your app streams the front camera, the light points away from the scene, and on iOS it may not switch on at all. Stream the back camera when the light is needed.
No event arrives on desktop.
Correct: where the extension is not available, the calls do nothing and no event is dispatched. Check isSupported before showing a light control.
Do I need the camera permission?
Not for KlugTorch. It does not open the camera. Your streaming code still needs its own camera permission.
Changelog
1.0.0 · update
- Android: isSupported and the light now use only a back-facing camera with a flash. Devices whose only flash belongs to the front camera report false, so a light button can be hidden there.
1.0.0 · first release
- Switch the camera light on and off on iOS and Android with one API.
- Detect whether the device has a camera light (isSupported) and read its state (mode).
- A change event after every switch, also when it fails.
- iOS: works while the camera is streaming, without interrupting the stream.