I have been working around in UIImagePickerController and am struck with a problem where I need to get the precise moment when the camera shutter opens in UIImagePickerController when the source type is set to camera (UIImagePickerControllerSourceTypeCamera).
I have done some googling around and have realized that no one had such strange requirement!
I looked around the docs of UIImagePickerController and UIImagePickerControllerDelegate hoping to get some delegate method / callback indicating the camera shutter open event, but did not find any.
Any suggestions?
Thanks for any help,
Raj Pawan
Subscribe to:
AVCaptureSessionDidStartRunningNotification
This is when the iris open animation begins. If you add a cameraOverlayView during this time, it will be properly covered up by the iris. It is posted at the same time as that PL… private notification. This is a documented approach that does not risk app rejection.
The solution is to observe for a private notification, just as discussed in this thread:
Detecting when camera's iris is open on iPhone.
My sugestion (didn't try it myself but don't see why it wouldn't work) :
Subclass the UIImagePickerController class into your own class, and override the viewWillAppear and viewDidAppear : those methods will be triggered when the UIImagePickerController is about to appear or does appear (if you trigger its display properly using presentModalController for instance) .
#interface MyUIImagePickerController : UIImagePickerController {
}
#end
#implementation MyUIImagePickerController
-(void)viewWillAppear:(BOOL)animated {
NSLog(#"the picker is about to appear");
[super viewWillAppear:animated];
}
-(void)viewDidAppear:(BOOL)animated {
NSLog(#"the picker did appear");
[super viewDidAppear:animated];
}
#end
Related
I'm programming an application for the hearing-impaired. I'm hoping to take tracks from the iTunes library, and in my app have a slider for panning. I don't want to use OpenAL (this isn't a game - I repeat this is a media player). So since AVAudioPlayer has the easy pan method, can I take selections from the MPMediaPicker and feed them into the AVAudioPlayer so I can pan them?
I dont do a lot of iOS development, but I believe there are two ways.
Method #1
You need to add /System/Library/Frameworks/AVFoundation.framework to your target in Xcode and #import AVAudioPlayer.h as well as You need to add MediaPlayer.framework to your target in Xcode and #import .
For this operation, you need MPMediaPicker to pass the song data to AVAMedia Player. That can be accomplished like this:
#interface MusicPlayerDemoViewController : UIViewController <MPMediaPickerControllerDelegate> {
...
}
...
// This action should open the media picker
- (IBAction)openMediaPicker:(id)sender;
#end
// MusicPlayerDemoViewController.m
- (IBAction)openMediaPicker:(id)sender {
MPMediaPickerController *mediaPicker = [[MPMediaPickerController alloc] initWithMediaTypes:MPMediaTypeMusic];
mediaPicker.delegate = self;
mediaPicker.allowsPickingMultipleItems = NO; // this is the default
[self presentModalViewController:mediaPicker animated:YES];
[mediaPicker release];
}
// Media picker delegate methods
- (void)mediaPicker: (MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection {
// We need to dismiss the picker
[self dismissModalViewControllerAnimated:YES];
(Code Continues Below, the blanks are for you to fill in)
AT THIS POINT, CALL THE AVAAUDIOPLAYER CLASS AND TELL IT TO PLAY mediaItemCollection . REMEMBER TO STOP AUDIO BEFORE PLAYING, AS IT WILL PLAY MULTIPLE SONGS AT ONCE.
}
- (void)mediaPickerDidCancel:(MPMediaPickerController *)mediaPicker {
// User did not select anything
// We need to dismiss the picker
[self dismissModalViewControllerAnimated:YES];
}
NOW, ONCE THIS IS DONE THE USER NEEDS TO SELECT A NEW SONG. YOU COULD EITHER CREATE A WHILE LOOP AROUND THE WHOLE THING, WHERE THE CONDITIONAL IS CURRENT TIME >= DURATION (FROM AVAAUDIO PLAYER),
ALTERNATIVELY, YOU COULD CREATE A BUTTON TO OPEN THE PICKER
For more questions checkout:
http://oleb.net/blog/2009/07/the-music-player-framework-in-the-iphone-sdk/ (I used much of their code)
http://developer.apple.com/library/ios/#DOCUMENTATION/AVFoundation/Reference/AVAudioPlayerClassReference/Reference/Reference.html
Good Luck!
Derek
Try having AVAMediaPlayer play the variable mediaItemCollection. This was assigned by the picker to be the song location by the code above. If this does not work make sure that AVAMediaPlayer uses the same input variable type (format, like an ID or a folder location) as MpMediaPicker.
That error message sounds like a technical issue. The only thing I can think of is that AVAAudio player or MPmedia player is looking for a Volume variable (it is required?) and can't find one. I can't really answer this one as I don't do iPhone Development, try there forums or website for some help.
Sounds like you are doing a good job! If you are interested, (I don't know if you are staying at DA) Mr. Cochran (the dean of students at the Upper School) is teaching a iPhone Development Class and a AP Computer Science Class (I am in). If you want to take it further, or you want to just ask questions I know he is more than happy too!
Good Luck! Tell me when it is finished so I can test the results!
Does any of you know what event I can tap into on the DatePicker when the wheel moves.
I want to play a sound (got sound code) as the wheel spin. Just like the timer set picker in Apple's clock app.
All that is there is a single event for ValueChanges which only fires once, at the end of a wheel spin.
Thanks in advance
I'm not sure this is possible, as the sounds seem to be linked to the Keyboard Clicks in the phone settings. Maybe someone else has a solution, but it doesn't seem to be documented anywhere.
There is an undocumented method for doing this:
Disable UIPickerView sound
#import <UIKit/UIKit.h>
#interface SilentUIPickerView: UIPickerView
{ }
- (void) setSoundsEnabled: (BOOL) enabled;
#end
use this subclass and call [view setSoundsEnabled: NO]
the reason behind this is when your controller is load the datepickr is scrolling so in view did load
write this code.
NSDate *d = [[NSDate alloc] init];
[objDatePicker setDate:d animated:NO];
I have designed an iris shutter animation for a camera view in an iPhone app.
Unfortunately, it seems impossible to hide Apple's shutter when the view appears, even if I hide the camera controls and create a custom cameraOverlayView.
I have gotten around this by animating my shutter on top of the normal shutter when the view appears, using the viewWillAppear and viewDidAppear methods of UIImagePickerController. However, I can't get the shutter to be hidden under my shutter the first time through. When the app launches, it shows a camera view, and the original shutter is visible. On all subsequent views of the cameraController, my workaround works. Any suggestions?
Here's my code. This is from my app delegate:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
cameraController = [[CameraController alloc] initWithMode:#"camera"];
[window addSubview:cameraController.view];
}
And this is from my UIImagePickerController subclass:
- (void) viewWillAppear:(BOOL)animated {
if (self.sourceType != UIImagePickerControllerSourceTypePhotoLibrary || simulatorView) {
[self addShutter];
[shutter close];
}
[super viewWillAppear:animated];
}
- (void) viewDidAppear:(BOOL)animated {
if (self.sourceType != UIImagePickerControllerSourceTypePhotoLibrary || simulatorView) {
[shutter openShutter:.5f];
}
[super viewDidAppear:animated];
}
Note that the docs say that subclassing UIImagePickerController isn't supported, so it may work in some cases but isn't "safe". Not sure if it would get rejected by the app store. (Probably depends on how picky their static code verification tool is.)
I don't really have a good answer, but you might try either 1) iterating over the subviews of the picker's main view to see if you can identify whatever is being used to animate the shutter, then mangle it so that it won't display, or 2) for the initial animation, just show the initial image picker main view under another opaque black view. Not sure if the user-specified overlay view would work for that or not, but you might be able to do those without subclassing.
Searching for undocumented subviews is another thing that's theoretically unsafe though since who knows how the implementation might change in the future.
Possibly too late, but my proposal is to use the following notifications (found while debugging)
PLCameraControllerAvailable - camera controller object is initiated, but shutter is not visible yet
PLCameraViewIrisAnimationDidEndNotification - iris animation is completed.
And the usage is straightforward: call UIGetScreenImage() on 1st notification, render grabbed image on screen (fullscreen) just above the UIImagePicker. Destroy rendered image on the 2nd notification.
I try the same thing with no results, so I do this workaround:
1- Suppose you have a method called showAllButtons with no parameters that will show all your custom things (buttons, tool bars,...)
2- Initialize all the custom controls hidden
3- Write a method that will call the last function but within an interval:
-(void)showAllButtonsDelayed:(NSTimeInterval)a_iMsToDelay
{
NSTimer* tmpShowButtonsTimer = [NSTimer timerWithTimeInterval:a_iMsToDelay target:self selector:#selector(showAllButtons) userInfo:nil repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:tmpShowButtonsTimer forMode:NSDefaultRunLoopMode];
}
4- Call that method in the willDidAppear method of the UIImagePickerController subclass. Play with some values of a_iMsToDelay.
Hope this helps.
I am creating a landscape only application using sdk 3.0 that uses mapkit. I need to use iphone camera in my application. But I am getting following warning when I try to open camera.
"Can't perform full-screen transition. The fromViewController's view must be within a view that occupies the full screen."
The view from which I am calling camera method is mapview with size of 480*320. I have written following code to call camera:
UIImagePickerController *picker = [[UIImagePickerController alloc]init];
picker.delegate = self;
picker.sourceType=UIImagePickerControllerSourceTypeCamera;
[self presentModalViewController: picker animated:YES];
[picker release];
After that I have written the usual method :
-(void)imagePickerController : (UIImagePickerController *)picker didFinishPickingImage : (UIImage *)image editingInfo : (NSDictionary *)editingInfo
But this is never called , since camera is never opened. So my question is what am I missing here...? I am testing this app on actual iphone device , not on simulator. I have used this code in another app and it works fine. But here, it simply doesnt work! Plz help if you have any idea about this..
it sounds like the warning is telling you the problem: the parent view you're passing in to presentModalViewController needs to be a full-screen view. So instead of using "self" in this code you need to use something else, like the parent view controller.
now, you're going to have another problem, because the camera controller doesn't like landscape mode, so you may have to switch back to portrait mode before showing it....
just replace "self" with the parent ViewController which is probably declared in you appDelegate.
I'm trying to use the UIImagePickerController interface from OS 3.1, with the cameraOverlayView and takePicture, but I've clearly failed to understand how this works, and so I'm not getting the behaviour I want.
What I want to do is open the camera and take a picture automatically without having to having the user interact with the picker or edit the image. So I subclass UIImagePickerController (similar to the example in http://github.com/pmark/Helpful-iPhone-Utilities/tree/master/BTL%20Utilities/) and turn off all of the controls:
- (void)displayModalWithController:(UIViewController*)controller animated:(BOOL)animated {
self.sourceType = UIImagePickerControllerSourceTypeCamera;
self.showsCameraControls = NO;
self.navigationBarHidden = YES;
self.toolbarHidden = YES;
// Setting the overlay view up programmatically.
ipView = [[ImagePickerView alloc] init];
self.cameraOverlayView = ipView;
[controller presentModalViewController:self animated:NO];
}
In the overlayView, I've managed to force the takePicture method of UIImagePickerController to fire (I know this, because I can NSLog it, and I hear the sound of the camera taking a picture). The overlayView shows up just fine. However, the delegate method didFinishPickingMediaWithInfo: never gets called, and imagePickerControllerDidCancel doesn't get called either.
So, how do I either get the delegate methods to get called, or save the picture by overriding the takePicture method? (I have no idea how to capture the picture data here, and Google seems to have failed me). I can't help feeling that I've failed to understand how the guts of UIImagePickerController works, but the docs aren't overly helpful:
e.g.:
"You can provide a custom overlay view to display a custom picture-taking interface and you can initiate the taking of pictures from your code. Your custom overlay view can be displayed in addition to, or instead of, the default controls provided by the image picker interface."
or from showCameraControls:
"If you set this property to NO and provide your own custom controls, you can take multiple pictures before dismissing the image picker interface." - How do I dismiss the picker interface?
Note: the delegate is set properly in IB, so that's not the problem.
Thanks for any help you can provide!
I've found that you just have to wait "long enough" before calling takePicture, or it just silently fails. I don't have a good answer for how to determine the minimum value of "long enough" that will always work, but if you set a timer and wait five or ten seconds you should be okay. It would be nice if it returned some kind of an "I'm not ready to take a picture yet, sorry" error either directly from takePicture or through the delegate, but as far as I know it doesn't.
As an update to my own question: It turns out that I was trying to use takePicture too early. When I moved the action to a button on the overlay and sent takePicture from that button (once the picker was presented modally), the delegate methods fired as they should. I don't know if what I wanted is achievable - taking the image without having to press that button, automatically - but if it is, it will probably have to be done by sending takePicture sometime after I was trying to use it.
-(void)imageMethod:(id)sender{
imagePickerController = [[UIImagePickerController alloc]init];
imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
imagePopover=[[UIPopoverController alloc]initWithContentViewController:imagePickerController];
[imagePopover presentPopoverFromRect:importButton.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
}