【问题标题】:Turn on torch/flash on iPhone在 iPhone 上打开手电筒/闪光灯
【发布时间】:2011-03-12 12:39:41
【问题描述】:

我知道在 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)。

谢谢

【问题讨论】:

标签: ios iphone avcapturesession avcapturedevice


【解决方案1】:

下面是一个较短的版本,您现在可以使用它来打开或关闭灯:

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

更新:(2015 年 3 月)

使用 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];
    }
}

您可能还想监视来自 setTorchModeOnWithLevel: 的返回值 (success)。如果您尝试将级别设置得太高并且割炬过热,则可能会失败。在这种情况下,将级别设置为AVCaptureMaxAvailableTorchLevel 会将级别设置为给定手电筒温度所允许的最高级别。

【讨论】:

  • 这无疑让我在尝试切换闪光灯时变得更简单、更灵敏。我使用了 iWasRobbed 发布的方法,但响应速度不是很好。
【解决方案2】:

iWasRobbed 的回答很好,除了一直在后台运行的 AVCaptureSession。根据 Instrument 的说法,在我的 iPhone 4s 上它需要大约 12% 的 CPU 功率,因此我的应用在一分钟内消耗了大约 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];
        }
    }
}

【讨论】:

  • 它应该适用于所有版本,即它应该从 5.0 开始工作,并且它不应该在低于该版本时崩溃。
  • 谢谢,它确实适用于 5.0 和 5.1,我担心 4.3
【解决方案3】:

在下面查看更好的答案: 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];
}

【讨论】:

  • 在 appdelegate.m 文件中,您应该将 init 方法的内容包含在如下内容中:if ((self = [super init])) { ... } return self;
  • 这太麻烦了,保持会话会消耗电池。从 Tibidabo 尝试以下方法
【解决方案4】:

lockforConfiguration 在您的代码中设置,您在其中声明您的 AVCaptureDevice 是一个属性。

[videoCaptureDevice lockForConfiguration:nil];

【讨论】:

    【解决方案5】:

    从 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];
        }
    }
    

    附:仅当您没有开/关功能时,才建议使用此方法。请记住还有一个选项Auto。即AVCaptureFlashModeAutoAVCaptureTorchModeAuto。为了也支持自动模式,您需要跟踪当前模式并根据闪光灯和手电筒的更改模式。

    【讨论】:

      【解决方案6】:

      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
              }
          }
      }
      

      【讨论】:

        【解决方案7】:
        //import fremework in .h file 
        
        #import <AVFoundation/AVFoundation.h>
        {
         AVCaptureSession *torchSession;
        }
        
        @property(nonatomic,retain)AVCaptureSession *torchSession;
        
        
        -(IBAction)onoff:(id)sender;
        
        //implement in .m file
        
        @synthesize torchSession;
        
        -(IBAction)onoff:(id)sender
        {
            AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
            if ([device hasTorch] && [device hasFlash])
            {
                if (device.torchMode == AVCaptureTorchModeOff) 
                {
                    [button setTitle:@"OFF" forState:UIControlStateNormal];
        
                    AVCaptureDeviceInput *flashInput = [AVCaptureDeviceInput deviceInputWithDevice:device error: nil];
        
                    AVCaptureVideoDataOutput *output = [[AVCaptureVideoDataOutput alloc] init];
                    AVCaptureSession *session = [[AVCaptureSession alloc] init];
        
                    [session beginConfiguration];
                    [device lockForConfiguration:nil];
                    [device setTorchMode:AVCaptureTorchModeOn];
                    [device setFlashMode:AVCaptureFlashModeOn];
                    [session addInput:flashInput];
                    [session addOutput:output];
                    [device unlockForConfiguration];
                    [output release];
                    [session commitConfiguration];
                    [session startRunning];
                    [self setTorchSession:session];
                    [session release];
                }
                else 
                {
                    [button setTitle:@"ON" forState:UIControlStateNormal];
                    [torchSession stopRunning];
                }
            }
        }
        
        - (void)dealloc
        {
            [torchSession release];
            [super dealloc];
        }
        

        【讨论】:

          【解决方案8】:

          这项工作非常好..希望对某人有所帮助!

          -(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];
                  }
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多