NSUserNotification makes sound but does not show - objective-c

My NSUserNotification is being delivered, playing the given sound, but doesn't show visually on the screen if my app is not the top-most application.
If my application is in the background, the notification does not show. If my application is active, it shows. In both cases the sound plays.
Here is how I'm sending the notification:
NSUserNotification *notification = [[NSUserNotification alloc] init];
[notification setTitle: #"hi"];
[notification setSoundName: NSUserNotificationDefaultSoundName];
[notification setDeliveryDate: [NSDate dateWithTimeIntervalSinceNow: 3]];
[[NSUserNotificationCenter defaultUserNotificationCenter] scheduleNotification: notification];
And I am overriding shouldPresentNotification to always present it.
[NSUserNotificationCenter defaultUserNotificationCenter].delegate = self;
...
- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification {
return YES;
}
OSX 10.10.1 Yosemite
How do I make this notification always display, just like it always plays the sound?

I found two ways to make a notification always display:
Remove all previous notifications with
[[NSUserNotificationCenter defaultUserNotificationCenter] removeAllDeliveredNotifications];
Or by changing the identifier
notification.identifier = #"com.yourcompany.yourapp.notificationidentifier";

Related

How to Highlight the active window and dim the rest windows cocoa app programmatically?

In my Cocoa app I want to Highlight which ever the window is active and dim the rest windows. something like focus window application.
Below block is my code.
NSNotificationCenter* center = [[NSWorkspace sharedWorkspace] notificationCenter];
[center addObserver:self selector:#selector(newApplicationDidActive:) name:NSWorkspaceDidActivateApplicationNotification object:nil];
- (void)newApplicationDidActive:(NSNotification *)notification {
NSDictionary* userInfo = notification.userInfo;
NSLog(#"did Active %#", [userInfo objectForKey:NSWorkspaceApplicationKey ]
if ([[NSUserDefaults standardUserDefaults] boolForKey:kUDKeyWindowFocus]) {
NSLog(#"window focus");
[[FocusWindow defaultHandler].window orderWindow:NSWindowAbove relativeTo:0];
}
}
Update :
Added below code partially working but not accurate can some suggest any ideas or views.
NSPoint mouseLocation = [NSEvent mouseLocation];
NSInteger windowNumber = [NSWindow windowNumberAtPoint:mouseLocation belowWindowWithWindowNumber:0];
NSLog(#"windowNumber %lu",windowNumber);
[focusWindowController.window orderWindow:NSWindowBelow relativeTo:windowNumber];
[app activateWithOptions:NSApplicationActivateIgnoringOtherApps];
Instead of
[[FocusWindow defaultHandler].window orderWindow:NSWindowAbove relativeTo:0];
In First Block windowNumberAtPoint:belowWindowWithWindowNumber which gives Frontmost window number with that i am ordering my dimming window below orderWindow:relativeTo the Frontmost window.

How to get iBeacon Notification when the app is in Background mode in ios 10 and above?

I have implemented iBeacon Notification in iOS 10 using objective-c. Can some one help me solve this problem to get the iBeacon in background mode in ios 10?
Even if the app is not running, location events (related to the beacons in this case) are handled the same way as any other app launching events. Every time a phone enters or exits a region while the app is terminated, it will be automatically launched.
application:didFinishLaunchingWithOptions: method (of AppDelegate class) is called with UIApplicationLaunchOptionsLocationKey key existing in launchOptions parameter.
When you verify this key exists (so location was the reason that your app was launched) you should create new instance of ESTBeaconManager class, set delegate to AppDelegate object (or any other object that is working as ESTBeaconManagerDelegate and was created before this event occurred) and start monitoring.
Region you are passing to the startMonitoringForRegion: method is not important, as ESTBeaconManager delegate will receive the most recent region information. You can just pick any of the ones your app registered in iOS. After Monitoring is revoked, app will automatically receive most recent entered/exited region event in beaconManager:didEnterRegion: or beaconManager:didExitRegion: method.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if([launchOptions objectForKey:#"UIApplicationLaunchOptionsLocationKey"])
{
self.beaconManager = [ESTBeaconManager new];
self.beaconManager.delegate = self;
// don't forget the NSLocationAlwaysUsageDescription in your Info.plist
[self.beaconManager requestAlwaysAuthorization];
[self.beaconManager startMonitoringForRegion:[[ESTBeaconRegion alloc]
initWithProximityUUID:ESTIMOTE_PROXIMITY_UUID
identifier:#"AppRegion"]];
}
return YES;
}
-(void)beaconManager:(ESTBeaconManager *)manager didEnterRegion:(ESTBeaconRegion *)region
{
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.alertBody = #"Enter region";
notification.soundName = UILocalNotificationDefaultSoundName;
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
}
-(void)beaconManager:(ESTBeaconManager *)manager didExitRegion:(ESTBeaconRegion *)region
{
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.alertBody = #"Exit region";
notification.soundName = UILocalNotificationDefaultSoundName;
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
}

How to remove NSUserNotification

I am using NSUserNotificationCenter to display scheduled Notifications. I have notifications of my app in the right side notification panel so whenever I click on the notification it'll launch the app but it won't remove notification from the panel.
When app is not running and I clicked on the notification, applicationDidFinishLaunching is called and it won't remove notification because didActivateNotification delegate is not called.
When application is already running and I clicked on the notification, appShouldHandleReopen is called. And won't call the delegate.
-(void)userNotificationCenter:(id)center didActivateNotification:(id)notification
I checked behavior in all the standard app they will remove notification when user click on the notifications.
I have implemented it as follows:
/* will create notification and set the delegate*/
#interface NotificationViewController : NSViewController
{
id delegate;
}
-(void)showNotification;
#end
#implementation NotificationViewController
- (void)createNotification:(NSString*)str
{
Class UserNotificationClass=NSClassFromString(#"NSUserNotification");
id notification = [[UserNotificationClass alloc] init];
//Set the title of the notification
[notification setTitle:#"My Notification"];
[notification setSubtitle:#"Test"];
[notification setHasActionButton:YES];
[notification setActionButtonTitle:#"OK"];
[notification setOtherButtonTitle:#"CANCEL"];
//Set the text of the notification
[notification setInformativeText:str];
[notification setDeliveryDate:[NSDate dateWithTimeInterval:0.1 sinceDate:[NSDate date]]];
[notification setSoundName:#"NSUserNotificationDefaultSoundName"];
[notification setUserInfo:[NSDictionary dictionaryWithObjectsAndKeys:str,#"string",nil]];
Class UserNotificationCenterClass=NSClassFromString(#"NSUserNotificationCenter");
id center = [UserNotificationCenterClass defaultUserNotificationCenter];
[center setDelegate:self.delegate];
//Scheldule our NSUserNotification
[center scheduleNotification:notification];
[notification release];
}
#end
/* Class which implements NSUserNotificationDelegate*/
#interface NotificationHandler : NSObject <NSUserNotificationCenterDelegate>
{
}
- (void)createNotification:(NSString*)str;
#end
#implementation NotificationHandler
- (void)createNotification:(NSString*)str
{
NotificationHandler *notificationHandler = [[NotificationHandler alloc] initWithNibName:#"NotificationHandler" bundle:[NSBundle mainBundle]];
notificationHandler.delegate = self;
[notificationHandler showNotification];
}
- (void)userNotificationCenter:(id)center didActivateNotification:(id)notification
{
[center removeDeliveredNotification:notification];
}
- (BOOL)userNotificationCenter:(id)center shouldPresentNotification:(id)notification
{
return YES;
}
#end
However this is not working in my case. Please let me know some pointer on it...
Other thing I observed:
When I implement NSUserNotificationDelegate into AppDelegate it'll work for 2nd case i.e. (When application is already running and I clicked on the notification) - in this case notification is removed.
And for deleting notification for 1st case i.e. (When app is not running and I clicked on the notification, appDidFinishLaunching is called) I wrote following code in appDidFinishLaunching.
NSUserNotification *userNoti = [[notification userInfo] valueForKey:#"NSApplicationLaunchUserNotificationKey"];
[[NSUserNotificationCenter defaultUserNotificationCenter] removeDeliveredNotification:userNoti];
Can anybody let me know whats the reason, why this works in the AppDelegate but not in my above implementation or Am I doing something wrong in first one?
Is my AppDelegate implementation fine to handle my both scenarios?
Thanks in Advance.

How to resume a movie that's being played with presentMoviePlayerViewControllerAnimated

I'm uisng this code to display a movie:
MPMoviePlayerViewController *mp = [[MPMoviePlayerViewController alloc]
initWithContentURL:movieURL];
mp.moviePlayer.movieSourceType = MPMovieSourceTypeUnknown;
[self presentMoviePlayerViewControllerAnimated:mp]; [mp.moviePlayer play];
The code is working fine. However when the application goes to the background while playing a movie, when the app comes back in the foreground the movieplayer is not displayed. (I see the view of the controller that called presentMoviePlayerViewControllerAnimated:mp
Is it possible when entering the foregound to resume the movie that was playing before the app went to the background?
Have you set the UIBackgroundmode to audio and also there has been problem with playing the video after app enters foreground .Refer this Tutorial on MPMoviePlayerViewController Also you can try using MPMoviePlayerViewController which has options for implementing various notifications .
you can implement notification techniques to handle it. Add a notification in the class where movie player is playing and associate with it a selector. When app goes to background then in the delegate method
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
UIApplication *app = [UIApplication sharedApplication];
UIBackgroundTaskIdentifier bgTask = 0;
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
}];
}
write this code.Actually when app goes background it pauses the MPMoviePlayerController so when it is coming to foreground you post the notification which call the method in class where movie controller is implemented and play it again in this method.
-(void)playIntroAnimationAgain
{
[[NSNotificationCenter defaultCenter]removeObserver:self name:NOTIFICATION_PlayAgain_Player object:nil];
[self.moviePlayerController play];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(playIntroAnimationAgain)name:NOTIFICATION_PlayAgain_Player object:nil];
}
It solved my problem.

MPMoviePlayerViewController doesn't show well when playing video

I trying to show video on my App. The App hides the iPhone top panel. The player seems to work fine. There is just one annoying problem: when the player shows the video, it sometimes show the top panel and sometime hides it. When it is hidden, the video player panel is pushed a little (the same size of the panel that used to be there). Is is Apple bug? Am I doing something wrong?
Here is my code:
- (void) showFullscreenMediaWithURL: (NSURL *) mediaURL
{
MPMoviePlayerViewController *ctrl = [[MPMoviePlayerViewController alloc] initWithContentURL: mediaURL];
[[NSNotificationCenter defaultCenter] addObserver:self selector: #selector(playbackDidFinish:) name:MPMoviePlayerPlaybackDidFinishNotification object:ctrl.moviePlayer];
ctrl.moviePlayer.movieSourceType = MPMovieSourceTypeFile;
ctrl.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[ctrl setWantsFullScreenLayout:YES];
[self presentMoviePlayerViewControllerAnimated:ctrl];
[ctrl release];
}
-(void) playbackDidFinish:(NSNotification*)aNotification
{
NSLog(#"Finished playback");
MPMoviePlayerController *player = [aNotification object];
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification
object:player];
[player stop];
[self dismissMoviePlayerViewControllerAnimated];
[[captureManager session] startRunning];
}
if by iPhone top panel you mean the iPhone Status bar, then the solution should be simple.
Just before present/dismissMoviePlayerViewControllerAnimated add the following:
// Hide Status Bar
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
// Show Status Bar
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];
Update: I can see what seems to be your problem.
First, the upper bar with the network indication icons and other information is the status bar (and nothing else). Your problem seems to be more ViewController related then a MediaPlayer. In other words, If you would have try to "push" some other ViewController to full screen (as the player is) you would have experience the exact same issue.
Second, the proper way, or I might say: my preferred way, of loading a view controller to full screen is the following:
Setup a full screen rootViewController which will be loaded on applicationDidFinishLaunchingWithOptions on your appDelegate.
On the rootViewController init put your default viewController (the one you used to load from appDelegate). Make sure that the rootViewController.view's frame is filling the screen.
Create 2 messages on rootViewController: LoadFullscreen:viewController and dismissFullscreen using present/dismissModelViewController. the setStatusBarHidden messages should be called from here.
To Lunch the player on full screen, create the player viewController and perform [rootViewController LoadFullscreen:player];
There are some other ways, but generally, this is the best practice and the method I recommend. It's relatively "a lot of code" to implement, thats why I couldn't help you with code snippers, but the general idea is relatively simple.
I hope that's help, E.G :)