NSUserNotification close calls didActivateNotification - objective-c

Since MacOS 10.13 everytime I click the close button on a NSUserNotification it calls:
- (void) userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification
How can I prevent this or handle the close vs the action button
To create the notification I do:
NSUserNotification *notification = [[NSUserNotification alloc] init];
...
[notification setHasActionButton:false];
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:(id)self];
and NSUserNotificationAlertStyle in the .plist is set to "alert"
but now basically the close button reacts the same way the actionButton does??

NSUserNotification has property from which you can manage notification identifier or hasActionButton value, so you can handle the close vs the action button with if else in the same delegate method
- (void) userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification{
}

This is works for me..
you can remove notification in didActivateNotification: method
- (void) userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification
{
NSLog(#"Notification - Clicked");
[center removeDeliveredNotification: notification];
notification=nil;
}
where center is...
NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
[center scheduleNotification:notification];

Related

didActivateNotification is not responding to NSUserNotification

I'm working to get osx native notifications working. I'm able to create a notification but not get the didActivateNotification working. I want didActivateNotification to allow me to focus the window and remove the notification from the notification center.
Here is my code: notice.m
#import "Notice.h"
#implementation Notice
- (void) notify:(NSDictionary *)message {
NSLog(#"Notification - Show it");
NSUserNotification *notification = [[NSUserNotification alloc] init];
[notification setTitle:[message valueForKey:#"title"]];
[notification setInformativeText:[message valueForKey:#"content"]];
[notification setDeliveryDate:[NSDate dateWithTimeInterval:0 sinceDate:[NSDate date]]];
[notification setSoundName:NSUserNotificationDefaultSoundName];
NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
[center scheduleNotification:notification];
}
- (void) userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification
{
NSLog(#"Notification - Clicked");
notification=nil;
[center removeDeliveredNotification: notification];
}
This is firing properly:
NSLog(#"Notification - Show it");
But this is not:
NSLog(#"Notification - Clicked");
Any suggestions? Thanks
You probably have to set the delegate for NSUserNotificationCenter:
NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
center.delegate = self;
You should also make sure your Notice class implements the NSUserNotificationCenterDelegate protocol.

NSUserNotification - How open the app when clicked

I'm using NSUserNotification to display notifications. This is working fine. The problem is that when you click on a notification:
The apps notifications are not removed from the notification center.
The app (when minimized) does not open.
Anyone familiar with the NSUserNotification who can offer some pointers?
notice.m
#import "Notice.h"
#implementation Notice
- (void) notify:(NSDictionary *)message {
NSLog(#"Notification - Show it");
NSUserNotification *notification = [[NSUserNotification alloc] init];
[notification setTitle:[message valueForKey:#"title"]];
[notification setInformativeText:[message valueForKey:#"content"]];
[notification setDeliveryDate:[NSDate dateWithTimeInterval:0 sinceDate:[NSDate date]]];
[notification setSoundName:NSUserNotificationDefaultSoundName];
NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
[center scheduleNotification:notification];
}
- (void) userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification
{
NSLog(#"Notification - Clicked");
notification=nil;
[center removeDeliveredNotification: notification];
}
#pragma mark WebScripting Protocol
+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector
{
if (selector == #selector(notify:))
return NO;
return YES;
}
+ (NSString*) webScriptNameForSelector:(SEL)selector
{
id result = nil;
if (selector == #selector(notify:)) {
result = #"notify";
}
return result;
}
// right now exclude all properties (eg keys)
+ (BOOL) isKeyExcludedFromWebScript:(const char*)name
{
return YES;
}
#end
Thank you
Just implement the NSUserNotificationCenterDelegate and define this method:
- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification
Example:
This is what I did in a "notifier" application.
- (void) userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification
{
NSRunAlertPanel([notification title], [notification informativeText], #"Ok", nil, nil);
}
- (void) userNotificationCenter:(NSUserNotificationCenter *)center didDeliverNotification:(NSUserNotification *)notification
{
notifications=nil;
[tableView reloadData];
[center removeDeliveredNotification: notification];
}
When the notification is activated (click by the user) I just inform the user with a panel (I could use a hud window).In this case I immediately remove the delivered notification, but this is not what happens usually.The notification could stay there some time and be removed after 1/2 hours (it depends on the application that you are developing).

MPMoviePlayerViewController backgrounding deal. How to continue playing after returning from background to foreground?

I'm working on application for video streaming. It is built with ARC for iOS5.
To display view I use MPMoviePlayerViewController this way:
.h
#interface EpisodesTableViewController : UITableViewController<EpisodeUrlResolverDelegate> {
NSTimeInterval playbackTime;
EpisodeUrlResolver *episodeUrlResolver;
}
#property (strong, nonatomic) MPMoviePlayerViewController *player;
#end
.m
#implementation EpisodesTableViewController
#synthesize episodes, player;
- (void)viewDidLoad
{
[super viewDidLoad];
episodeUrlResolver = [[Soap4MeEpisodeUrlResolver alloc] init];
[episodeUrlResolver setDelegate:self];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(willEnterForeground) name:#"WillEnterForeground" object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(willEnterBackground) name:#"WillEnterBackground" object:nil];
}
- (void)viewDidUnload
{
episodeUrlResolver = nil;
player = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"WillEnterForeground" object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"WillEnterBackground" object:nil];
[super viewDidUnload];
}
- (void)url:(NSURL *)url WasResolvedForEpisode:(Episode *)episode {
player = [[MPMoviePlayerViewController alloc] initWithContentURL:url];
player.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
player.moviePlayer.allowsAirPlay = YES;
[self presentModalViewController:player animated:YES];
}
- (void)willEnterBackground {
if (player) {
playbackTime = player.moviePlayer.currentPlaybackTime;
}
}
- (void)willEnterForeground {
if (!player)
return;
if(player.moviePlayer.playbackState == MPMoviePlaybackStateInterrupted || player.moviePlayer.playbackState == MPMoviePlaybackStateStopped || player.moviePlayer.playbackState == MPMoviePlaybackStatePaused)
{
[self continuePlayback];
}
}
- (void)continuePlayback {
[self presentModalViewController:player animated:YES];
[player.moviePlayer setInitialPlaybackTime:playbackTime];
NSLog(#"%f", player.moviePlayer.initialPlaybackTime);
[player.moviePlayer play];
}
Few words about presented code:
when url for video is resolved I create the MPMoviePlayerViewController object for video playback. Playback is started. Then when app is going background with home button MPMoviePlayerViewController automatically pauses playback and dissapears from screen (weird behavior, as for me). Thats why I have to save playback time when app is going background and show existing MPMoviePlayerViewController again with restored playback time when app is back to foreground.
It works fine when user presses home button and then is going back to application.
But it doesn't work when user locks the device. WillEnterBackground notification is fired when
applicationWillEnterForeground is called, so for locking event it is called too.
But in case when user locks the device MPMoviePlayerViewController wasn't being dismissed properly as in situation when user presses home button. It is hidden from the screen, but calling the code
[self presentModalViewController:player animated:YES];
throws the exception
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modally an active controller <EpisodesTableViewController: 0x91b3950>.'
I tried to change the code to dismiss controller:
- (void)willEnterForeground {
if (!player)
return;
if(player.moviePlayer.playbackState == MPMoviePlaybackStateInterrupted || player.moviePlayer.playbackState == MPMoviePlaybackStateStopped || player.moviePlayer.playbackState == MPMoviePlaybackStatePaused)
{
if (self.presentedViewController) {
[self dismissViewControllerAnimated:YES completion:^{
[self continuePlayback];
}];
}
else {
[self continuePlayback];
}
}
}
Now it doesn't throw the exception, but displays warning
wait_fences: failed to receive reply: 10004003
Also completion block is never called.
How to properly to solve the background/foreground continue playing with modally displayed MPMoviePlayerViewController?
Thanks for replies.
I solved the problem.
Method -willEnterBackground should look like:
- (void)willEnterBackground {
if (player) {
playbackTime = player.moviePlayer.currentPlaybackTime;
[self dismissModalViewControllerAnimated:NO];
}
}
We have to dismiss MPMoviePlayerViewController manually when app is entering background mode.
Pay attention to use only
[self dismissModalViewControllerAnimated:NO];
instead of
[self dismissMoviePlayerViewControllerAnimated];
Thats because MPMoviePlayerViewController was shown with
[self presentModalViewController:player animated:YES];

Programmatically show controls in MPMoviePlayerController

I have a MPMoviePlayerController subclass that should show the controls when playback is finished. I have attached a responder to the MPMoviePlayerPlaybackDidFinishNotification notification and tried setting the control style as follows:
[self setControlStyle:MPMovieControlStyleEmbedded];
This is not working. In essence, at the end of the video I want to controls to show.
How can I show controls programatically?
NOTE: The controller is NOT in fullscreen mode.
Kindly find my full Code about this , it's working with me
add .h class add this
#property(strong,nonatomic) MPMoviePlayerViewController * moviePlayer;
at .m class add this code "pass the movie URl"
-(void) playMovie:(NSString *)filePath
{
NSURL *theOutputURL = [NSURL fileURLWithPath:filePath];
if(_moviePlayer)
[_moviePlayer.moviePlayer setContentURL:theOutputURL];
else
_moviePlayer = [[MPMoviePlayerViewController alloc] initWithContentURL:theOutputURL];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(myMovieFinishedCallback:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:_moviePlayer.moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayerPlaybackStateDidChange:) name:MPMoviePlayerPlaybackStateDidChangeNotification object:_moviePlayer.moviePlayer];
if (![_moviePlayer.moviePlayer isPreparedToPlay])
[_moviePlayer.moviePlayer prepareToPlay];
_moviePlayer.moviePlayer.movieSourceType = MPMovieSourceTypeFile;
[_moviePlayer.moviePlayer setFullscreen:YES];
_moviePlayer.moviePlayer.controlStyle=MPMovieControlStyleEmbedded;
[_moviePlayer.moviePlayer setContentURL:theOutputURL];
_moviePlayer.view.frame = CGRectMake(0, 0, [[UIScreen mainScreen]bounds].size.width, [[UIScreen mainScreen]bounds].size.height);
[_moviePlayer shouldAutorotateToInterfaceOrientation: AVCaptureVideoOrientationLandscapeRight];
[self.view addSubview:_moviePlayer.view];
}
- (void) moviePlayerPlaybackStateDidChange: (NSNotification *) notification {
if (_moviePlayer.moviePlayer.playbackState == MPMoviePlaybackStateStopped) {
[_moviePlayer.moviePlayer setContentURL:[_moviePlayer.moviePlayer contentURL]];
[_moviePlayer.moviePlayer play];
}
}
-(void)myMovieFinishedCallback:(NSNotification*)aNotification
{
// to add your code after playback is finished
}

MPMoviePlayerController problems on iPad

I'm trying to use the MPMoviePlayerController class on the iPad.
Here's my code:
multimediaPlayer = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL fileURLWithPath:path]];
multimediaPlayer.movieControlMode = MPMovieControlModeDefault;
[multimediaPlayer play];
and this works very well on the iPhone but it don't want to run on the iPad. I hear the sound of the video, but the movie doesn't playing.
Why it can be this problem?
Below code working perfect for my application. Hope it would do same for you.
The main thing is to set the frame of mpMoviePlayerController's frame. if you don't do it, it would almost not show the video.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[UIApplication sharedApplication] setStatusBarHidden:YES];
// Register to receive a notification when the movie has finished playing.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:nil];
// Register to receive a notification when the movie scaling mode has changed.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movieScalingModeDidChange:)
name:MPMoviePlayerScalingModeDidChangeNotification
object:nil];
kDomain = [NSString stringWithString:#"http://www.virtua-book.com/"];
[navigationController setNavigationBarHidden:YES];
NSURL *ur=[[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:#"IPAD" ofType:#"mp4"]];
mpMCtr=[[MPMoviePlayerController alloc] initWithContentURL:ur];
mpMCtr.fullscreen=YES;
[mpMCtr setScalingMode:MPMovieScalingModeFill];
[mpMCtr setShouldAutoplay:YES];
[mpMCtr setControlStyle:MPMovieControlStyleNone];
[mpMCtr setMovieSourceType:MPMovieSourceTypeFile];
mpMCtr.view.frame = CGRectMake(0, 0, 1024, 768);
[mpMCtr setRepeatMode:MPMovieRepeatModeNone];
[mpMCtr play];
[ur release];
// Override point for customization after app launch
[navigationController.view addSubview:mpMCtr.view];
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
return YES;
}
// Notification called when the movie finished playing.
- (void) moviePlayBackDidFinish:(NSNotification*)notification
{
[mpMCtr.view removeFromSuperview];
}
To fix back/forward (or previous/next) buttons you should do the following:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(moviePlayerPlaybackStateDidChange:) name:MPMoviePlayerPlaybackStateDidChangeNotification object:nil];
...
- (void) moviePlayerPlaybackStateDidChange: (NSNotification *) notification {
if (moviePlayer.playbackState == MPMoviePlaybackStateStopped) {
[moviePlayer setContentURL:[moviePlayer contentURL]];
[moviePlayer play];
}
}
Something along these lines is probably what you want to do:
MPMoviePlayerViewController *mpvc = [[MPMoviePlayerViewController alloc] initWithContentUrl:movieUrl];
[self presentMoviePlayerViewController:mpvc];
MPMoviePlayerViewController *mp = [[MPMoviePlayerViewController alloc]initWithContentURL:movieURL];
mp.moviePlayer.controlStyle = 2;
Ok, guys, I found that this: is deprecated.
The solution is multimediaPlayer.controlStyle = MPMovieControlStyleDefault; but it still doesn't work.