how to find Login & logout events in mac? - objective-c

I am fresher for this application development field. I am tried to get notifications during user login & logout events. I have tried with NSWorkSpaceNotifications, but it does not working for me.
Can somebody help me please.
-(void)logInLogOutNotifications{
NSNotificationCenter *notCenter;
notCenter = [[NSWorkspace sharedWorkspace] notificationCenter];
[notCenter addObserver:self
selector:#selector(observerMethod)
name:NSWorkspaceWillPowerOffNotification object:nil];
}
-(void)observerMethod:(NSNotification *)senderNotification;{
NSLog(#"System Logout Notification is called***********************");
}

NSApplicationMain Begin the RunLoop. You are calling logInLogOutNotifications function from main() function, so you shoud run runloop. or call logInLogOutNotifications in applicationDidFinishLaunching
-(void)logInLogOutNotifications{
NSNotificationCenter *notCenter;
notCenter = [[NSWorkspace sharedWorkspace] notificationCenter];
[notCenter addObserver:self
selector:#selector(observerMethod)
name:NSWorkspaceWillPowerOffNotification object:nil];
[[NSRunLoop currentRunLoop] run];
}

Your method takes one argument, so you should change
#selector(observerMethod)
to
#selector(observerMethod:)

If you're like me and having problems figuring out why in the world you are not getting receiving the NSWorkspaceWillPowerOffNotification notification, make sure you are setting yourself as an observer of [[NSWorkspace sharedWorkspace] notificationCenter] and -NOT- [NSNotificationCenter defaultCenter]!
I spent the better part of a day trying to debug why I wasn't getting that notification because I didn't read the answer clearly!

If you want to know when user resign or become active you just should subscribe to the following notifications:
Swift 3
NSWorkspace.shared().notificationCenter.addObserver(self, selector: #selector(sessionResignActive(_:)), name: NSNotification.Name.NSWorkspaceSessionDidResignActive, object: nil)
NSWorkspace.shared().notificationCenter.addObserver(self, selector: #selector(sessionBecomeActive(_:)), name: NSNotification.Name.NSWorkspaceSessionDidBecomeActive, object: nil)

Related

Unable to receive NSWorkspaceActiveSpaceDidChangeNotification specifically, but other notifications work

-(void)monitor {
NSNotificationCenter *notcenter;
notcenter = [[NSWorkspace sharedWorkspace] notificationCenter];
[notcenter addObserver:self selector:#selector(activeSpaceDidChange:) name:NSWorkspaceActiveSpaceDidChangeNotification object:[NSWorkspace sharedWorkspace]];
- (void) activeSpaceDidChange:(NSNotification *)notification
{
NSLog(#"%#", notification.name);
}
Hey guys, does anyone have any info on this specific notification? For some reason, I seem to be able to get all other notifications, and if I put in nil for the name and receive all NSWorkspace messages, I can get all of them except NSWorkspaceActiveSpaceDidChangeNotification. All code snippets I have seen from people don't seem to be doing anything specific or different than what I have, so I have no idea why I wouldn't be able to get these notifications specifically.

After IORegisterForSystemPower failing to call IODeregisterForSystemPower

I have an application, written in Objective-C for MacOS 10.10+ which registers for sleep/wake notifications (code sample below, but the code isn't the question). What I am wondering is, if I call IORegisterForSystemPower at App initialisation, but during debugging I kill the app before it has a chance to call IODeregisterForSystemPower, what are the implications? Does the app get de-registered automatically when it dies in any case? Is there a system dictionary I need to clear out (a plist somewhere, etc.)? Thanks in advance for any help.
io_object_t root_notifier = MACH_PORT_NULL;
IONotificationPortRef notify = NULL;
DebugLog(#"App: Logging IORegisterForSystemPower sleep/wake notifications %#", [NSDate date]);
/* Log sleep/wake messages */
powerCallbackPort = IORegisterForSystemPower ((__bridge void *)self, &notify, sleepWakeCallback, &root_notifier);
if ( powerCallbackPort == IO_OBJECT_NULL ) {
DebugLog(#"IORegisterForSystemPower failed");
return;
}
self.rootNotifierPtr = &(root_notifier); // MARK: deregister with this pointer
if ( notify && powerCallbackPort )
{
CFRunLoopAddSource(CFRunLoopGetCurrent(),IONotificationPortGetRunLoopSource(notify), kCFRunLoopDefaultMode);
}
To be honest, I don't know the exact answer. But it may help you.
First of, if you call IORegisterForSystemPower, you need to make two calls in this order: - Call IODeregisterForSystemPower with the 'notifier' argument returned here. - Then call IONotificationPortDestroy passing the 'thePortRef' argument returned here (Please visit apple's document for more detail).
In case of port binding, if I use CFSocketSetAddress, before releasing this socket no other can use this port for binding. But in case of app terminate/closed without releasing this socket this port is available. That means after terminated the app system automatically releasing this.
Does the app get de-registered automatically when it dies in any case?
I think it will automatically de-registered by system.
I also used similar code as you in one of my project. But recently replaced with below codes:
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self selector: #selector(receiveWakeNotification:) name: NSWorkspaceDidWakeNotification object: nil];
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self selector: #selector(receiveSleepNotification:) name: NSWorkspaceWillSleepNotification object: nil];

Detect when a volume is mounted on OS X

I have an OS X application that needs to respond to a volume being mounted or unmounted.
I've already solved this problem by retrieving the list of volumes periodically and checking for changes, but I'd like to know if there is a better way.
Register to the notification center you get from [[NSWorkspace sharedWorkspace] notificationCenter] and then process the notifications you are interested in. These are the volume related ones: NSWorkspaceDidRenameVolumeNotification, NSWorkspaceDidMountNotification, NSWorkspaceWillUnmountNotification and NSWorkspaceDidUnmountNotification.
The NSWorkspace approach is exactly the kind of thing I was looking for. A few lines of code later, I have a much better solution than using a timer.
-(void) monitorVolumes
{
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector: #selector(volumesChanged:) name:NSWorkspaceDidMountNotification object: nil];
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector: #selector(volumesChanged:) name:NSWorkspaceDidUnmountNotification object:nil];
}
-(void) volumesChanged: (NSNotification*) notification
{
NSLog(#"dostuff");
}
Swift 4 version:
Declare NSWorkspace in applicationDidFinishLaunching and add observers for mount and unmount events.
let workspace = NSWorkspace.shared
workspace.notificationCenter.addObserver(self, selector: #selector(didMount(_:)), name: NSWorkspace.didMountNotification, object: nil)
workspace.notificationCenter.addObserver(self, selector: #selector(didUnMount(_:)), name: NSWorkspace.didUnmountNotification, object: nil)
Capture mount and unmount events in:
#objc func didMount(_ notification: NSNotification) {
if let devicePath = notification.userInfo!["NSDevicePath"] as? String {
print(devicePath)
}
}
#objc func didUnMount(_ notification: NSNotification) {
if let devicePath = notification.userInfo!["NSDevicePath"] as? String {
print(devicePath)
}
}
It will print device path e.g /Volumes/EOS_DIGITAL
Here are the constants you can read from userInfo.
NSDevicePath,
NSWorkspaceVolumeLocalizedNameKey
NSWorkspaceVolumeURLKey
Do you know SCEvents? It allows you to be notified when the contents of an observed folder change (/Volumes). This way you don't have to use a timer to periodically check the contents.

Get notification using NSDistributedNotificationCenter for iTunes on song info change

I know you can use [iTunesDNC addObserver:self selector:#selector(updateInfo:) name:#"com.apple.iTunes.playerInfo" object:nil]; to get a notification every time the player changes song/stops/plays/etc. But what I need is a notification every time information is changed on iTunes (ex. song title changed, lyrics changed, artist, etc)
Any suggestions? Im pretty sure I just need to change com.apple.iTunes.playerInfo to something else that is not playerInfo.
I know it should be posible, because there is an app called SongGenie that will change its info if you edit a song's ID3 tags on iTunes or add lyrics.
Thank you!
Yes, there is a way. Every time song info is changed iTunes posts a "com.apple.iTunes.sourceSaved" notification whose userInfo dictionary is the user's library.
You can check out this and other notifications that iTunes sends by listening to every notificaion posted to the Distributed Notification Center.
[[NSDistributedNotificationCenter defaultCenter] addObserver:self
selector:#selector(allDistributedNotifications:)
name:nil
object:nil];
- (void) allDistributedNotifications:(NSNotification *)note
{
NSString *object = [note object];
NSString *name = [note name];
NSDictionary *userInfo = [note userInfo];
NSLog(#"<%p>%s: object: %# name: %# userInfo: %#", self, __PRETTY_FUNCTION__, object, name, userInfo);
}
or use scripting bridge, https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ScriptingBridgeConcepts/AboutScriptingBridge/AboutScriptingBridge.html#//apple_ref/doc/uid/TP40006104-CH3-SW9

Objective-C Mac OS X Distributed notifications iTunes

i need a little help, i currently have a method; updateTrackInfo in my Mac OS X application which gets the artist name, the track name and duration of the track currently being played in iTunes
However i want the app to listen for the distributed iTunes notification; com.apple.iTunes.playerInfo then call the method updateTrackInfo when ever the notification is distributed by iTunes. Please could someone help me, on what i would need to write in both the header and implementation file.
Thanks, Sami.
You're looking for -[NSDistributedNotificationCenter addObserver:selector:name:object:]:
NSDistributedNotificationCenter *dnc = [NSDistributedNotificationCenter defaultCenter];
[dnc addObserver:self selector:#selector(updateTrackInfo:) name:#"com.apple.iTunes.playerInfo" object:nil];
Elsewhere in the same class...
- (void) updateTrackInfo:(NSNotification *)notification {
NSDictionary *information = [notification userInfo];
NSLog(#"track information: %#", information);
}
It even gives you a whole bunch of track information in the notification. Isn't that nice?
Thanks for your help, you helped me correct my code, I had this written up:
- (id) init {
self = [super init];
if (!self) return nil;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receiveNotification:)
name:#"com.apple.iTunes.playerInfo"
object:nil];
return self;}
- (void) receiveNotification:(NSNotification *) notification {
if ([#"com.apple.iTunes.playerInfo" isEqualToString:#"com.apple.iTunes.playerInfo"]) {
NSLog (#"Successfully received the test notification!");
}}
But it used NSNotificationCenter instead of NSDistributedNotificationCenter. Which is where I was going wrong.
Thanks, Sami.