Creating Growl Notifications From A MacRuby App

I’ve been wanting an excuse to learn how to code for OSX for a while now, and I finally thought of a project worth trying. In an effort to get up and running on XCode and Cocoa as quickly as possible, a number of people suggested I check out MacRuby. I have to say, I’m quite happy with it so far. I was able to find some simple tutorials to get me moving and started putting together some simple native OSX UIs pretty quickly, with UI elements that actually do things.

One of the goals of the app that I want to build is to show Growl notifications at various times, so I started digging into what this would take. I found a few tutorials, various forums and even a few bug tickets that generally gave me the information I needed, but I had to put it all together myself. So, in an effort to help the community a little more, I am going to try and post a complete tutorial on creating a MacRuby app with Growl notifications.

 

Getting Started – Xcode And The Growl Frameworks

First, you need a Mac and you need to install the latest and greatest Xcode. Start up Xcode and create a new MacRuby project. Give it a name and save it somewhere. Next, you’ll need the Growl frameworks. Xcode comes with several examples of how to work with Growl, but I found them all to be difficult and couldn’t get them working correctly. A few google searches later and I realized Growl delivers a nice framework package from their website.

Go download the Growl SDK from the Growl website. Open the disk image, and in the Frameworks folder, copy both the “Growl.framework” and “Growl-WithInstaller.framework”. Paste these into /Library/Frameworks on your OSX drive. This will make them easier to find from within Xcode.

Screen shot 2011-01-20 at 10.34.42 PM.png

 

Adding The Growl Framework To Your Project

Open Xcode and your project, and locate Frameworks in the project tree view. Pick one of the framework groups (I chose “Other” for no apparent reason), right click and “Add Existing Framework”. If you got copied the growl frameworks into the right folder, they will show up in the list. Otherwise you’ll have to hunt for them with the “Add Other” button.

Screen shot 2011-01-20 at 10.36.07 PM.png

Your projet now references Growl, but it won’t be able to find it at run time. We have to tell the project to copy the framework to the output folder so it can be found at runtime. Find the Targets node in the project treeview, and find your app’s name. Expand that portion of the tree and you will see several build phase. If you have an empty “Copy Files” step, great! If not, you need to right click your app name and “Add” a “New Build Phase” to “Copy Files”. If the Copy Files phase doesn’t open an “Info” screen, double click on it to open it. In this screen, set the “Destination” to “Frameworks” and leave the “Path” blank.

Screen shot 2011-01-20 at 10.42.22 PM.png

Close this window.

Now drag the Growl.framework from the “Frameworks/Other Frameworks” tree node, down into the “Copy Files” node that you just added. This will tell Xcode to copy the Growl.framework into your project’s output when it builds.

Screen shot 2011-01-20 at 10.46.59 PM.png

 

Configuration Growl To Know About Your App

You can’t just send things to Growl and expect it to magically work. You have to configure your app to use Growl and let Growl know what your app wants to do with it – what notifications you want to set up, what you want on by default, etc. There are several ways to configure your app to work with Growl. I chose to use a .growlRegDict file – a Growl Registration Dictionary. It’s an XML file that defines your app in a manner that Growl understands. You could use code to do the registration as well. There are a lot of examples for doing this online.

Start by adding a filed called “Growl Registration Ticket.growlRegDict” to your project. I chose to put this in my Resources folder. I’m not sure if the file must be named this, exactly, but I am fairly certain it has to have the .growlRegDict extension.  Once you have the file in place, place the following XML in it:

<?xml version=”1.0″ encoding=”UTF-8″?>

<!DOCTYPE plist PUBLIC “-//Apple Computer//DTD PLIST 1.0//EN” “http://www.apple.com/DTDs/PropertyList-1.0.dtd”>

<plist version=”1.0″>

<dict>

<key>TicketVersion</key>

<integer>1</integer>

<key>AllNotifications</key>

<array>

<string>Test</string>

</array>

<key>DefaultNotifications</key>

<array>

<string>Test</string>

</array>

</dict>

</plist>

I’ll let you read all of the documentation on the settings you can supply here. The basics of what you need to know, though, is the “AllNotifications” and “DefaultNotifications” list. Under all notifications, you must supply the names of every notification type your app will send. If you send anything that is not in this list, Growl will ignore it. Under default notifications, you need to tell Growl which of the notification types to enable, by default.

Next, drag the .growlRegDict file from Resources down into “Targets/(project)/Copy Bundle Resources”.

Screen shot 2011-01-20 at 10.57.36 PM.png

This will copy the resource so that the Growl Application Bridge will be able to find it at runtime.

 

Configuring Your App To Use Growl

From what I have read, a standard Xcode app will have various application delegates set up. I’m still not entirely sure how to describe these, other than they are classes that meet specific API needs and provide callback methods for various parts of your app. Perhaps the closest thing I can think of from my .NET days is the Event system, which does use delegates under the hood. However, there is a significant difference between a .NET delegate and an XCode/OSX delegate.

If you do not have an app delegate set up, you need to create one for two purposes:

  • To register your app with Growl, at startup
  • To use Growl callbacks for various events

Add a new ruby document to your project. I called it “ApplicationDelegate.rb” and placed it in the Classes folder of my project:

Screen shot 2011-01-20 at 11.07.05 PM.png

In this file, define a ruby class called ApplicationDelegate (though the name doesn’t matter that much at this point) and put the following code in it:

framework "Growl"

class ApplicationDelegate

  def awakeFromNib()
    GrowlApplicationBridge.setGrowlDelegate(self)
  end

end

This code will tell Growl that your application is going to be sending notifications, once we have told the system that this class is an application delegate. To do that,open the Interface Builder by double clicking “MainMenu.xib” in the “Resources” folder of your project. Open the Library window by pressing “shift-cmd-L” (or however you want to get it open) and find an Object. Drag an Object over to your MainMenu.xib window, and drop it there. This adds an object that we can wire up to our UI.

Screen shot 2011-01-20 at 11.13.07 PM.png

Double click on the Object you just created to open the Info dialog. Set the “Class Identity” to your ApplicationController class.

Screen shot 2011-01-20 at 11.17.36 PM.png

Then hold down control on your keyboard and click-and-drag from “File’s Owner” down to the “Object” that you just added.

Screen shot 2011-01-20 at 11.18.49 PM.png

Let go of the mouse button and select “Delegate” from the resulting dialog. This will wire up your ApplicationDelegate so that the “awakeFromNib” method will fire when your app starts up, which will then register your app with Growl.

 

Make Your App Growl

Now for the fun part… we get to make the app Growl! At a very basic level, it’s easy. All you need to do is call the “GrowlApplicationBridge.notifyWithTitle” method. Somewhere in your app, you need to have some code that calls this method. To start with, you can put it directly into your awakeFromNib method in your Application Delegate class. This will fire off a Growl notification as soon as your app starts up.

def awakeFromNib()
  GrowlApplicationBridge.setGrowlDelegate(self)

  GrowlApplicationBridge.notifyWithTitle("Our Growling Title",
    description: "this is a really big description of really cool things! now you can take over the world with Growl from MacRuby!",
    notificationName: "Test",
    iconData: nil,
    priority: 0,
    isSticky: false,
    clickContext: nil)
end

You can read all the documentation on what these options do. For the most part, though, you need to pay attention to the first parameter and the “description” and “notificationName” in the hash.

The first parameter is the title of the notification. The remaining parameters are all technically a ruby hash using the succinct “key: value” syntax. The “description” is the large text body of the notification that is being sent. The “notificationName” is very important – it’s the name of the notification type that you are sending, and it must be one of the types that you set up in your “Growl Registration Ticket.growlRegDict” file. If you don’t use one that was set up in that file, Growl will ignore the notification.

Assuming my instructions are good, you should be able to run the app from Xcode and see a Growl notification!

Screen shot 2011-01-20 at 11.31.58 PM.png

That wasn’t too bad, was it?

 

And There’s So Much More

I’ve only just started learning MacRuby, XCode, Cocoa, Growl and all the things related to all of this. I know there’s so much more that I’ll be picking up on in the next few weeks while I’m trying to put together my little app. I’ll try to keep posting walk throughs like this, to help out those who would like to learn a little more.

As a preview of what else I’ve learned, though, you can set up a callback from a Growl notification so that when you click on the notification a chunk of code in your app will be executed. This opens up nearly limitless possibilities of what you can do with a Growl notification – launch a web page, launch another app, move your app into a specific feature, and more!

I’ll show you how to set up the click callback delegate in my next post.

 

Resources

Here are some of the resources I used when figuring this out


Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Derick Bailey

Derick Bailey is an entrepreneur, problem solver (and creator? :P ), software developer, screecaster, writer, blogger, speaker and technology leader in central Texas (north of Austin). He runs SignalLeaf.com - the amazingly awesome podcast audio hosting service that everyone should be using, and WatchMeCode.net where he throws down the JavaScript gauntlets to get you up to speed. He has been a professional software developer since the late 90's, and has been writing code since the late 80's. Find me on twitter: @derickbailey, @mutedsolutions, @backbonejsclass Find me on the web: SignalLeaf, WatchMeCode, Kendo UI blog, MarionetteJS, My Github profile, On Google+.
This entry was posted in Growl, MacRuby, OSX, Ruby, Xcode. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://novemberkilo.com Navin

    Thanks for this!

    FYI – I implemented a very low tech way of getting a ruby program to put out growl notifications by using the command line tool ‘growlnotify’ and have a small writeup here:

    http://novemberkilo.com/2010/05/Flickr-notifier/

    Of course this requires that the user has Growl’s command line tools installed – on the other hand, following what you have described here and integrating an app with the Growl framework makes all this config stuff go away (resulting in a much more usable app). Time I did this myself!

  • https://github.com/ashchan/gmail-notifr James Chen

    Cool. I followed your great instructions and replaced the ruby growl.rb with the official framework for Gmail Notifr. Thanks.

  • http://www.lostechies.com/members/derick.bailey/default.aspx derick.bailey

    Navin – :) glad it was useful!

    James – nice! I’ve been looking for an app to do exactly what gmail notifr does, for a while now. definitely going to check this out. :)