Включите фонарик/вспышку на iPhone

Я знаю, что единственный способ включить вспышку и оставить ее включенной на iPhone 4 — это включить видеокамеру. Я не слишком уверен в коде, хотя. Вот что я пытаюсь:

-(IBAction)turnTorchOn {
    AVCaptureSession *captureSession = [[AVCaptureSession alloc] init];
    AVCaptureDevice *videoCaptureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    NSError *error = nil;
    AVCaptureDeviceInput *videoInput = [AVCaptureDeviceInput deviceInputWithDevice:videoCaptureDevice error:&error];

    if (videoInput) {
        [captureSession addInput:videoInput];

        AVCaptureVideoDataOutput* videoOutput = [[AVCaptureVideoDataOutput alloc] init];
        [videoOutput setSampleBufferDelegate:self queue:dispatch_get_current_queue()];

        [captureSession addOutput:videoOutput];

        [captureSession startRunning];

        videoCaptureDevice.torchMode = AVCaptureTorchModeOn;
    }   
}

Кто-нибудь знает, будет ли это работать или я что-то упустил? (У меня еще нет iPhone 4 для тестирования — я просто пробую некоторые из новых API).

Спасибо


person John    schedule 06.07.2010    source источник
comment
Я написал плагин Torch, который работает для Cordova 2.2.0. Вы можете найти его здесь: github.com/tomschreck/iOS-Torch-Plugin   -  person Tom Schreck    schedule 24.01.2013


Ответы (7)


lockforConfiguration устанавливается в вашем коде, где вы объявляете, что AVCaptureDevice является свойством.

[videoCaptureDevice lockForConfiguration:nil];
person Gustavo Barrientos    schedule 09.07.2010

Вот более короткая версия, которую вы теперь можете использовать для включения или выключения света:

AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if ([device hasTorch]) {
    [device lockForConfiguration:nil];
    [device setTorchMode:AVCaptureTorchModeOn];  // use AVCaptureTorchModeOff to turn off
    [device unlockForConfiguration];
}

ОБНОВЛЕНИЕ: (март 2015 г.)

В iOS 6.0 и более поздних версиях вы можете управлять яркостью или уровнем фонарика, используя следующий метод:

- (void)setTorchToLevel:(float)torchLevel
{
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    if ([device hasTorch]) {
        [device lockForConfiguration:nil];
        if (torchLevel <= 0.0) {
            [device setTorchMode:AVCaptureTorchModeOff];
        }
        else {
            if (torchLevel >= 1.0)
                torchLevel = AVCaptureMaxAvailableTorchLevel;
            BOOL success = [device setTorchModeOnWithLevel:torchLevel   error:nil];
        }
        [device unlockForConfiguration];
    }
}

Вы также можете отслеживать возвращаемое значение (success) из setTorchModeOnWithLevel:. Вы можете получить отказ, если попытаетесь установить слишком высокий уровень, а резак перегреется. В этом случае установка уровня AVCaptureMaxAvailableTorchLevel установит самый высокий уровень, допустимый для данной температуры резака.

person mahboudz    schedule 01.11.2011
comment
Это определенно упростило мои попытки переключить вспышку и сделало их более отзывчивыми. Я использовал метод, опубликованный iWasRobbed, но он не очень быстро реагировал. - person Clay Horste; 02.01.2012

Ответ iWasRobbed отличный, за исключением того, что в фоновом режиме все время работает AVCaptureSession. На моем iPhone 4s он требует около 12 % мощности процессора по данным Instrument, поэтому мое приложение расходует около 1 % заряда батареи за минуту. Другими словами, если устройство подготовлено для AV-захвата, оно недешевое.

Использование кода ниже моего приложения требует 0,187% в минуту, поэтому срок службы батареи увеличивается более чем в 5 раз.

Этот код отлично работает на любом устройстве (проверено как на 3GS (без прошивки), так и на 4s). Проверено на 4.3 в симуляторе.

#import <AVFoundation/AVFoundation.h>

- (void) turnTorchOn:(BOOL)on {

    Class captureDeviceClass = NSClassFromString(@"AVCaptureDevice");
    if (captureDeviceClass != nil) {
        AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        if ([device hasTorch] && [device hasFlash]){

            [device lockForConfiguration:nil];
            if (on) {
                [device setTorchMode:AVCaptureTorchModeOn];
                [device setFlashMode:AVCaptureFlashModeOn];
                torchIsOn = YES;
            } else {
                [device setTorchMode:AVCaptureTorchModeOff];
                [device setFlashMode:AVCaptureFlashModeOff];
                torchIsOn = NO;            
            }
            [device unlockForConfiguration];
        }
    }
}
person Tibidabo    schedule 07.04.2012
comment
он должен работать на всех, то есть он должен работать с 5.0 и не должен падать ниже этого. - person Tibidabo; 08.04.2012
comment
спасибо, точно работает на 5.0 и 5.1, переживаю за 4.3 - person Mona; 10.04.2012

Смотрите лучший ответ ниже: https://stackoverflow.com/a/10054088/308315


Старый ответ:

Во-первых, в вашем файле AppDelegate .h:

#import <AVFoundation/AVFoundation.h>

@interface AppDelegate : NSObject <UIApplicationDelegate> {

    AVCaptureSession *torchSession;

}

@property (nonatomic, retain) AVCaptureSession * torchSession;

@end

Затем в вашем файле AppDelegate .m:

@implementation AppDelegate

@synthesize torchSession;

- (void)dealloc {
    [torchSession release];

    [super dealloc];
}

- (id) init {
    if ((self = [super init])) {

    // initialize flashlight
    // test if this class even exists to ensure flashlight is turned on ONLY for iOS 4 and above
        Class captureDeviceClass = NSClassFromString(@"AVCaptureDevice");
        if (captureDeviceClass != nil) {

            AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

            if ([device hasTorch] && [device hasFlash]){

                if (device.torchMode == AVCaptureTorchModeOff) {

                NSLog(@"Setting up flashlight for later use...");

                    AVCaptureDeviceInput *flashInput = [AVCaptureDeviceInput deviceInputWithDevice:device error: nil];
                    AVCaptureVideoDataOutput *output = [[AVCaptureVideoDataOutput alloc] init];

                    AVCaptureSession *session = [[AVCaptureSession alloc] init];

                [session beginConfiguration];
                    [device lockForConfiguration:nil];

                    [session addInput:flashInput];
                    [session addOutput:output];

                    [device unlockForConfiguration];

                    [output release];

                [session commitConfiguration];
                [session startRunning];

                [self setTorchSession:session];
                [session release];
                    }

            }

        }
    } 
    return self;
}

Затем в любое время, когда вы хотите включить его, просто сделайте что-то вроде этого:

// test if this class even exists to ensure flashlight is turned on ONLY for iOS 4 and above
Class captureDeviceClass = NSClassFromString(@"AVCaptureDevice");
if (captureDeviceClass != nil) {

    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    [device lockForConfiguration:nil];

    [device setTorchMode:AVCaptureTorchModeOn];
    [device setFlashMode:AVCaptureFlashModeOn];

    [device unlockForConfiguration];

}

И аналогично для его отключения:

// test if this class even exists to ensure flashlight is turned on ONLY for iOS 4 and above
Class captureDeviceClass = NSClassFromString(@"AVCaptureDevice");
if (captureDeviceClass != nil) {

    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    [device lockForConfiguration:nil];

    [device setTorchMode:AVCaptureTorchModeOff];
    [device setFlashMode:AVCaptureFlashModeOff];

    [device unlockForConfiguration];
}
person iwasrobbed    schedule 29.07.2010
comment
В файле appdelegate.m вы должны заключить содержимое метода init в нечто вроде: if ((self = [super init])) { ... } return self; - person Senseful; 28.04.2011
comment
Это слишком неуместно, и поддержание сеанса расходует заряд батареи. Попробуйте метод ниже от Tibidabo - person doozMen; 27.02.2013

Начиная с iOS 6.0 и выше, включение/выключение фонарика,

- (void) toggleFlash {
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    if ([device hasTorch] && [device hasFlash]){
        [device lockForConfiguration:nil];
        [device setFlashMode:(device.flashActive) ? AVCaptureFlashModeOff : AVCaptureFlashModeOn];
        [device setTorchMode:(device.torchActive) ? AVCaptureTorchModeOff : AVCaptureTorchModeOn];
        [device unlockForConfiguration];
    }
}

P.S. Этот подход рекомендуется только в том случае, если у вас нет функции включения / выключения. Помните, что есть еще один вариант Auto. то есть AVCaptureFlashModeAuto и AVCaptureTorchModeAuto. Чтобы поддерживать автоматический режим, вы также отслеживаете текущий режим и на основе этого изменяете режим вспышки и фонарика.

person Hemang    schedule 25.11.2014

Версия Swift 2.0:

func setTorchLevel(torchLevel: Float)
{
    self.captureSession?.beginConfiguration()
    defer {
        self.captureSession?.commitConfiguration()
    }

    if let device = backCamera?.device where device.hasTorch && device.torchAvailable {
        do {
            try device.lockForConfiguration()
            defer {
                device.unlockForConfiguration()
            }

            if torchLevel <= 0.0 {
                device.torchMode = .Off
            }
            else if torchLevel >= 1.0 {
                try device.setTorchModeOnWithLevel(min(torchLevel, AVCaptureMaxAvailableTorchLevel))
            }
        }
        catch let error {
            print("Failed to set up torch level with error \(error)")
            return
        }
    }
}
person Avt    schedule 30.08.2015

Эта работа очень хорошо .. надеюсь, что это кому-то поможет!

-(IBAction)flashlight:(id)sender {

    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    if ([device hasTorch] && [device hasFlash]){

        if (device.torchMode == AVCaptureTorchModeOff) {

            [sender setTitle:@"Torch Off" forState:UIControlStateNormal];

            AVCaptureDeviceInput *flashInput = [AVCaptureDeviceInput deviceInputWithDevice:device error: nil];
            AVCaptureVideoDataOutput *output = [[AVCaptureVideoDataOutput alloc] init];

            AVCaptureSession *cam = [[AVCaptureSession alloc] init];

            [cam beginConfiguration];
            [device lockForConfiguration:nil];

            [device setTorchMode:AVCaptureTorchModeOn];
            [device setFlashMode:AVCaptureFlashModeOn];

            [cam addInput:flashInput];
            [cam addOutput:output];

            [device unlockForConfiguration];

            [cam commitConfiguration];
            [cam startRunning];

            [self setTorchSession:cam];
        }
        else {
            [sender setTitle:@"Torch On" forState:UIControlStateNormal];
            [_torchSession stopRunning];
        }
    }
}
person Jonas    schedule 21.08.2015