2012-12-21

MacOS X Mountain Lionの通知センターを便利に使う

この記事はVOYAGE GROUP エンジニアブログ : Advent Calendar 2012の20日目である。特にテーマは何でも良いそうなので、Mac OS X Mountain Lionで追加された通知センターについて。

VOYAGE GROUPではグループウェアにサイボウズガルーン3を使っている。このサイボウズガルーン3、不便な事にMac用のリマインダークライアントが提供されていない。そこで、ミーティングをすっぽかさないためにもMacユーザーはリマインダーを各自実装する必要がある。
私はAPIを叩いて結果をGrowl通知させていたが、OSアップデートでこれが動かなくなった。単にGrowlをインストールするのを忘れていただけだが、通知センターがOSに追加されたのでGrowlはもう不要な気がする。

というわけで、通知センターでガルーンのスケジュール通知を受けられるようにしてみよう。私はObjective-Cが全く書けないので、ガルーンのAPIを叩く所はとりあえず現状のを使いまわして、JSON形式のファイルを配置するようにした。

通知センターに通知を送る

通知センターを使うのに一番手っ取り速いのは多分Cocoaなので、Xcodeでそれっぽいコードを書く。NSUserNotificationNSUserNotificationCenterを使えば良い。

// AppDelegate.h
#import <Cocoa/Cocoa.h>
@interface AppDelegate : NSObject <NSApplicationDelegate, NSUserNotificationCenterDelegate>
// Windowはいらないのでxibファイルから消しておく
@property (assign) IBOutlet NSWindow *window;
@end
view raw AppDelegate.h hosted with ❤ by GitHub
// AppDelegate.m
#define DATA_FILE_PATH @"/Users/hagino3000/tmp/data.json"
#define CHECK_INTERVAL 20 * 60
#import "AppDelegate.h"
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[NSUserNotificationCenter defaultUserNotificationCenter].delegate = self;
// 初回起動
[self checkSchedule];
// 次回以降はタイマーで起動
[NSTimer scheduledTimerWithTimeInterval:CHECK_INTERVAL
target:self
selector:@selector(checkSchedule)
userInfo:nil
repeats:YES];
}
- (void)checkSchedule {
// ファイルでスケジュールデータを受けとる
NSInputStream* stream = [NSInputStream inputStreamWithFileAtPath:DATA_FILE_PATH];
[stream open];
NSError *error;
NSArray *arr = [NSJSONSerialization JSONObjectWithStream:stream
options:NSJSONReadingMutableContainers
error:&error];
[stream close];
for (int i = 0; i < arr.count; i++) {
NSDictionary *dict = [arr objectAtIndex:i];
[self sendNotification:[dict objectForKey:@"title"]
subtitle:[dict objectForKey:@"time"]
body:[dict objectForKey:@"body"]
url:[dict objectForKey:@"url"]];
}
}
- (void)sendNotification:(NSString *)title subtitle:(NSString *)subtitle body:(NSString *)body url:(NSString *)url {
// UserNotificationの生成
NSUserNotification *userNotification = [[NSUserNotification alloc] init];
userNotification.actionButtonTitle = @"開く";
userNotification.title = title;
userNotification.subtitle = subtitle;
userNotification.informativeText = body;
userNotification.userInfo = [[NSDictionary alloc] initWithObjectsAndKeys:url, @"url", nil];
// 通知センターに送る
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:userNotification];
NSLog(@"done!!");
}
- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification {
// アクションボタンがクリックされたら、スケジュールのページを開く
NSURL *url = [NSURL URLWithString:[notification.userInfo valueForKey:@"url"]];
[[NSWorkspace sharedWorkspace] openURL:url];
}
@end
view raw AppDelegate.m hosted with ❤ by GitHub
通知を表示するだけなら通知を送った後にアプリケーションを終了さても良いが、通知をクリックした時に任意の操作をしたい場合はアプリケーションを生かしておく必要がある。ガルーンAPIを叩く部分のCocoa移植は後にして、とりあえず動くようになった。めでたしめでたし。



という訳で、せっかくエンジニアをやっているので、日々ハックできる所はハックしていきたいですね。


次は@pank7さんです。