How to set local notification on Mac OS X? - macos

I'm writing an app for mac os x, and I have to display a notification every day, to remind users about something. The notification should appear even if the app isn't running, and I can't use push notification.
I guess the best solution would be local notification, just like on iOS. Also I know UILocalNotification is available on iOS only. But I think there should be an alternative solution.
Can anybody please point me in the right direction? Is it even possible? If yes, what is the best practice to do this?

Local notifications support, very similar to iOS local notifications, has been added in MacOS 10.8 (Mountain Lion). See MacOSX10.8/Frameworks/Foundation.Framework/NSUserNotification.h for more information. Quick usage example could be found here.

The notification should appear even if the app isn't running
Well, something will still have to be running to send the actual notification. Mostly helper programs are used for this (separate executable binaries that are added as launch agents or launch daemons). So I'm suggesting you create a daemon-like helper program that would be added as launch daemon on a per-user basis. You can also look at shared file list api to see how can it be added to user's login items.

Related

How can one run many copies of a MacOS App

I was thinking of this today and was wondering what is it on MacOS app that prevent me from running, for example, 5 instances of a specific app?
I was thinking it could be the bundle_id (similar to iOS) but when I copied and renamed the app (to appname_2) edited the bundle_id (to bundle_id_2) for that specific app it didn't launch and instead just put that application in the foreground.
Maybe there's a method that checks the Mac address of the device and only allows one app to run per Mac address.
Due to it being hard to find and info on this online, wondering if it's possible to run multiple versions of an app on my Mac.
I'm pretty sure a virtual machine would work but if I wanted to run 100 instances of that specific app then id run all out of ram and would render my Mac useless for actual work.
The LaunchServices (Finder, NSWorkspace APIs, etc.) on MacOS allow you run one app per user session. Nothing prevents you from launching an app a second time when you don't use Launch Services. (And your assumption is correct that LaunchServices looks at the BundleID to see if the app is already running).
e.g. when you open two Terminal windows and start Mail via (/Applications/Mail.app/Contents/MacOS/Mail) in both you have two Mail instances. open /Applications/Mail.app/ won't work two times because it'll use LaunchServices.

How to distribute an update for an nw.js app

With the forthcoming demise of Chrome Web Store Apps, I have successfully transitioned my app to nw.js I was amazed at how easy it was and how it ran first time. About the only tricky thing I encountered was how to get my app icon showing on mac.
However I am somewhat worried about app updates. Does anyone know what happens to persistent data (indexed-DB etc) when a user updates a nw.js app with a new version that I publish to my web site for download?
Also if anyone can help me with how to achieve automatic updates. I mean the full works here. What code is needed to check for an update, what code do I need to write to deliver the update, what code is needed to install the update. Chrome did all of this for me and I know absolutely nothing about server side coding.
For mac there is a mac store support:
http://docs.nwjs.io/en/latest/For%20Users/Advanced/Support%20for%20Mac%20App%20Store/
IndexedDb, localstorage, etc. will persists until the app name will not change.
For automatic updates:
There is an ongoing pull request going on for auto updater.
https://github.com/nwjs/nw.js/pull/5722
Till then, the easiest way for auto update Your application code is to host your app code on the web and open the web page with nw.js.
If You want to autoupdate the nw.js itself then you will have to provide an installer for that and tell the user to download and run the installer if there is a new update.
The documentation (http://docs.nwjs.io/en/latest/For%20Users/Advanced/Autoupdates/#autoupdates) recommends node-webkit-updater and nwjs-autoupdater. Wherein node-webkit-updater the oldest solution, which is not maintained anymore. It's also has flaws (e.g. unpack via unsigned unzip and system specific apps)
As for the second one (nwjs-autoupdater), I personally do not like the idea to install golang just to have my NWJS app autoupdate...
As an alternative one can consider https://github.com/dsheiko/nw-autoupdater
It provides an API (like node-webkit-updater, but cleaner with use of async/await) to customize auto-update flow in one's app including download/install progress

How do I monitor processes/apps or file locks on Mac OSX?

I'm porting a file encryption app from Windows to Mac OSX. One of its features, is that it lets you open an encrypted file in its source application (say TextEdit), make some changes and then re-rencrypt the file.
To accomplish this on OSX, I would like to either monitor the start/stop of the process that is launched when I ask the system to open my decrypted document, or monitor the file itself for any acquired and released locks.
Is there a way to programatically accomplish this, either through existing OSX or Unix APIs? I've already tried the .NET provided APIs (FileSystemWatcher, Process) without luck.
What I wound up doing, was to listen to Notifications from NSNotificationCenter and NSApplication after I had asked the OS to open my file in its default Application. The particular events were:
NSWorkspace.Notifications.ObserveDidLaunchApplication(EventHandler)
NSWorkspace.Notifications.ObserveDidTerminateApplication(EventHandler)
If you're stuck with the same issue, please see my implementation here.

Creating a "Uninstaller" for a program on Mac OS

I have a requirement to create a cross platform application that launches a web link to a feedback form when its uninstalled.
This is obviously normal sort of behaviour on windows..., but on a Mac is is proving to be more complicated as applications are not technically installed and uninstalled in a windows sense, aka you just copy the .app file into Applications and delete it when you're finished.
How can I achieve this website launching requirement? (Should I even be trying, is this process too alien to Mac users?)
I tired packing the application with an uninstall shell script that deletes the app and lunches the site, but obviously the script can't delete itself.
I don't think this is the best idea, since the process would be a bit unusual to OS X users. As you noted, most applications are installed simply by dragging a .app file to /Applications (or some other location). Some apps do have an installer, but even apps with an installer only occasionally have an uninstaller; and furthermore, as a Mac user, I'd be immediately suspicious of an app that installed itself and some sort of unknown shell script.
Mac OS applications should not need to be uninstalled in any way other than the user dragging them into the trash.
Also, I would rethink very carefully your plan to make a cross-platform applications. Cross-platform applications that treat Mac OS as an afterthought and try to push foreign paradigms onto Mac OS are really irritating. If you want a Mac client, keep your backend code, but rewrite the front-end from scratch. Don't use something like Qt, no matter how tempting the portability is.
So, long story short, you're right. The process is alien to Mac users (except for things like plugins). So my suggestion is just to go with the normal Mac OS behavior (drag to trash). Best of luck!
I would recommend against it. You could create an uninstaller but nothing is going to stop a user from just deleting it from the application folder or using something like AppZapper. Most people don't even look for an uninstaller application, they just trash the app, so even if you wrote one there would be no guarantee it'll be used.
I'd certainly avoid an uninstaller shell script, no way in the world I'd personally run it.
An uninstaller on a Mac makes no sense and would be awkward to implement, if you could even implement it at all in a way where people would use it.
Consider trying to get user feedback using alternate methods, such as:
Add a menu item that opens the feedback form
Require registration when the software is downloaded, then send an email to the user at some point in the future to ask for feedback
Ask for feedback occasionally on application quit (could be annoying, though)
I don't think that it's a good idea to ask for a feedback when the app is uninstalled. However, here is a good way to provide an uninstaller for a MACOS app in case it needs to do some clean up.

Can I hide a directory/path from Launch Services?

I would like to be able to build test applications (e.g. the nightly Minefield/Firefox) without Launch Services deciding that they're the best way to open their assigned file types.
Is there a way to hide my ~/src directory from Launch Services, so that Finder won't register applications in that folder?
I don't know of a way to do that hiding, but you can change the bundle ID of your development apps so that they don't get treated as the preferred app for that content type/URI scheme by LaunchServices.
and for Firefox specifically, the answer is: if OS X finds multiple applications that can handle an URL scheme, it will use the app with the highest version number. So, to fake out OS X, you can edit mozilla-central/browser/app/macbuild/Contents/Info.plist.in, and change the CFBundleShortVersionString from
<string>%APP_VERSION%</string>
to
<string>0.%APP_VERSION%</string>
This way, OS X will think the app is, say, version 0.3.2apre1, and it'll prefer the "real" version of Firefox.
A more general solution might be possible. OS X will prefer apps on a local volume to apps on a remote volume, and among local apps, it'll prefer those on the boot volume. So it might be possible to do some type of loopback mount, and keep your source code on a looped-back "volume", which again will lower its priority.
How OS X decides which app to launch for a given document or URL:
Launch Services Programming Guide: Preferred Applications

Resources