iOS check if torch is on
While this doesn't technically solve the problem this is KVO code for determining a state change in the torch. Maybe this could help. I am trying to solve the same problem but am unable to access any information about the torch that is turned on from the control center. It seems there should be some other way using KVO or something else to know if the torch is currently active or not.
static void * const torchActiveObservationContext = (void*)&torchActiveObservationContext;
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (context == torchActiveObservationContext) {
AVCaptureDevice *thisDevice = (AVCaptureDevice*)object;
NSLog( @"Current torch level: %f", thisDevice.torchActive);
}
else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
-(id) init {
if (self = [super init]) {
AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
[videoDevice addObserver:self forKeyPath:@"torchActive" options:NSKeyValueObservingOptionNew context:torchActiveObservationContext];
// whatever other initialization code ...
}
return self;
}
I also tried using torchLevel and torchMode to no avail. This is a real issue because I want to leave the torch on if it is on already when taking over control of the AVCaptureDevice.
torchLevel KVO - iOS
It took a while for me to figure out how to do this but I believe this KVO code will work for you. I haven't tested this code out thoroughly but I did get it basically working in an app:
static void * const torchLevelObservationContext = (void*)&torchLevelObservationContext;
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (context == torchLevelObservationContext) {
AVCaptureDevice *thisDevice = (AVCaptureDevice*)object;
NSLog( @"Current torch level: %f", thisDevice.torchLevel);
}
else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
-(id) init {
if (self = [super init]) {
AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
[videoDevice addObserver:self forKeyPath:@"torchLevel" options:NSKeyValueObservingOptionNew context:torchLevelObservationContext];
// whatever other initialization code ...
}
return self;
}
Caveat: the main reason I was trying to use this code is to determine the current state of the torch that is turned on via the control center so I could leave it on when using the AVCaptureDevice and the torch is turned off for some reason once the capture starts. But no matter what I tried (torchActive, torchMode, torchLevel), I was unable to determine the state. This code only seems to work after it has taken control of the AVCaptureDevice and is using it an AVCaptureSession. If anyone knows how to get the current state of the flashlight or torch that is turned on from the control center, that is what I am trying to do.
iOS: Torch level on iPhone 11 Pro
I remembered that back in the iOS 3.x days we didn't have simple LED API. We had to start a full video capture session. Well it turns out that with the iPhone 11 this seems to be the only solution. I'd love to hear about others which don't require this.
This is my tested workaround. I am using Objective C here, not Swift because that's what I used in this old app from 2009! You can easily find Swift code to start video capture (and ignore the output, it should work the same.
AVCaptureSession* session = [[AVCaptureSession alloc] init];
AVCaptureDevice *inputDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:inputDevice error:&error];
if ([session canAddInput:deviceInput]) {
[session addInput:deviceInput];
}
AVCaptureVideoPreviewLayer *previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
[previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
CALayer *rootLayer = self.view.layer;
[rootLayer setMasksToBounds:YES];
CGRect frame = self.view.frame;
[previewLayer setFrame:frame];
[rootLayer insertSublayer:previewLayer atIndex:0];
//This is where you'd save the video with AVCaptureVideoDataOutput but of course we don't.
[session startRunning];
And after this you just start the LED as usual:
NSError *error = nil;
if ([inputDevice isTorchModeSupported:AVCaptureTorchModeOn])
[inputDevice setTorchModeOnWithLevel:1.0 error:&error];
This gets maximum brightness on my iPhone 11 Pro. I am now looking for the same solution without having to use the video capture (which obviously uses battery AND requires a permission, which users may not like. It needs to be explained well).
setTorchModeOnWithLevel from string
You need to cast torchLevel
to Float.
Or make it float explicitly like so :
var torchLevel : Float = 0.0
How to turn flashlight ON and OFF in swift?
Update #1: (torchActive
isn't returning the expected value; perhaps because it's been modified)
Update #2: For Swift 2.0
To toggle the flash from on to off (not just "on" as in mad pig's answer), you can use the following method:
func toggleFlash() {
let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
if (device.hasTorch) {
do {
try device.lockForConfiguration()
if (device.torchMode == AVCaptureTorchMode.On) {
device.torchMode = AVCaptureTorchMode.Off
} else {
do {
try device.setTorchModeOnWithLevel(1.0)
} catch {
print(error)
}
}
device.unlockForConfiguration()
} catch {
print(error)
}
}
}
I used nested do-catch blocks to implement Awesomeness's suggestion from the comments. This way, even if try device.setTorchModeOnWithLevel(1.0)
fails, the device is properly unlocked for configuration.
Update #3: For Swift 4:
(I edited the code a bit to my personal taste)
func toggleFlash() {
guard let device = AVCaptureDevice.default(for: AVMediaType.video) else { return }
guard device.hasTorch else { return }
do {
try device.lockForConfiguration()
if (device.torchMode == AVCaptureDevice.TorchMode.on) {
device.torchMode = AVCaptureDevice.TorchMode.off
} else {
do {
try device.setTorchModeOn(level: 1.0)
} catch {
print(error)
}
}
device.unlockForConfiguration()
} catch {
print(error)
}
}
Original answer:
To toggle the flash from on to off (not just "on" as in mad pig's answer), you can use the following method:
func toggleFlash() {
let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
if (device.hasTorch) {
device.lockForConfiguration(nil)
let torchOn = !device.torchActive
device.setTorchModeOnWithLevel(1.0, error: nil)
device.torchMode = torchOn ? AVCaptureTorchMode.On : AVCaptureTorchMode.Off
device.unlockForConfiguration()
}
}
Turn on torch/flash on iPhone
the lockforConfiguration
is set in your code, where you declare your AVCaptureDevice
is a property.
[videoCaptureDevice lockForConfiguration:nil];
Related Topics
How Make Polygon Without Intersection in Swift
Could Not Find an Overload for '-' That Accepts The Supplied Arguments
Msmessagelivelayout Freeze/Crash in Transcript When Info.Plist Contains Privacy Request
How to Make an Ellipse/Circular UIimage with Transparent Background
Must Call a Designated Initializer of The Superclass 'Day' Error
When Creating Thread Safe Reads in Swift, Why Is a Variable Create Outside The Concurrent Queue
Unexpectedly Found Nil While Unwrapping an Optional Value with Avaudioplayer
Make Statement More Clear: Checking Object for Key in Dictionary
How to Populate Table Rows, Using a [String] Array Sent from iPhone by Watch Connectivity
Uibutton State Changing While Scrolling The Tableview with Multiple Sections - Swift
Replicate Opengl Blending in Metal
Return Object for a Method Inside Completion Block
Spacing Between Sections in a Form
Filter by Day from Nsdate in Realm, Swift
Swift - Rotate Gesture and Rotation Increments of 90 Degrees
Swiftui Sheet Shows Sheet with Wrong Data
How to Update User Interface on Core Data
How to Get and Save The Mixed of Multiple Audios in to Single Audio in Swift