From 6cc96e56033ff45fb26436d6891e022b9ce99bee Mon Sep 17 00:00:00 2001 From: Abilio Henrique Date: Fri, 7 Aug 2015 11:01:30 +1000 Subject: [PATCH 1/6] - Add image and video quality options for iOS --- src/ios/CDVCapture.m | 18 ++++++++++++++++-- www/CaptureImageOptions.js | 2 ++ www/CaptureVideoOptions.js | 2 +- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/ios/CDVCapture.m b/src/ios/CDVCapture.m index c49f76cf..1f2bed8f 100644 --- a/src/ios/CDVCapture.m +++ b/src/ios/CDVCapture.m @@ -127,11 +127,11 @@ - (void)captureImage:(CDVInvokedUrlCommand*)command if ([options isKindOfClass:[NSNull class]]) { options = [NSDictionary dictionary]; } - + // options could contain limit and mode neither of which are supported at this time // taking more than one picture (limit) is only supported if provide own controls via cameraOverlayView property // can support mode in OS - + if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { NSLog(@"Capture.imageCapture: camera not available."); CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:CAPTURE_NOT_SUPPORTED]; @@ -178,6 +178,7 @@ - (CDVPluginResult*)processImage:(UIImage*)image type:(NSString*)mimeType forCal if (mimeType && [mimeType isEqualToString:@"image/png"]) { data = UIImagePNGRepresentation(image); } else { + NSLog(@"ImageQuality: %@", [quality]); data = UIImageJPEGRepresentation(image, 0.5); } @@ -222,6 +223,7 @@ - (void)captureVideo:(CDVInvokedUrlCommand*)command // options could contain limit, duration and mode // taking more than one video (limit) is only supported if provide own controls via cameraOverlayView property NSNumber* duration = [options objectForKey:@"duration"]; + NSNumber* quality = [options objectForKey:@"quality"]; NSString* mediaType = nil; if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { @@ -250,6 +252,18 @@ - (void)captureVideo:(CDVInvokedUrlCommand*)command pickerController.delegate = self; pickerController.sourceType = UIImagePickerControllerSourceTypeCamera; pickerController.allowsEditing = NO; + + // Set quality of captured video + if (quality) { + if ([quality intValue] == 1) { + pickerController.videoQuality = UIImagePickerControllerQualityTypeLow; + } else if ([quality intValue] == 1) { + pickerController.videoQuality = UIImagePickerControllerQualityTypeHigh; + } else { + pickerController.videoQuality = UIImagePickerControllerQualityTypeMedium; + } + } + // iOS 3.0 pickerController.mediaTypes = [NSArray arrayWithObjects:mediaType, nil]; diff --git a/www/CaptureImageOptions.js b/www/CaptureImageOptions.js index 1fb5615e..7beaeab1 100644 --- a/www/CaptureImageOptions.js +++ b/www/CaptureImageOptions.js @@ -25,6 +25,8 @@ var CaptureImageOptions = function(){ // Upper limit of images user can take. Value must be equal or greater than 1. this.limit = 1; + // Image quality (0-100) + this.quality = 50; }; module.exports = CaptureImageOptions; diff --git a/www/CaptureVideoOptions.js b/www/CaptureVideoOptions.js index 261dbae8..8640f236 100644 --- a/www/CaptureVideoOptions.js +++ b/www/CaptureVideoOptions.js @@ -27,7 +27,7 @@ var CaptureVideoOptions = function(){ this.limit = 1; // Maximum duration of a single video clip in seconds. this.duration = 0; - // Video quality parameter, 0 means low quality, suitable for MMS messages, and value 1 means high quality. + // Video quality parameter, 0 means low quality, suitable for MMS messages, and value 1 means high quality. Defaults to medium quality in iOS, if set to null. this.quality = 1; }; From 35973373b0ea0d20c10d02a3639873ce236d4d9e Mon Sep 17 00:00:00 2001 From: Abilio Henrique Date: Fri, 7 Aug 2015 12:23:35 +1000 Subject: [PATCH 2/6] - Add option to set setting for save to photo album --- src/ios/CDVCapture.m | 270 +++++++++++++++++++------------------ www/CaptureImageOptions.js | 2 + 2 files changed, 142 insertions(+), 130 deletions(-) diff --git a/src/ios/CDVCapture.m b/src/ios/CDVCapture.m index 1f2bed8f..fafde309 100644 --- a/src/ios/CDVCapture.m +++ b/src/ios/CDVCapture.m @@ -6,9 +6,9 @@ Licensed to the Apache Software Foundation (ASF) under one to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - + http://www.apache.org/licenses/LICENSE-2.0 - + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -28,6 +28,9 @@ Licensed to the Apache Software Foundation (ASF) under one #define kW3CMediaFormatDuration @"duration" #define kW3CMediaModeType @"type" +NSNumber *globalQuality; +NSNumber *globalSaveToPhotoAlbum; + @implementation NSBundle (PluginExtensions) + (NSBundle*) pluginBundle:(CDVPlugin*)plugin { @@ -47,22 +50,22 @@ @implementation CDVImagePicker - (uint64_t)accessibilityTraits { NSString* systemVersion = [[UIDevice currentDevice] systemVersion]; - + if (([systemVersion compare:@"4.0" options:NSNumericSearch] != NSOrderedAscending)) { // this means system version is not less than 4.0 return UIAccessibilityTraitStartsMediaSession; } - + return UIAccessibilityTraitNone; } - (BOOL)prefersStatusBarHidden { return YES; } - + - (UIViewController*)childViewControllerForStatusBarHidden { return nil; } - + - (void)viewWillAppear:(BOOL)animated { SEL sel = NSSelectorFromString(@"setNeedsStatusBarAppearanceUpdate"); if ([self respondsToSelector:sel]) { @@ -86,18 +89,18 @@ - (void)captureAudio:(CDVInvokedUrlCommand*)command { NSString* callbackId = command.callbackId; NSDictionary* options = [command argumentAtIndex:0]; - + if ([options isKindOfClass:[NSNull class]]) { options = [NSDictionary dictionary]; } - + NSNumber* duration = [options objectForKey:@"duration"]; // the default value of duration is 0 so use nil (no duration) if default value if (duration) { duration = [duration doubleValue] == 0 ? nil : duration; } CDVPluginResult* result = nil; - + if (NSClassFromString(@"AVAudioRecorder") == nil) { result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:CAPTURE_NOT_SUPPORTED]; } else if (self.inUse == YES) { @@ -105,15 +108,15 @@ - (void)captureAudio:(CDVInvokedUrlCommand*)command } else { // all the work occurs here CDVAudioRecorderViewController* audioViewController = [[CDVAudioRecorderViewController alloc] initWithCommand:self duration:duration callbackId:callbackId]; - + // Now create a nav controller and display the view... CDVAudioNavigationController* navController = [[CDVAudioNavigationController alloc] initWithRootViewController:audioViewController]; - + self.inUse = YES; - + [self.viewController presentViewController:navController animated:YES completion:nil]; } - + if (result) { [self.commandDelegate sendPluginResult:result callbackId:callbackId]; } @@ -123,7 +126,7 @@ - (void)captureImage:(CDVInvokedUrlCommand*)command { NSString* callbackId = command.callbackId; NSDictionary* options = [command argumentAtIndex:0]; - + if ([options isKindOfClass:[NSNull class]]) { options = [NSDictionary dictionary]; } @@ -132,6 +135,12 @@ - (void)captureImage:(CDVInvokedUrlCommand*)command // taking more than one picture (limit) is only supported if provide own controls via cameraOverlayView property // can support mode in OS + NSNumber* quality = [options objectForKey:@"quality"]; + globalQuality = quality; + + NSNumber* saveToPhotoAlbum = [options objectForKey:@"saveToPhotoAlbum"]; + globalSaveToPhotoAlbum = saveToPhotoAlbum; + if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { NSLog(@"Capture.imageCapture: camera not available."); CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:CAPTURE_NOT_SUPPORTED]; @@ -140,7 +149,7 @@ - (void)captureImage:(CDVInvokedUrlCommand*)command if (pickerController == nil) { pickerController = [[CDVImagePicker alloc] init]; } - + pickerController.delegate = self; pickerController.sourceType = UIImagePickerControllerSourceTypeCamera; pickerController.allowsEditing = NO; @@ -148,16 +157,16 @@ - (void)captureImage:(CDVInvokedUrlCommand*)command // iOS 3.0 pickerController.mediaTypes = [NSArray arrayWithObjects:(NSString*)kUTTypeImage, nil]; } - + /*if ([pickerController respondsToSelector:@selector(cameraCaptureMode)]){ - // iOS 4.0 - pickerController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto; - pickerController.cameraDevice = UIImagePickerControllerCameraDeviceRear; - pickerController.cameraFlashMode = UIImagePickerControllerCameraFlashModeAuto; - }*/ + // iOS 4.0 + pickerController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto; + pickerController.cameraDevice = UIImagePickerControllerCameraDeviceRear; + pickerController.cameraFlashMode = UIImagePickerControllerCameraFlashModeAuto; + }*/ // CDVImagePicker specific property pickerController.callbackId = callbackId; - + [self.viewController presentViewController:pickerController animated:YES completion:nil]; } } @@ -170,30 +179,31 @@ - (void)captureImage:(CDVInvokedUrlCommand*)command - (CDVPluginResult*)processImage:(UIImage*)image type:(NSString*)mimeType forCallbackId:(NSString*)callbackId { CDVPluginResult* result = nil; - + // save the image to photo album - UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil); - + if (!globalSaveToPhotoAlbum || (int)globalSaveToPhotoAlbum == 1) { + UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil); + } + NSData* data = nil; if (mimeType && [mimeType isEqualToString:@"image/png"]) { data = UIImagePNGRepresentation(image); } else { - NSLog(@"ImageQuality: %@", [quality]); - data = UIImageJPEGRepresentation(image, 0.5); + data = UIImageJPEGRepresentation(image, ((int)globalQuality / 100)); } - + // write to temp directory and return URI NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath]; // use file system temporary directory NSError* err = nil; NSFileManager* fileMgr = [[NSFileManager alloc] init]; - + // generate unique file name NSString* filePath; int i = 1; do { filePath = [NSString stringWithFormat:@"%@/photo_%03d.jpg", docsPath, i++]; } while ([fileMgr fileExistsAtPath:filePath]); - + if (![data writeToFile:filePath options:NSAtomicWrite error:&err]) { result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageToErrorObject:CAPTURE_INTERNAL_ERR]; if (err) { @@ -201,13 +211,13 @@ - (CDVPluginResult*)processImage:(UIImage*)image type:(NSString*)mimeType forCal } } else { // create MediaFile object - + NSDictionary* fileDict = [self getMediaDictionaryFromPath:filePath ofType:mimeType]; NSArray* fileArray = [NSArray arrayWithObject:fileDict]; - + result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:fileArray]; } - + return result; } @@ -215,26 +225,26 @@ - (void)captureVideo:(CDVInvokedUrlCommand*)command { NSString* callbackId = command.callbackId; NSDictionary* options = [command argumentAtIndex:0]; - + if ([options isKindOfClass:[NSNull class]]) { options = [NSDictionary dictionary]; } - + // options could contain limit, duration and mode // taking more than one video (limit) is only supported if provide own controls via cameraOverlayView property NSNumber* duration = [options objectForKey:@"duration"]; NSNumber* quality = [options objectForKey:@"quality"]; NSString* mediaType = nil; - + if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { // there is a camera, it is available, make sure it can do movies pickerController = [[CDVImagePicker alloc] init]; - + NSArray* types = nil; if ([UIImagePickerController respondsToSelector:@selector(availableMediaTypesForSourceType:)]) { types = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera]; // NSLog(@"MediaTypes: %@", [types description]); - + if ([types containsObject:(NSString*)kUTTypeMovie]) { mediaType = (NSString*)kUTTypeMovie; } else if ([types containsObject:(NSString*)kUTTypeVideo]) { @@ -263,17 +273,17 @@ - (void)captureVideo:(CDVInvokedUrlCommand*)command pickerController.videoQuality = UIImagePickerControllerQualityTypeMedium; } } - + // iOS 3.0 pickerController.mediaTypes = [NSArray arrayWithObjects:mediaType, nil]; - + if ([mediaType isEqualToString:(NSString*)kUTTypeMovie]){ if (duration) { pickerController.videoMaximumDuration = [duration doubleValue]; } //NSLog(@"pickerController.videoMaximumDuration = %f", pickerController.videoMaximumDuration); } - + // iOS 4.0 if ([pickerController respondsToSelector:@selector(cameraCaptureMode)]) { pickerController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModeVideo; @@ -283,7 +293,7 @@ - (void)captureVideo:(CDVInvokedUrlCommand*)command } // CDVImagePicker specific property pickerController.callbackId = callbackId; - + [self.viewController presentViewController:pickerController animated:YES completion:nil]; } } @@ -291,18 +301,18 @@ - (void)captureVideo:(CDVInvokedUrlCommand*)command - (CDVPluginResult*)processVideo:(NSString*)moviePath forCallbackId:(NSString*)callbackId { // save the movie to photo album (only avail as of iOS 3.1) - + /* don't need, it should automatically get saved NSLog(@"can save %@: %d ?", moviePath, UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(moviePath)); - if (&UIVideoAtPathIsCompatibleWithSavedPhotosAlbum != NULL && UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(moviePath) == YES) { - NSLog(@"try to save movie"); - UISaveVideoAtPathToSavedPhotosAlbum(moviePath, nil, nil, nil); - NSLog(@"finished saving movie"); - }*/ + if (&UIVideoAtPathIsCompatibleWithSavedPhotosAlbum != NULL && UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(moviePath) == YES) { + NSLog(@"try to save movie"); + UISaveVideoAtPathToSavedPhotosAlbum(moviePath, nil, nil, nil); + NSLog(@"finished saving movie"); + }*/ // create MediaFile object NSDictionary* fileDict = [self getMediaDictionaryFromPath:moviePath ofType:nil]; NSArray* fileArray = [NSArray arrayWithObject:fileDict]; - + return [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:fileArray]; } @@ -313,48 +323,48 @@ - (void)getMediaModes:(CDVInvokedUrlCommand*)command NSArray* imageArray = nil; NSArray* movieArray = nil; NSArray* audioArray = nil; - + if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { // there is a camera, find the modes // can get image/jpeg or image/png from camera - + /* can't find a way to get the default height and width and other info * for images/movies taken with UIImagePickerController */ NSDictionary* jpg = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithInt:0], kW3CMediaFormatHeight, - [NSNumber numberWithInt:0], kW3CMediaFormatWidth, - @"image/jpeg", kW3CMediaModeType, - nil]; + [NSNumber numberWithInt:0], kW3CMediaFormatHeight, + [NSNumber numberWithInt:0], kW3CMediaFormatWidth, + @"image/jpeg", kW3CMediaModeType, + nil]; NSDictionary* png = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithInt:0], kW3CMediaFormatHeight, - [NSNumber numberWithInt:0], kW3CMediaFormatWidth, - @"image/png", kW3CMediaModeType, - nil]; + [NSNumber numberWithInt:0], kW3CMediaFormatHeight, + [NSNumber numberWithInt:0], kW3CMediaFormatWidth, + @"image/png", kW3CMediaModeType, + nil]; imageArray = [NSArray arrayWithObjects:jpg, png, nil]; - + if ([UIImagePickerController respondsToSelector:@selector(availableMediaTypesForSourceType:)]) { NSArray* types = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera]; - + if ([types containsObject:(NSString*)kUTTypeMovie]) { NSDictionary* mov = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithInt:0], kW3CMediaFormatHeight, - [NSNumber numberWithInt:0], kW3CMediaFormatWidth, - @"video/quicktime", kW3CMediaModeType, - nil]; + [NSNumber numberWithInt:0], kW3CMediaFormatHeight, + [NSNumber numberWithInt:0], kW3CMediaFormatWidth, + @"video/quicktime", kW3CMediaModeType, + nil]; movieArray = [NSArray arrayWithObject:mov]; } } } NSDictionary* modes = [NSDictionary dictionaryWithObjectsAndKeys: - imageArray ? (NSObject*) imageArray:[NSNull null], @"image", - movieArray ? (NSObject*) movieArray:[NSNull null], @"video", - audioArray ? (NSObject*) audioArray:[NSNull null], @"audio", - nil]; + imageArray ? (NSObject*) imageArray:[NSNull null], @"image", + movieArray ? (NSObject*) movieArray:[NSNull null], @"video", + audioArray ? (NSObject*) audioArray:[NSNull null], @"audio", + nil]; NSData* jsonData = [NSJSONSerialization dataWithJSONObject:modes options:0 error:nil]; NSString* jsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; - + NSString* jsString = [NSString stringWithFormat:@"navigator.device.capture.setSupportedModes(%@);", jsonStr]; [self.commandDelegate evalJs:jsString]; } @@ -366,14 +376,14 @@ - (void)getFormatData:(CDVInvokedUrlCommand*)command NSString* fullPath = [command argumentAtIndex:0]; // mimeType could be null NSString* mimeType = nil; - + if ([command.arguments count] > 1) { mimeType = [command argumentAtIndex:1]; } BOOL bError = NO; CDVCaptureError errorCode = CAPTURE_INTERNAL_ERR; CDVPluginResult* result = nil; - + if (!mimeType || [mimeType isKindOfClass:[NSNull class]]) { // try to determine mime type if not provided id command = [self.commandDelegate getCommandInstance:@"File"]; @@ -396,7 +406,7 @@ - (void)getFormatData:(CDVInvokedUrlCommand*)command [formatData setObject:[NSNumber numberWithInt:0] forKey:kW3CMediaFormatHeight]; [formatData setObject:[NSNumber numberWithInt:0] forKey:kW3CMediaFormatWidth]; [formatData setObject:[NSNumber numberWithInt:0] forKey:kW3CMediaFormatDuration]; - + if ([mimeType rangeOfString:@"image/"].location != NSNotFound) { UIImage* image = [UIImage imageWithContentsOfFile:fullPath]; if (image) { @@ -409,12 +419,12 @@ - (void)getFormatData:(CDVInvokedUrlCommand*)command AVURLAsset* movieAsset = [[AVURLAsset alloc] initWithURL:movieURL options:nil]; CMTime duration = [movieAsset duration]; [formatData setObject:[NSNumber numberWithFloat:CMTimeGetSeconds(duration)] forKey:kW3CMediaFormatDuration]; - + NSArray* allVideoTracks = [movieAsset tracksWithMediaType:AVMediaTypeVideo]; if ([allVideoTracks count] > 0) { AVAssetTrack* track = [[movieAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; CGSize size = [track naturalSize]; - + [formatData setObject:[NSNumber numberWithFloat:size.height] forKey:kW3CMediaFormatHeight]; [formatData setObject:[NSNumber numberWithFloat:size.width] forKey:kW3CMediaFormatWidth]; // not sure how to get codecs or bitrate??? @@ -427,7 +437,7 @@ - (void)getFormatData:(CDVInvokedUrlCommand*)command if (NSClassFromString(@"AVAudioPlayer") != nil) { NSURL* fileURL = [NSURL fileURLWithPath:fullPath]; NSError* err = nil; - + AVAudioPlayer* avPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:&err]; if (!err) { // get the data @@ -457,16 +467,16 @@ - (NSDictionary*)getMediaDictionaryFromPath:(NSString*)fullPath ofType:(NSString { NSFileManager* fileMgr = [[NSFileManager alloc] init]; NSMutableDictionary* fileDict = [NSMutableDictionary dictionaryWithCapacity:5]; - + CDVFile *fs = [self.commandDelegate getCommandInstance:@"File"]; - + // Get canonical version of localPath NSURL *fileURL = [NSURL URLWithString:[NSString stringWithFormat:@"file://%@", fullPath]]; NSURL *resolvedFileURL = [fileURL URLByResolvingSymlinksInPath]; NSString *path = [resolvedFileURL path]; - + CDVFilesystemURL *url = [fs fileSystemURLforLocalPath:path]; - + [fileDict setObject:[fullPath lastPathComponent] forKey:@"name"]; [fileDict setObject:fullPath forKey:@"fullPath"]; if (url) { @@ -486,7 +496,7 @@ - (NSDictionary*)getMediaDictionaryFromPath:(NSString*)fullPath ofType:(NSString NSDate* modDate = [fileAttrs fileModificationDate]; NSNumber* msDate = [NSNumber numberWithDouble:[modDate timeIntervalSince1970] * 1000]; [fileDict setObject:msDate forKey:@"lastModifiedDate"]; - + return fileDict; } @@ -509,11 +519,11 @@ - (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingM { CDVImagePicker* cameraPicker = (CDVImagePicker*)picker; NSString* callbackId = cameraPicker.callbackId; - + [[picker presentingViewController] dismissViewControllerAnimated:YES completion:nil]; - + CDVPluginResult* result = nil; - + UIImage* image = nil; NSString* mediaType = [info objectForKey:UIImagePickerControllerMediaType]; if (!mediaType || [mediaType isEqualToString:(NSString*)kUTTypeImage]) { @@ -546,9 +556,9 @@ - (void)imagePickerControllerDidCancel:(UIImagePickerController*)picker { CDVImagePicker* cameraPicker = (CDVImagePicker*)picker; NSString* callbackId = cameraPicker.callbackId; - + [[picker presentingViewController] dismissViewControllerAnimated:YES completion:nil]; - + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:CAPTURE_NO_MEDIA_FILES]; [self.commandDelegate sendPluginResult:result callbackId:callbackId]; pickerController = nil; @@ -559,11 +569,11 @@ - (void)imagePickerControllerDidCancel:(UIImagePickerController*)picker @implementation CDVAudioNavigationController #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000 - - (NSUInteger)supportedInterfaceOrientations - { - // delegate to CVDAudioRecorderViewController - return [self.topViewController supportedInterfaceOrientations]; - } +- (NSUInteger)supportedInterfaceOrientations +{ + // delegate to CVDAudioRecorderViewController + return [self.topViewController supportedInterfaceOrientations]; +} #endif @end @@ -580,7 +590,7 @@ - (NSString*)resolveImageResource:(NSString*)resource { NSString* systemVersion = [[UIDevice currentDevice] systemVersion]; BOOL isLessThaniOS4 = ([systemVersion compare:@"4.0" options:NSNumericSearch] == NSOrderedAscending); - + // the iPad image (nor retina) differentiation code was not in 3.x, and we have to explicitly set the path // if user wants iPhone only app to run on iPad they must remove *~ipad.* images from CDVCapture.bundle if (isLessThaniOS4) { @@ -591,7 +601,7 @@ - (NSString*)resolveImageResource:(NSString*)resource return [NSString stringWithFormat:@"%@.png", resource]; } } - + return resource; } @@ -604,38 +614,38 @@ - (id)initWithCommand:(CDVCapture*)theCommand duration:(NSNumber*)theDuration ca self.errorCode = CAPTURE_NO_MEDIA_FILES; self.isTimed = self.duration != nil; _previousStatusBarStyle = [UIApplication sharedApplication].statusBarStyle; - + return self; } - + return nil; } - (void)loadView { - if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) { + if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) { self.edgesForExtendedLayout = UIRectEdgeNone; } // create view and display CGRect viewRect = [[UIScreen mainScreen] applicationFrame]; UIView* tmp = [[UIView alloc] initWithFrame:viewRect]; - + // make backgrounds NSString* microphoneResource = @"CDVCapture.bundle/microphone"; - + BOOL isIphone5 = ([[UIScreen mainScreen] bounds].size.width == 568 && [[UIScreen mainScreen] bounds].size.height == 320) || ([[UIScreen mainScreen] bounds].size.height == 568 && [[UIScreen mainScreen] bounds].size.width == 320); if (isIphone5) { microphoneResource = @"CDVCapture.bundle/microphone-568h"; } - + UIImage* microphone = [UIImage imageNamed:[self resolveImageResource:microphoneResource]]; UIView* microphoneView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, viewRect.size.width, microphone.size.height)]; [microphoneView setBackgroundColor:[UIColor colorWithPatternImage:microphone]]; [microphoneView setUserInteractionEnabled:NO]; [microphoneView setIsAccessibilityElement:NO]; [tmp addSubview:microphoneView]; - + // add bottom bar view UIImage* grayBkg = [UIImage imageNamed:[self resolveImageResource:@"CDVCapture.bundle/controls_bg"]]; UIView* controls = [[UIView alloc] initWithFrame:CGRectMake(0, microphone.size.height, viewRect.size.width, grayBkg.size.height)]; @@ -643,7 +653,7 @@ - (void)loadView [controls setUserInteractionEnabled:NO]; [controls setIsAccessibilityElement:NO]; [tmp addSubview:controls]; - + // make red recording background view UIImage* recordingBkg = [UIImage imageNamed:[self resolveImageResource:@"CDVCapture.bundle/recording_bg"]]; UIColor* background = [UIColor colorWithPatternImage:recordingBkg]; @@ -653,7 +663,7 @@ - (void)loadView [self.recordingView setUserInteractionEnabled:NO]; [self.recordingView setIsAccessibilityElement:NO]; [tmp addSubview:self.recordingView]; - + // add label self.timerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, viewRect.size.width, recordingBkg.size.height)]; // timerLabel.autoresizingMask = reSizeMask; @@ -670,9 +680,9 @@ - (void)loadView self.timerLabel.accessibilityTraits |= UIAccessibilityTraitUpdatesFrequently; self.timerLabel.accessibilityTraits &= ~UIAccessibilityTraitStaticText; [tmp addSubview:self.timerLabel]; - + // Add record button - + self.recordImage = [UIImage imageNamed:[self resolveImageResource:@"CDVCapture.bundle/record_button"]]; self.stopRecordImage = [UIImage imageNamed:[self resolveImageResource:@"CDVCapture.bundle/stop_button"]]; self.recordButton.accessibilityTraits |= [self accessibilityTraits]; @@ -681,12 +691,12 @@ - (void)loadView [self.recordButton setImage:recordImage forState:UIControlStateNormal]; [self.recordButton addTarget:self action:@selector(processButton:) forControlEvents:UIControlEventTouchUpInside]; [tmp addSubview:recordButton]; - + // make and add done button to navigation bar self.doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(dismissAudioView:)]; [self.doneButton setStyle:UIBarButtonItemStyleDone]; self.navigationItem.rightBarButtonItem = self.doneButton; - + [self setView:tmp]; } @@ -695,7 +705,7 @@ - (void)viewDidLoad [super viewDidLoad]; UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil); NSError* error = nil; - + if (self.avSession == nil) { // create audio session self.avSession = [AVAudioSession sharedInstance]; @@ -706,22 +716,22 @@ - (void)viewDidLoad [self dismissAudioView:nil]; } } - + // create file to record to in temporary dir - + NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath]; // use file system temporary directory NSError* err = nil; NSFileManager* fileMgr = [[NSFileManager alloc] init]; - + // generate unique file name NSString* filePath; int i = 1; do { filePath = [NSString stringWithFormat:@"%@/audio_%03d.wav", docsPath, i++]; } while ([fileMgr fileExistsAtPath:filePath]); - + NSURL* fileURL = [NSURL fileURLWithPath:filePath isDirectory:NO]; - + // create AVAudioPlayer self.avRecorder = [[AVAudioRecorder alloc] initWithURL:fileURL settings:nil error:&err]; if (err) { @@ -739,14 +749,14 @@ - (void)viewDidLoad } #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000 - - (NSUInteger)supportedInterfaceOrientations - { - NSUInteger orientation = UIInterfaceOrientationMaskPortrait; // must support portrait - NSUInteger supported = [captureCommand.viewController supportedInterfaceOrientations]; - - orientation = orientation | (supported & UIInterfaceOrientationMaskPortraitUpsideDown); - return orientation; - } +- (NSUInteger)supportedInterfaceOrientations +{ + NSUInteger orientation = UIInterfaceOrientationMaskPortrait; // must support portrait + NSUInteger supported = [captureCommand.viewController supportedInterfaceOrientations]; + + orientation = orientation | (supported & UIInterfaceOrientationMaskPortraitUpsideDown); + return orientation; +} #endif - (void)viewDidUnload @@ -833,8 +843,8 @@ - (void)stopRecordingCleanup BOOL isUIAccessibilityAnnouncementNotification = (&UIAccessibilityAnnouncementNotification != NULL); if (isUIAccessibilityAnnouncementNotification) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 500ull * NSEC_PER_MSEC), dispatch_get_main_queue(), ^{ - UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, PluginLocalizedString(captureCommand, @"timed recording complete", nil)); - }); + UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, PluginLocalizedString(captureCommand, @"timed recording complete", nil)); + }); } } else { // issue a layout notification change so that VO will reannounce the button label when recording completes @@ -846,12 +856,12 @@ - (void)dismissAudioView:(id)sender { // called when done button pressed or when error condition to do cleanup and remove view [[self.captureCommand.viewController.presentedViewController presentingViewController] dismissViewControllerAnimated:YES completion:nil]; - + if (!self.pluginResult) { // return error self.pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:(int)self.errorCode]; } - + self.avRecorder = nil; [self.avSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil]; [self.avSession setActive:NO error:nil]; @@ -859,7 +869,7 @@ - (void)dismissAudioView:(id)sender UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil); // return result [self.captureCommand.commandDelegate sendPluginResult:pluginResult callbackId:callbackId]; - + if (IsAtLeastiOSVersion(@"7.0")) { [[UIApplication sharedApplication] setStatusBarStyle:_previousStatusBarStyle]; } @@ -876,7 +886,7 @@ - (NSString*)formatTime:(int)interval // is this format universal? int secs = interval % 60; int min = interval / 60; - + if (interval < 60) { return [NSString stringWithFormat:@"0:%02d", interval]; } else { @@ -889,14 +899,14 @@ - (void)audioRecorderDidFinishRecording:(AVAudioRecorder*)recorder successfully: // may be called when timed audio finishes - need to stop time and reset buttons [self.timer invalidate]; [self stopRecordingCleanup]; - + // generate success result if (flag) { NSString* filePath = [avRecorder.url path]; // NSLog(@"filePath: %@", filePath); NSDictionary* fileDict = [captureCommand getMediaDictionaryFromPath:filePath ofType:@"audio/wav"]; NSArray* fileArray = [NSArray arrayWithObject:fileDict]; - + self.pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:fileArray]; } else { self.pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageToErrorObject:CAPTURE_INTERNAL_ERR]; @@ -907,7 +917,7 @@ - (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder*)recorder error:(NSErr { [self.timer invalidate]; [self stopRecordingCleanup]; - + NSLog(@"error recording audio"); self.pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageToErrorObject:CAPTURE_INTERNAL_ERR]; [self dismissAudioView:nil]; @@ -923,7 +933,7 @@ - (void)viewWillAppear:(BOOL)animated if (IsAtLeastiOSVersion(@"7.0")) { [[UIApplication sharedApplication] setStatusBarStyle:[self preferredStatusBarStyle]]; } - + [super viewWillAppear:animated]; } diff --git a/www/CaptureImageOptions.js b/www/CaptureImageOptions.js index 7beaeab1..e1e71d84 100644 --- a/www/CaptureImageOptions.js +++ b/www/CaptureImageOptions.js @@ -27,6 +27,8 @@ var CaptureImageOptions = function(){ this.limit = 1; // Image quality (0-100) this.quality = 50; + // Save photos to album/camera roll + this.saveToPhotoAlbum = true; }; module.exports = CaptureImageOptions; From ff3508db58566c5e08ee3a5ff24c747dcf154c3d Mon Sep 17 00:00:00 2001 From: Abilio Henrique Date: Fri, 7 Aug 2015 13:57:59 +1000 Subject: [PATCH 3/6] - fix if statement --- src/ios/CDVCapture.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ios/CDVCapture.m b/src/ios/CDVCapture.m index fafde309..89f33dca 100644 --- a/src/ios/CDVCapture.m +++ b/src/ios/CDVCapture.m @@ -181,7 +181,8 @@ - (CDVPluginResult*)processImage:(UIImage*)image type:(NSString*)mimeType forCal CDVPluginResult* result = nil; // save the image to photo album - if (!globalSaveToPhotoAlbum || (int)globalSaveToPhotoAlbum == 1) { + + if([globalSaveToPhotoAlbum isEqual:@1]) { UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil); } From b7d38b1e6b4b776088f6a994bf00a039e5498660 Mon Sep 17 00:00:00 2001 From: Andrew Garside Date: Fri, 4 Sep 2015 15:54:01 +1000 Subject: [PATCH 4/6] Added the ability to scale images before saving --- src/ios/CDVCapture.h | 2 +- src/ios/CDVCapture.m | 58 ++++++++++++++++++++++++++++++++++++++ www/CaptureImageOptions.js | 6 +++- 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/ios/CDVCapture.h b/src/ios/CDVCapture.h index 2cd8db8b..e5eb514c 100644 --- a/src/ios/CDVCapture.h +++ b/src/ios/CDVCapture.h @@ -61,7 +61,7 @@ typedef NSUInteger CDVCaptureError; - (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info; - (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingImage:(UIImage*)image editingInfo:(NSDictionary*)editingInfo; - (void)imagePickerControllerDidCancel:(UIImagePickerController*)picker; - +- (UIImage*)imageByScalingNotCroppingForSize:(UIImage*)sourceImage targetSize:(CGSize)targetSize; @end @interface CDVAudioNavigationController : UINavigationController diff --git a/src/ios/CDVCapture.m b/src/ios/CDVCapture.m index 89f33dca..33ddd978 100644 --- a/src/ios/CDVCapture.m +++ b/src/ios/CDVCapture.m @@ -30,6 +30,8 @@ Licensed to the Apache Software Foundation (ASF) under one NSNumber *globalQuality; NSNumber *globalSaveToPhotoAlbum; +NSNumber *globalWidth; +NSNumber *globalHeight; @implementation NSBundle (PluginExtensions) @@ -141,6 +143,9 @@ - (void)captureImage:(CDVInvokedUrlCommand*)command NSNumber* saveToPhotoAlbum = [options objectForKey:@"saveToPhotoAlbum"]; globalSaveToPhotoAlbum = saveToPhotoAlbum; + globalWidth = [options objectForKey:@"width"]; + globalHeight = [options objectForKey:@"height"]; + if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { NSLog(@"Capture.imageCapture: camera not available."); CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:CAPTURE_NOT_SUPPORTED]; @@ -186,6 +191,17 @@ - (CDVPluginResult*)processImage:(UIImage*)image type:(NSString*)mimeType forCal UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil); } + NSLog(@"Width: %f", [globalWidth floatValue]); + NSLog(@"Height: %f", [globalHeight floatValue]); + + if(![globalWidth isEqual:@0] && ![globalHeight isEqual:@0]) { + struct CGSize newScale; + newScale.width = [globalWidth floatValue]; + newScale.height = [globalHeight floatValue]; + + image = [self imageByScalingNotCroppingForSize:image targetSize:newScale]; + } + NSData* data = nil; if (mimeType && [mimeType isEqualToString:@"image/png"]) { data = UIImagePNGRepresentation(image); @@ -222,6 +238,48 @@ - (CDVPluginResult*)processImage:(UIImage*)image type:(NSString*)mimeType forCal return result; } +- (UIImage*)imageByScalingNotCroppingForSize:(UIImage*)sourceImage targetSize:(CGSize)targetSize +{ + UIImage* newImage = nil; + CGSize imageSize = sourceImage.size; + CGFloat width = imageSize.width; + CGFloat height = imageSize.height; + CGFloat targetWidth = targetSize.width; + CGFloat targetHeight = targetSize.height; + CGFloat scaleFactor = 0.0; + CGSize scaledSize = targetSize; + + if (CGSizeEqualToSize(imageSize, targetSize) == NO) { + CGFloat widthFactor = targetWidth / width; + CGFloat heightFactor = targetHeight / height; + + // opposite comparison to imageByScalingAndCroppingForSize in order to contain the image within the given bounds + if (widthFactor > heightFactor) { + scaleFactor = heightFactor; // scale to fit height + } else { + scaleFactor = widthFactor; // scale to fit width + } + scaledSize = CGSizeMake(MIN(width * scaleFactor, targetWidth), MIN(height * scaleFactor, targetHeight)); + } + + // If the pixels are floats, it causes a white line in iOS8 and probably other versions too + scaledSize.width = (int)scaledSize.width; + scaledSize.height = (int)scaledSize.height; + + UIGraphicsBeginImageContext(scaledSize); // this will resize + + [sourceImage drawInRect:CGRectMake(0, 0, scaledSize.width, scaledSize.height)]; + + newImage = UIGraphicsGetImageFromCurrentImageContext(); + if (newImage == nil) { + NSLog(@"could not scale image"); + } + + // pop the context to get back to the default + UIGraphicsEndImageContext(); + return newImage; +} + - (void)captureVideo:(CDVInvokedUrlCommand*)command { NSString* callbackId = command.callbackId; diff --git a/www/CaptureImageOptions.js b/www/CaptureImageOptions.js index e1e71d84..637a213c 100644 --- a/www/CaptureImageOptions.js +++ b/www/CaptureImageOptions.js @@ -17,7 +17,7 @@ * specific language governing permissions and limitations * under the License. * -*/ + */ /** * Encapsulates all image capture operation configuration options. @@ -29,6 +29,10 @@ var CaptureImageOptions = function(){ this.quality = 50; // Save photos to album/camera roll this.saveToPhotoAlbum = true; + // Width of the saved image, this must be used with height to take effect + this.width = 0; + // Height of the saved image, this must be used with width to take effect + this.height = 0; }; module.exports = CaptureImageOptions; From 4a752ac6af0deb8775f4a000d96eb40d4fbf8062 Mon Sep 17 00:00:00 2001 From: Andrew Garside Date: Fri, 4 Sep 2015 16:05:55 +1000 Subject: [PATCH 5/6] Changed width and height parameters to targetWidth and targetHeight to be consistent with Cordova's official camera plugin. --- src/ios/CDVCapture.m | 11 ++++------- www/CaptureImageOptions.js | 4 ++-- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/ios/CDVCapture.m b/src/ios/CDVCapture.m index 33ddd978..f96298ed 100644 --- a/src/ios/CDVCapture.m +++ b/src/ios/CDVCapture.m @@ -143,9 +143,9 @@ - (void)captureImage:(CDVInvokedUrlCommand*)command NSNumber* saveToPhotoAlbum = [options objectForKey:@"saveToPhotoAlbum"]; globalSaveToPhotoAlbum = saveToPhotoAlbum; - globalWidth = [options objectForKey:@"width"]; - globalHeight = [options objectForKey:@"height"]; - + globalWidth = [options objectForKey:@"targetWidth"]; + globalHeight = [options objectForKey:@"targetHeight"]; + if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { NSLog(@"Capture.imageCapture: camera not available."); CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:CAPTURE_NOT_SUPPORTED]; @@ -191,10 +191,7 @@ - (CDVPluginResult*)processImage:(UIImage*)image type:(NSString*)mimeType forCal UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil); } - NSLog(@"Width: %f", [globalWidth floatValue]); - NSLog(@"Height: %f", [globalHeight floatValue]); - - if(![globalWidth isEqual:@0] && ![globalHeight isEqual:@0]) { + if(!([globalWidth isEqual:@0] || [globalHeight isEqual:@0])) { struct CGSize newScale; newScale.width = [globalWidth floatValue]; newScale.height = [globalHeight floatValue]; diff --git a/www/CaptureImageOptions.js b/www/CaptureImageOptions.js index 637a213c..faae0274 100644 --- a/www/CaptureImageOptions.js +++ b/www/CaptureImageOptions.js @@ -30,9 +30,9 @@ var CaptureImageOptions = function(){ // Save photos to album/camera roll this.saveToPhotoAlbum = true; // Width of the saved image, this must be used with height to take effect - this.width = 0; + this.targetWidth = 0; // Height of the saved image, this must be used with width to take effect - this.height = 0; + this.targetHeight = 0; }; module.exports = CaptureImageOptions; From aeecac3ab5b8c6d27d352f19b34838e58208698a Mon Sep 17 00:00:00 2001 From: Abilio Henrique Date: Thu, 17 Sep 2015 12:00:24 +1000 Subject: [PATCH 6/6] - Merged changes from master --- src/ios/CDVCapture.m | 254 +++++++++++++++++++++++-------------------- 1 file changed, 135 insertions(+), 119 deletions(-) diff --git a/src/ios/CDVCapture.m b/src/ios/CDVCapture.m index f96298ed..6dff47fb 100644 --- a/src/ios/CDVCapture.m +++ b/src/ios/CDVCapture.m @@ -6,9 +6,9 @@ Licensed to the Apache Software Foundation (ASF) under one to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - + http://www.apache.org/licenses/LICENSE-2.0 - + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -52,22 +52,22 @@ @implementation CDVImagePicker - (uint64_t)accessibilityTraits { NSString* systemVersion = [[UIDevice currentDevice] systemVersion]; - + if (([systemVersion compare:@"4.0" options:NSNumericSearch] != NSOrderedAscending)) { // this means system version is not less than 4.0 return UIAccessibilityTraitStartsMediaSession; } - + return UIAccessibilityTraitNone; } - (BOOL)prefersStatusBarHidden { return YES; } - + - (UIViewController*)childViewControllerForStatusBarHidden { return nil; } - + - (void)viewWillAppear:(BOOL)animated { SEL sel = NSSelectorFromString(@"setNeedsStatusBarAppearanceUpdate"); if ([self respondsToSelector:sel]) { @@ -91,18 +91,18 @@ - (void)captureAudio:(CDVInvokedUrlCommand*)command { NSString* callbackId = command.callbackId; NSDictionary* options = [command argumentAtIndex:0]; - + if ([options isKindOfClass:[NSNull class]]) { options = [NSDictionary dictionary]; } - + NSNumber* duration = [options objectForKey:@"duration"]; // the default value of duration is 0 so use nil (no duration) if default value if (duration) { duration = [duration doubleValue] == 0 ? nil : duration; } CDVPluginResult* result = nil; - + if (NSClassFromString(@"AVAudioRecorder") == nil) { result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:CAPTURE_NOT_SUPPORTED]; } else if (self.inUse == YES) { @@ -110,15 +110,15 @@ - (void)captureAudio:(CDVInvokedUrlCommand*)command } else { // all the work occurs here CDVAudioRecorderViewController* audioViewController = [[CDVAudioRecorderViewController alloc] initWithCommand:self duration:duration callbackId:callbackId]; - + // Now create a nav controller and display the view... CDVAudioNavigationController* navController = [[CDVAudioNavigationController alloc] initWithRootViewController:audioViewController]; - + self.inUse = YES; - + [self.viewController presentViewController:navController animated:YES completion:nil]; } - + if (result) { [self.commandDelegate sendPluginResult:result callbackId:callbackId]; } @@ -128,11 +128,11 @@ - (void)captureImage:(CDVInvokedUrlCommand*)command { NSString* callbackId = command.callbackId; NSDictionary* options = [command argumentAtIndex:0]; - + if ([options isKindOfClass:[NSNull class]]) { options = [NSDictionary dictionary]; } - + // options could contain limit and mode neither of which are supported at this time // taking more than one picture (limit) is only supported if provide own controls via cameraOverlayView property // can support mode in OS @@ -154,7 +154,7 @@ - (void)captureImage:(CDVInvokedUrlCommand*)command if (pickerController == nil) { pickerController = [[CDVImagePicker alloc] init]; } - + pickerController.delegate = self; pickerController.sourceType = UIImagePickerControllerSourceTypeCamera; pickerController.allowsEditing = NO; @@ -162,16 +162,16 @@ - (void)captureImage:(CDVInvokedUrlCommand*)command // iOS 3.0 pickerController.mediaTypes = [NSArray arrayWithObjects:(NSString*)kUTTypeImage, nil]; } - + /*if ([pickerController respondsToSelector:@selector(cameraCaptureMode)]){ - // iOS 4.0 - pickerController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto; - pickerController.cameraDevice = UIImagePickerControllerCameraDeviceRear; - pickerController.cameraFlashMode = UIImagePickerControllerCameraFlashModeAuto; - }*/ + // iOS 4.0 + pickerController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto; + pickerController.cameraDevice = UIImagePickerControllerCameraDeviceRear; + pickerController.cameraFlashMode = UIImagePickerControllerCameraFlashModeAuto; + }*/ // CDVImagePicker specific property pickerController.callbackId = callbackId; - + [self.viewController presentViewController:pickerController animated:YES completion:nil]; } } @@ -184,7 +184,7 @@ - (void)captureImage:(CDVInvokedUrlCommand*)command - (CDVPluginResult*)processImage:(UIImage*)image type:(NSString*)mimeType forCallbackId:(NSString*)callbackId { CDVPluginResult* result = nil; - + // save the image to photo album if([globalSaveToPhotoAlbum isEqual:@1]) { @@ -205,19 +205,19 @@ - (CDVPluginResult*)processImage:(UIImage*)image type:(NSString*)mimeType forCal } else { data = UIImageJPEGRepresentation(image, ((int)globalQuality / 100)); } - + // write to temp directory and return URI NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath]; // use file system temporary directory NSError* err = nil; NSFileManager* fileMgr = [[NSFileManager alloc] init]; - + // generate unique file name NSString* filePath; int i = 1; do { filePath = [NSString stringWithFormat:@"%@/photo_%03d.jpg", docsPath, i++]; } while ([fileMgr fileExistsAtPath:filePath]); - + if (![data writeToFile:filePath options:NSAtomicWrite error:&err]) { result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageToErrorObject:CAPTURE_INTERNAL_ERR]; if (err) { @@ -225,13 +225,13 @@ - (CDVPluginResult*)processImage:(UIImage*)image type:(NSString*)mimeType forCal } } else { // create MediaFile object - + NSDictionary* fileDict = [self getMediaDictionaryFromPath:filePath ofType:mimeType]; NSArray* fileArray = [NSArray arrayWithObject:fileDict]; - + result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:fileArray]; } - + return result; } @@ -281,26 +281,26 @@ - (void)captureVideo:(CDVInvokedUrlCommand*)command { NSString* callbackId = command.callbackId; NSDictionary* options = [command argumentAtIndex:0]; - + if ([options isKindOfClass:[NSNull class]]) { options = [NSDictionary dictionary]; } - + // options could contain limit, duration and mode // taking more than one video (limit) is only supported if provide own controls via cameraOverlayView property NSNumber* duration = [options objectForKey:@"duration"]; NSNumber* quality = [options objectForKey:@"quality"]; NSString* mediaType = nil; - + if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { // there is a camera, it is available, make sure it can do movies pickerController = [[CDVImagePicker alloc] init]; - + NSArray* types = nil; if ([UIImagePickerController respondsToSelector:@selector(availableMediaTypesForSourceType:)]) { types = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera]; // NSLog(@"MediaTypes: %@", [types description]); - + if ([types containsObject:(NSString*)kUTTypeMovie]) { mediaType = (NSString*)kUTTypeMovie; } else if ([types containsObject:(NSString*)kUTTypeVideo]) { @@ -332,14 +332,14 @@ - (void)captureVideo:(CDVInvokedUrlCommand*)command // iOS 3.0 pickerController.mediaTypes = [NSArray arrayWithObjects:mediaType, nil]; - + if ([mediaType isEqualToString:(NSString*)kUTTypeMovie]){ if (duration) { pickerController.videoMaximumDuration = [duration doubleValue]; } //NSLog(@"pickerController.videoMaximumDuration = %f", pickerController.videoMaximumDuration); } - + // iOS 4.0 if ([pickerController respondsToSelector:@selector(cameraCaptureMode)]) { pickerController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModeVideo; @@ -349,7 +349,7 @@ - (void)captureVideo:(CDVInvokedUrlCommand*)command } // CDVImagePicker specific property pickerController.callbackId = callbackId; - + [self.viewController presentViewController:pickerController animated:YES completion:nil]; } } @@ -357,18 +357,18 @@ - (void)captureVideo:(CDVInvokedUrlCommand*)command - (CDVPluginResult*)processVideo:(NSString*)moviePath forCallbackId:(NSString*)callbackId { // save the movie to photo album (only avail as of iOS 3.1) - + /* don't need, it should automatically get saved NSLog(@"can save %@: %d ?", moviePath, UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(moviePath)); - if (&UIVideoAtPathIsCompatibleWithSavedPhotosAlbum != NULL && UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(moviePath) == YES) { - NSLog(@"try to save movie"); - UISaveVideoAtPathToSavedPhotosAlbum(moviePath, nil, nil, nil); - NSLog(@"finished saving movie"); - }*/ + if (&UIVideoAtPathIsCompatibleWithSavedPhotosAlbum != NULL && UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(moviePath) == YES) { + NSLog(@"try to save movie"); + UISaveVideoAtPathToSavedPhotosAlbum(moviePath, nil, nil, nil); + NSLog(@"finished saving movie"); + }*/ // create MediaFile object NSDictionary* fileDict = [self getMediaDictionaryFromPath:moviePath ofType:nil]; NSArray* fileArray = [NSArray arrayWithObject:fileDict]; - + return [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:fileArray]; } @@ -379,48 +379,48 @@ - (void)getMediaModes:(CDVInvokedUrlCommand*)command NSArray* imageArray = nil; NSArray* movieArray = nil; NSArray* audioArray = nil; - + if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { // there is a camera, find the modes // can get image/jpeg or image/png from camera - + /* can't find a way to get the default height and width and other info * for images/movies taken with UIImagePickerController */ NSDictionary* jpg = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithInt:0], kW3CMediaFormatHeight, - [NSNumber numberWithInt:0], kW3CMediaFormatWidth, - @"image/jpeg", kW3CMediaModeType, - nil]; + [NSNumber numberWithInt:0], kW3CMediaFormatHeight, + [NSNumber numberWithInt:0], kW3CMediaFormatWidth, + @"image/jpeg", kW3CMediaModeType, + nil]; NSDictionary* png = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithInt:0], kW3CMediaFormatHeight, - [NSNumber numberWithInt:0], kW3CMediaFormatWidth, - @"image/png", kW3CMediaModeType, - nil]; + [NSNumber numberWithInt:0], kW3CMediaFormatHeight, + [NSNumber numberWithInt:0], kW3CMediaFormatWidth, + @"image/png", kW3CMediaModeType, + nil]; imageArray = [NSArray arrayWithObjects:jpg, png, nil]; - + if ([UIImagePickerController respondsToSelector:@selector(availableMediaTypesForSourceType:)]) { NSArray* types = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera]; - + if ([types containsObject:(NSString*)kUTTypeMovie]) { NSDictionary* mov = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithInt:0], kW3CMediaFormatHeight, - [NSNumber numberWithInt:0], kW3CMediaFormatWidth, - @"video/quicktime", kW3CMediaModeType, - nil]; + [NSNumber numberWithInt:0], kW3CMediaFormatHeight, + [NSNumber numberWithInt:0], kW3CMediaFormatWidth, + @"video/quicktime", kW3CMediaModeType, + nil]; movieArray = [NSArray arrayWithObject:mov]; } } } NSDictionary* modes = [NSDictionary dictionaryWithObjectsAndKeys: - imageArray ? (NSObject*) imageArray:[NSNull null], @"image", - movieArray ? (NSObject*) movieArray:[NSNull null], @"video", - audioArray ? (NSObject*) audioArray:[NSNull null], @"audio", - nil]; + imageArray ? (NSObject*) imageArray:[NSNull null], @"image", + movieArray ? (NSObject*) movieArray:[NSNull null], @"video", + audioArray ? (NSObject*) audioArray:[NSNull null], @"audio", + nil]; NSData* jsonData = [NSJSONSerialization dataWithJSONObject:modes options:0 error:nil]; NSString* jsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; - + NSString* jsString = [NSString stringWithFormat:@"navigator.device.capture.setSupportedModes(%@);", jsonStr]; [self.commandDelegate evalJs:jsString]; } @@ -432,14 +432,14 @@ - (void)getFormatData:(CDVInvokedUrlCommand*)command NSString* fullPath = [command argumentAtIndex:0]; // mimeType could be null NSString* mimeType = nil; - + if ([command.arguments count] > 1) { mimeType = [command argumentAtIndex:1]; } BOOL bError = NO; CDVCaptureError errorCode = CAPTURE_INTERNAL_ERR; CDVPluginResult* result = nil; - + if (!mimeType || [mimeType isKindOfClass:[NSNull class]]) { // try to determine mime type if not provided id command = [self.commandDelegate getCommandInstance:@"File"]; @@ -462,7 +462,7 @@ - (void)getFormatData:(CDVInvokedUrlCommand*)command [formatData setObject:[NSNumber numberWithInt:0] forKey:kW3CMediaFormatHeight]; [formatData setObject:[NSNumber numberWithInt:0] forKey:kW3CMediaFormatWidth]; [formatData setObject:[NSNumber numberWithInt:0] forKey:kW3CMediaFormatDuration]; - + if ([mimeType rangeOfString:@"image/"].location != NSNotFound) { UIImage* image = [UIImage imageWithContentsOfFile:fullPath]; if (image) { @@ -475,12 +475,12 @@ - (void)getFormatData:(CDVInvokedUrlCommand*)command AVURLAsset* movieAsset = [[AVURLAsset alloc] initWithURL:movieURL options:nil]; CMTime duration = [movieAsset duration]; [formatData setObject:[NSNumber numberWithFloat:CMTimeGetSeconds(duration)] forKey:kW3CMediaFormatDuration]; - + NSArray* allVideoTracks = [movieAsset tracksWithMediaType:AVMediaTypeVideo]; if ([allVideoTracks count] > 0) { AVAssetTrack* track = [[movieAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; CGSize size = [track naturalSize]; - + [formatData setObject:[NSNumber numberWithFloat:size.height] forKey:kW3CMediaFormatHeight]; [formatData setObject:[NSNumber numberWithFloat:size.width] forKey:kW3CMediaFormatWidth]; // not sure how to get codecs or bitrate??? @@ -493,7 +493,7 @@ - (void)getFormatData:(CDVInvokedUrlCommand*)command if (NSClassFromString(@"AVAudioPlayer") != nil) { NSURL* fileURL = [NSURL fileURLWithPath:fullPath]; NSError* err = nil; - + AVAudioPlayer* avPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:&err]; if (!err) { // get the data @@ -523,16 +523,16 @@ - (NSDictionary*)getMediaDictionaryFromPath:(NSString*)fullPath ofType:(NSString { NSFileManager* fileMgr = [[NSFileManager alloc] init]; NSMutableDictionary* fileDict = [NSMutableDictionary dictionaryWithCapacity:5]; - + CDVFile *fs = [self.commandDelegate getCommandInstance:@"File"]; - + // Get canonical version of localPath NSURL *fileURL = [NSURL URLWithString:[NSString stringWithFormat:@"file://%@", fullPath]]; NSURL *resolvedFileURL = [fileURL URLByResolvingSymlinksInPath]; NSString *path = [resolvedFileURL path]; - + CDVFilesystemURL *url = [fs fileSystemURLforLocalPath:path]; - + [fileDict setObject:[fullPath lastPathComponent] forKey:@"name"]; [fileDict setObject:fullPath forKey:@"fullPath"]; if (url) { @@ -552,7 +552,7 @@ - (NSDictionary*)getMediaDictionaryFromPath:(NSString*)fullPath ofType:(NSString NSDate* modDate = [fileAttrs fileModificationDate]; NSNumber* msDate = [NSNumber numberWithDouble:[modDate timeIntervalSince1970] * 1000]; [fileDict setObject:msDate forKey:@"lastModifiedDate"]; - + return fileDict; } @@ -575,11 +575,11 @@ - (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingM { CDVImagePicker* cameraPicker = (CDVImagePicker*)picker; NSString* callbackId = cameraPicker.callbackId; - + [[picker presentingViewController] dismissViewControllerAnimated:YES completion:nil]; - + CDVPluginResult* result = nil; - + UIImage* image = nil; NSString* mediaType = [info objectForKey:UIImagePickerControllerMediaType]; if (!mediaType || [mediaType isEqualToString:(NSString*)kUTTypeImage]) { @@ -596,7 +596,7 @@ - (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingM result = [self processImage:image type:cameraPicker.mimeType forCallbackId:callbackId]; } else if ([mediaType isEqualToString:(NSString*)kUTTypeMovie]) { // process video - NSString* moviePath = [[info objectForKey:UIImagePickerControllerMediaURL] path]; + NSString* moviePath = [(NSURL *)[info objectForKey:UIImagePickerControllerMediaURL] path]; if (moviePath) { result = [self processVideo:moviePath forCallbackId:callbackId]; } @@ -612,9 +612,9 @@ - (void)imagePickerControllerDidCancel:(UIImagePickerController*)picker { CDVImagePicker* cameraPicker = (CDVImagePicker*)picker; NSString* callbackId = cameraPicker.callbackId; - + [[picker presentingViewController] dismissViewControllerAnimated:YES completion:nil]; - + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:CAPTURE_NO_MEDIA_FILES]; [self.commandDelegate sendPluginResult:result callbackId:callbackId]; pickerController = nil; @@ -624,7 +624,13 @@ - (void)imagePickerControllerDidCancel:(UIImagePickerController*)picker @implementation CDVAudioNavigationController -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000 +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000 +- (UIInterfaceOrientationMask)supportedInterfaceOrientations +{ + // delegate to CVDAudioRecorderViewController + return [self.topViewController supportedInterfaceOrientations]; +} +#else - (NSUInteger)supportedInterfaceOrientations { // delegate to CVDAudioRecorderViewController @@ -646,7 +652,7 @@ - (NSString*)resolveImageResource:(NSString*)resource { NSString* systemVersion = [[UIDevice currentDevice] systemVersion]; BOOL isLessThaniOS4 = ([systemVersion compare:@"4.0" options:NSNumericSearch] == NSOrderedAscending); - + // the iPad image (nor retina) differentiation code was not in 3.x, and we have to explicitly set the path // if user wants iPhone only app to run on iPad they must remove *~ipad.* images from CDVCapture.bundle if (isLessThaniOS4) { @@ -657,7 +663,7 @@ - (NSString*)resolveImageResource:(NSString*)resource return [NSString stringWithFormat:@"%@.png", resource]; } } - + return resource; } @@ -670,38 +676,38 @@ - (id)initWithCommand:(CDVCapture*)theCommand duration:(NSNumber*)theDuration ca self.errorCode = CAPTURE_NO_MEDIA_FILES; self.isTimed = self.duration != nil; _previousStatusBarStyle = [UIApplication sharedApplication].statusBarStyle; - + return self; } - + return nil; } - (void)loadView { - if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) { + if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) { self.edgesForExtendedLayout = UIRectEdgeNone; } // create view and display CGRect viewRect = [[UIScreen mainScreen] applicationFrame]; UIView* tmp = [[UIView alloc] initWithFrame:viewRect]; - + // make backgrounds NSString* microphoneResource = @"CDVCapture.bundle/microphone"; - + BOOL isIphone5 = ([[UIScreen mainScreen] bounds].size.width == 568 && [[UIScreen mainScreen] bounds].size.height == 320) || ([[UIScreen mainScreen] bounds].size.height == 568 && [[UIScreen mainScreen] bounds].size.width == 320); if (isIphone5) { microphoneResource = @"CDVCapture.bundle/microphone-568h"; } - + UIImage* microphone = [UIImage imageNamed:[self resolveImageResource:microphoneResource]]; UIView* microphoneView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, viewRect.size.width, microphone.size.height)]; [microphoneView setBackgroundColor:[UIColor colorWithPatternImage:microphone]]; [microphoneView setUserInteractionEnabled:NO]; [microphoneView setIsAccessibilityElement:NO]; [tmp addSubview:microphoneView]; - + // add bottom bar view UIImage* grayBkg = [UIImage imageNamed:[self resolveImageResource:@"CDVCapture.bundle/controls_bg"]]; UIView* controls = [[UIView alloc] initWithFrame:CGRectMake(0, microphone.size.height, viewRect.size.width, grayBkg.size.height)]; @@ -709,7 +715,7 @@ - (void)loadView [controls setUserInteractionEnabled:NO]; [controls setIsAccessibilityElement:NO]; [tmp addSubview:controls]; - + // make red recording background view UIImage* recordingBkg = [UIImage imageNamed:[self resolveImageResource:@"CDVCapture.bundle/recording_bg"]]; UIColor* background = [UIColor colorWithPatternImage:recordingBkg]; @@ -719,7 +725,7 @@ - (void)loadView [self.recordingView setUserInteractionEnabled:NO]; [self.recordingView setIsAccessibilityElement:NO]; [tmp addSubview:self.recordingView]; - + // add label self.timerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, viewRect.size.width, recordingBkg.size.height)]; // timerLabel.autoresizingMask = reSizeMask; @@ -736,9 +742,9 @@ - (void)loadView self.timerLabel.accessibilityTraits |= UIAccessibilityTraitUpdatesFrequently; self.timerLabel.accessibilityTraits &= ~UIAccessibilityTraitStaticText; [tmp addSubview:self.timerLabel]; - + // Add record button - + self.recordImage = [UIImage imageNamed:[self resolveImageResource:@"CDVCapture.bundle/record_button"]]; self.stopRecordImage = [UIImage imageNamed:[self resolveImageResource:@"CDVCapture.bundle/stop_button"]]; self.recordButton.accessibilityTraits |= [self accessibilityTraits]; @@ -747,12 +753,12 @@ - (void)loadView [self.recordButton setImage:recordImage forState:UIControlStateNormal]; [self.recordButton addTarget:self action:@selector(processButton:) forControlEvents:UIControlEventTouchUpInside]; [tmp addSubview:recordButton]; - + // make and add done button to navigation bar self.doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(dismissAudioView:)]; [self.doneButton setStyle:UIBarButtonItemStyleDone]; self.navigationItem.rightBarButtonItem = self.doneButton; - + [self setView:tmp]; } @@ -761,7 +767,7 @@ - (void)viewDidLoad [super viewDidLoad]; UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil); NSError* error = nil; - + if (self.avSession == nil) { // create audio session self.avSession = [AVAudioSession sharedInstance]; @@ -772,24 +778,25 @@ - (void)viewDidLoad [self dismissAudioView:nil]; } } - + // create file to record to in temporary dir - + NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath]; // use file system temporary directory NSError* err = nil; NSFileManager* fileMgr = [[NSFileManager alloc] init]; - + // generate unique file name NSString* filePath; int i = 1; do { filePath = [NSString stringWithFormat:@"%@/audio_%03d.wav", docsPath, i++]; } while ([fileMgr fileExistsAtPath:filePath]); - + NSURL* fileURL = [NSURL fileURLWithPath:filePath isDirectory:NO]; - + // create AVAudioPlayer - self.avRecorder = [[AVAudioRecorder alloc] initWithURL:fileURL settings:nil error:&err]; + NSDictionary *recordSetting = [[NSMutableDictionary alloc] init]; + self.avRecorder = [[AVAudioRecorder alloc] initWithURL:fileURL settings:recordSetting error:&err]; if (err) { NSLog(@"Failed to initialize AVAudioRecorder: %@\n", [err localizedDescription]); self.avRecorder = nil; @@ -804,7 +811,16 @@ - (void)viewDidLoad } } -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000 +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000 +- (UIInterfaceOrientationMask)supportedInterfaceOrientations +{ + UIInterfaceOrientationMask orientation = UIInterfaceOrientationMaskPortrait; + UIInterfaceOrientationMask supported = [captureCommand.viewController supportedInterfaceOrientations]; + + orientation = orientation | (supported & UIInterfaceOrientationMaskPortraitUpsideDown); + return orientation; +} +#else - (NSUInteger)supportedInterfaceOrientations { NSUInteger orientation = UIInterfaceOrientationMaskPortrait; // must support portrait @@ -896,11 +912,11 @@ - (void)stopRecordingCleanup } if (self.duration && self.isTimed) { // VoiceOver announcement so user knows timed recording has finished - BOOL isUIAccessibilityAnnouncementNotification = (&UIAccessibilityAnnouncementNotification != NULL); - if (isUIAccessibilityAnnouncementNotification) { + //BOOL isUIAccessibilityAnnouncementNotification = (&UIAccessibilityAnnouncementNotification != NULL); + if (UIAccessibilityAnnouncementNotification) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 500ull * NSEC_PER_MSEC), dispatch_get_main_queue(), ^{ - UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, PluginLocalizedString(captureCommand, @"timed recording complete", nil)); - }); + UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, PluginLocalizedString(captureCommand, @"timed recording complete", nil)); + }); } } else { // issue a layout notification change so that VO will reannounce the button label when recording completes @@ -912,12 +928,12 @@ - (void)dismissAudioView:(id)sender { // called when done button pressed or when error condition to do cleanup and remove view [[self.captureCommand.viewController.presentedViewController presentingViewController] dismissViewControllerAnimated:YES completion:nil]; - + if (!self.pluginResult) { // return error self.pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:(int)self.errorCode]; } - + self.avRecorder = nil; [self.avSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil]; [self.avSession setActive:NO error:nil]; @@ -925,7 +941,7 @@ - (void)dismissAudioView:(id)sender UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil); // return result [self.captureCommand.commandDelegate sendPluginResult:pluginResult callbackId:callbackId]; - + if (IsAtLeastiOSVersion(@"7.0")) { [[UIApplication sharedApplication] setStatusBarStyle:_previousStatusBarStyle]; } @@ -942,7 +958,7 @@ - (NSString*)formatTime:(int)interval // is this format universal? int secs = interval % 60; int min = interval / 60; - + if (interval < 60) { return [NSString stringWithFormat:@"0:%02d", interval]; } else { @@ -955,14 +971,14 @@ - (void)audioRecorderDidFinishRecording:(AVAudioRecorder*)recorder successfully: // may be called when timed audio finishes - need to stop time and reset buttons [self.timer invalidate]; [self stopRecordingCleanup]; - + // generate success result if (flag) { NSString* filePath = [avRecorder.url path]; // NSLog(@"filePath: %@", filePath); NSDictionary* fileDict = [captureCommand getMediaDictionaryFromPath:filePath ofType:@"audio/wav"]; NSArray* fileArray = [NSArray arrayWithObject:fileDict]; - + self.pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:fileArray]; } else { self.pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageToErrorObject:CAPTURE_INTERNAL_ERR]; @@ -973,7 +989,7 @@ - (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder*)recorder error:(NSErr { [self.timer invalidate]; [self stopRecordingCleanup]; - + NSLog(@"error recording audio"); self.pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageToErrorObject:CAPTURE_INTERNAL_ERR]; [self dismissAudioView:nil]; @@ -989,7 +1005,7 @@ - (void)viewWillAppear:(BOOL)animated if (IsAtLeastiOSVersion(@"7.0")) { [[UIApplication sharedApplication] setStatusBarStyle:[self preferredStatusBarStyle]]; } - + [super viewWillAppear:animated]; }