In my app, I can use code like this to play a video:
- (void)playVideo:(NSURL *)url {
MPMoviePlayerViewController *m = [[[MPMoviePlayerViewController alloc] initWithContentURL:url] autorelease];
[self.rootViewController presentMoviePlayerViewControllerAnimated:m];
}
And it works fine.
But if I use code like this to display a video editor:
- (void)editVideo:(NSString *)file {
UIVideoEditorController *ed = [[[UIVideoEditorController alloc] init] autorelease];
ed.delegate = self;
ed.videoPath = file;
[self.rootViewController presentModalViewController:ed animated:YES];
}
- (void)videoEditorControllerDidCancel:(UIVideoEditorController *)vc {
[vc.parentViewController dismissModalViewControllerAnimated:YES];
}
and just hit cancel, the playVideo: method will no longer play a video! It brings up the movie player window fine and does the throbber to indicate loading, but once the load finishes it fails. Sometimes it closes the video window right away without playing anything, and sometimes it changes to a black screen that responds to no input (but will go away if I send the app to the background and then bring it back to the foreground). It's not MPMoviePlayerViewController Black Screen issue! though, as I get the same black screen if I intentionally leak the MPMoviePlayerViewController.
Am I doing something wrong, or is Apple's junk just broken?
Related
I start -play with AVAudioPlayer, and then set the nowPlaying dictionary like this:
NSMutableDictionary *songInfo = [[NSMutableDictionary alloc] init];
MPMediaItemArtwork *albumArt = [[MPMediaItemArtwork alloc] initWithImage: [UIImage imagedNamed:#"AlbumArt"]];
[songInfo setObject:#"Audio Title" forKey:MPMediaItemPropertyTitle];
[songInfo setObject:#"Audio Author" forKey:MPMediaItemPropertyArtist];
[songInfo setObject:#"Audio Album" forKey:MPMediaItemPropertyAlbumTitle];
[songInfo setObject:albumArt forKey:MPMediaItemPropertyArtwork];
[[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:songInfo];
The lock screen always shows a pause button. I receive the remote control events correctly and I can toggle play/pause through the remote control events, but the lock screen keeps showing "pause" even when it is playing.
Now I seen this work with MPMoviePlayerController. Can someone explain how does the MPNowPlayingInfoCenter determine if it should show a play or a pause button?
Have you set the correct AVAudioSessionCategory on the AudioSession? it needs to be AVAudioSessionCategoryPlayback I believe to get it to work.
I'm not using MPNowPlaying at the moment, but apparently I have to, in order to get the audio info displayed on the lock screen.
However, in addition to what #user3061915 said, to manage the play/pause button, I've used UIEventTypeRemoteControl and it works perfect for controlling the play/pause button:
- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
//if it is a remote control event handle it correctly
if (event.type == UIEventTypeRemoteControl)
{
if (event.subtype == UIEventSubtypeRemoteControlPlay)
{
[self playAudio];
}
else if (event.subtype == UIEventSubtypeRemoteControlPause)
{
[self pauseAudio];
}
else if (event.subtype == UIEventSubtypeRemoteControlTogglePlayPause)
{
[self togglePlayPause]; //This method will handle the toggling.
}
}
I just fixed a problem like this in my own app. I originally used [[AVAudioSession sharedInstance] setCategory:withOptions:error:] and supplied AVAudioSessionCategoryOptionMixWithOthers and AVAudioSessionCategoryOptionDuckOthers. This turned out to be my problem. If you set mix with others, you get no remote control events. They still go to the iPod app. If you set duck others, you get remote control events, but it appears as though it causes the problem you describe: the play/pause button shows the wrong thing. I'm not sure why. I got the play/pause button to behave by setting options to 0, or actually just calling setCategory:error:.
I want my app to only use the front facing camera. So I've implemented the following code.
if ([UIImagePickerControllerisCameraDeviceAvailable:UIImagePickerControllerCameraDeviceFront]) {
self.imagePickerController.cameraDevice = UIImagePickerControllerCameraDeviceFront;
}
This works the first time I open up the camera (it is using the front facing camera). But if I cancel the photo and then re-enter into the camera it is using the rear facing camera.
With each cancel / re-enter into camera it switches between front and rear cameras...
Is there something I am missing?
Tr this code .I used this code and it is working fine .Use this code either in button action or viewwillappear or viewdidload and dismiss the camera view properly
imgPicker =[[UIImagePickerController alloc] init];
imgPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imgPicker.cameraDevice=UIImagePickerControllerCameraDeviceFront;
imgPicker.showsCameraControls = YES;
imgPicker.allowsEditing = YES;
imgPicker.delegate=self;
[self presentViewController:imgPicker
animated:NO completion:nil];
I was having the same problem and resolved the issue in my case by including autorelease on the call to allocate the UIImagePickerController as shown here
UIImagePickerController *cameraUI = [[[UIImagePickerController alloc] init] autorelease];
Ok here is the code that I wrote to display the UIImagePickerController in the camera source. I just declared the myPhotopicker in the header for the property and retain it. Synthesized it in the main code file. Then calling the picker I wrote the code below:
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
if (myPhotopicker==nil) {
myPhotopicker = [[UIImagePickerController alloc] init];
myPhotopicker.delegate = self;
}// create once!
myPhotopicker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentModalViewController:myPhotopicker animated:NO];
}
Upon calling it, there are a few things that is weird happening to the app.
Sometimes, when there are many apps running in the background (iPhone4), the app would fail to load the camera and crash the app. Though it will load CameraRoll/PhotoAlbums without problem.
If the camera view is able to load (when there are less apps running in the background), tapping the Cancel button on the camera view results in the app rebooting itself (where the Default.png image is shown quickly, and back to the main page - like when we started the app).
I have been trying to figure out this problem, but not sure what to do... pls help.. Thanks.
here is the complete code of image pickercontrol try too find solu. here.
http://www.icodeblog.com/2009/07/28/getting-images-from-the-iphone-photo-library-or-camera-using-uiimagepickercontroller/
Regards,
Shyam Parmar
Rather than your 'create once' logic try creating and releasing each time.
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
myPhotopicker = [[UIImagePickerController alloc] init];
myPhotopicker.delegate = self;
myPhotopicker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentModalViewController:myPhotopicker animated:NO];
[myPhotopicker release];
}
You should also implement the delegate to remove the modal view controller from view when it is dismissed (if you haven't already).
You should also check that the current class conforms to the UINavigationConrollerDelegate protocol.
here is my situation :
I call a local movie with an URL. the function is in a custom viewController
in .h :
MPMoviePlayerViewController* modalVideoController
in .m
-(void)startVideoAd:(NSNotification*)notification
{
NSURL* url = (NSURL*)[notification object];
// no problem with url ... already check :)
modalVideoController = [[MPMoviePlayerViewController alloc] initWithContentURL:url];
[modalVideoController shouldAutorotateToInterfaceOrientation:YES];
[self presentMoviePlayerViewControllerAnimated:modalVideoController];
[modalVideoController release];
}
Problem : if the user hit the enter/exit fullscreen button (the double arrow button at right of the fastfoward button in the video button panel), the modalviewController normaly disappear but the video still playing , no images just sounds.
is there a way to kill the video after the button is pressed ?
Answer:
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
// avoid exitFullscreen button problem on FullScreen mode
if(modalVideoController != nil)
{
[modalVideoController.moviePlayer stop];
}
}
this way stop correctly the movie. Last details: modalVideoController became global.
Update:
This has been answered. It was my own stupidity, possibly not worth reading any more of this question. lol.
Question:
Right so i have this UIViewController(master) subclass, it has a UIImagepickerController(camera), it also has a UIView(overlayView). Master setups the camera to be configured as a camera only with a custom cameraOverlay, hiding the custom controls e.t.c.
All appears to work fine apart from when i try to programatically take a picture. What happens is the overlayView calls the master and this triggers the take picture, then i hear the shutter sound and the iris closes, the camera appears to dismiss itself (i am defiantly not doing this in my code) and then my viewDidAppear gets called in my master again.
Anybody have any idea whats going on ?
-(void)viewDidLoad
{
NSLog(#"loading the view");
//if the camera is on the device
if ( [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
//make one
camera = [[UIImagePickerController alloc] init];
//setup some settings that we need
camera.sourceType = UIImagePickerControllerSourceTypeCamera;
camera.showsCameraControls = NO;
camera.navigationBarHidden = NO;
camera.toolbarHidden = YES;
camera.cameraViewTransform = CGAffineTransformScale(camera.cameraViewTransform, 1.03, 1.03);
//show it
overlayView = [[OverlayView alloc] initWithFrame:CGRectMake(0,0,320,480) withDelegate:self andController:self];
camera.cameraOverlayView = overlayView;
camerashowing=NO;
}
else
{
alert = [[UIAlertView alloc] initWithTitle:#"No Camera Detected" message:#"The camera is broken or your device has no camera. Please close the application" delegate:self cancelButtonTitle:nil otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
}
-(void)viewDidAppear:(BOOL)animated
{
if (!cameraShowing)
{
NSLog(#"going to show camera");
[self presentModalViewController:camera animated:NO];
camerashowing = YES;
}
}
-(void)releaseShutter
{
[overlayView toolbarShowWarning];
NSLog(#"going to show camera: %#", self);
[camera takePicture];
}
After some help advice from people in the answers i can say that the camera is not being released.
I have also managed to stop the exec_bad_access by stopping it from calling [presentmodal....] for a second time by checking a bool value in the viewDidAppear Method.
I still have the issue where the modal view disapears, any help, again lol ??
I think you're missing a camera.delegate = self;
For any EXC_BAD_ACCESS errors, you are usually trying to send a message to a released object. The BEST way to track these down is use NSZombieEnabled.
This works by never actually releasing an object, but by wrapping it up as a "zombie" and setting a flag inside it that says it normally would have been released. This way, if you try to access it again, it still know what it was before you made the error, and with this little bit of information, you can usually backtrack to see what the issue was.
It especially helps in background threads when the Debugger sometimes craps out on any useful information.
VERY IMPORTANT TO NOTE however, is that you need to 100% make sure this is only in your debug code and not your distribution code. Because nothing is ever released, your app will leak and leak and leak. To remind me to do this, I put this log in my appdelegate:
if(getenv("NSZombieEnabled") || getenv("NSAutoreleaseFreedObjectCheckEnabled"))
NSLog(#"NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled enabled!");
If you need help finding the exact line, Do a Build-and-Debug (CMD-Y) instead of a Build-and-Run (CMD-R). When the app crashes, the debugger will show you exactly which line and in combination with NSZombieEnabled, you should be able to find out exactly why.
Check the value of the camera member variable before you try and display it:
NSLog(#"going to show camera: %#", camera);
I suspect it might be being released somewhere, but as coneybeare NSZombieEnabled will let you track it down.