この記事は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形式のファイルを配置するようにした。
VOYAGE GROUPではグループウェアにサイボウズガルーン3を使っている。このサイボウズガルーン3、不便な事にMac用のリマインダークライアントが提供されていない。そこで、ミーティングをすっぽかさないためにもMacユーザーはリマインダーを各自実装する必要がある。
私はAPIを叩いて結果をGrowl通知させていたが、OSアップデートでこれが動かなくなった。単にGrowlをインストールするのを忘れていただけだが、通知センターがOSに追加されたのでGrowlはもう不要な気がする。
というわけで、通知センターでガルーンのスケジュール通知を受けられるようにしてみよう。私はObjective-Cが全く書けないので、ガルーンのAPIを叩く所はとりあえず現状のを使いまわして、JSON形式のファイルを配置するようにした。
通知センターに通知を送る
通知センターを使うのに一番手っ取り速いのは多分Cocoaなので、Xcodeでそれっぽいコードを書く。NSUserNotificationとNSUserNotificationCenterを使えば良い。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// AppDelegate.h | |
#import <Cocoa/Cocoa.h> | |
@interface AppDelegate : NSObject <NSApplicationDelegate, NSUserNotificationCenterDelegate> | |
// Windowはいらないのでxibファイルから消しておく | |
@property (assign) IBOutlet NSWindow *window; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 |
通知を表示するだけなら通知を送った後にアプリケーションを終了さても良いが、通知をクリックした時に任意の操作をしたい場合はアプリケーションを生かしておく必要がある。ガルーンAPIを叩く部分のCocoa移植は後にして、とりあえず動くようになった。めでたしめでたし。
という訳で、せっかくエンジニアをやっているので、日々ハックできる所はハックしていきたいですね。
という訳で、せっかくエンジニアをやっているので、日々ハックできる所はハックしていきたいですね。
次は@pank7さんです。