ホームページ>開発ツール>Xojo / Real Studio Trial and Error・Cocoaのプラグインで通知センターを利用する
Xojo / Real Studio Trial and Error
目次
Cocoaのプラグインで通知センターを利用する 
はじめに
前回、Declareで通知センターの利用を試みましたが、アプリが最前面にあるとバナー表示されないという問題が残ってしまいました。
そこで、この問題がプラグインでは解消されるのかどうか、確かめてみることにしました。
なお、(理由は後述しますが)今回の検証には、Xojo 2013 Release 2 / Xcode 4.6.3を用いています。(Mac mini + OS X 10.8 Mountain Lion)
Cocoaプラグインを作ってみる
Cocoaのプラグインについては、随分前(手持ちでは、REALbasic 2008には既にある)から説明があり、以前にも試したことがあったのですが、作り方がよく分からず、従って、適当に作ってビルド(当時はXcode 3)してみても、エラーが大量に出たりするので、放置していました。
ですが、今回の実験にあたり、Cocoa対応がより進化しているであろうことを期待して、Xojoの最新版を使って、再度トライしてみることにしました。
作成にあたっては、以前と同じようにテンプレートが使えると便利と思って探してみたのですが、見つかりませんでした。
なので、Xojoフォルダ内の、Extras/Plugin SDK/Examplesフォルダ内を一通り俯瞰したところ、HostedPluginExampleが手頃そうだったのでXcode 4.6.3で開いてみると、エラー表示もなくビルドもできたので、使ってみたら問題なく動きました。よって、これをベースにすることとしました。
まずは、プラグイン作成手順の(再)確認も兼ねて、簡単な処理のテスト版を作ってみました。
結果、文字列を連結したメッセージを含むダイアログが表示されることを確認しました。
- Plugin SDKフォルダを、適当な場所にコピー
 - Examplesフォルダ内のHostedPluginExampleフォルダを複製し、適当な名前(ここでは、NSStringTest)にリネーム
 - HostedPluginExample.xcodeprojをXcode 4.6.3で開く
 - REALExampleLevelIndicator.hとREALExampleLevelIndicator.mmを削除
 - プロジェクト名をNSStringTestにリネーム(やり方は、例えば参考サイト(1)を参照。ただし、フォルダ名の変更の項は不要)
 - HostedPluginExample.cppをNSStringTest.cppにリネーム(ファイル名選択後、もう一度クリックして名前を変更)
 - NSStringTest.cppの中身を全文削除後に、以下をペースト
 
注1)REALCStringとREALRegisterMethodでdeprecatedのWarningが出るが、実験目的であり、とりあえず動作しているので、そのままにしている。#include "rb_plugin.h" static REALstring CatString(REALstring str1, REALstring str2) { const char* cstr1 = REALCString(str1); NSString* nsstr1 = [NSString stringWithCString:cstr1 encoding:NSUTF8StringEncoding]; const char* cstr2 = REALCString(str2); NSString* nsstr2 = [NSString stringWithCString:cstr2 encoding:NSUTF8StringEncoding]; NSString* nsstr3 = [NSString stringWithFormat:@"%@ %@",nsstr1, nsstr2]; const char* cstr3 = [nsstr3 UTF8String]; return REALBuildString(cstr3, ::strlen(cstr3)); } REALmethodDefinition CatStringDefn = { (REALproc) CatString, REALnoImplementation, "CatString(str1 as string, str2 as string) as string" }; void PluginEntry(void) { REALRegisterMethod(&CatStringDefn); }
注2)Cocoa以外のAPIを混在させる場合は、Cocoa部分を#if COCOA〜#endifで囲む。今回はCocoa以外の利用は考えていないので、何もしていない。- ビルド(初回やリネーム後は、先にCleanを実行)
 - DerivedData/NSStringTest/Build/Products/Debug内のlibNSStringTest.dylibを、NSStringTest/Build Resources/Mac Cocoaフォルダにコピー
 
(詳細は、Plugin SDK内のPluginPackaging.rtf、Plugin Converter内のPlugin Converter Read Me.txtを参照)- Plugin Converter.rbpで、プラグイン形式(rbx)に変換
 
(コンソールアプリのライセンスを持っていなくても実行は可能。「-f <フォルダへのパス>」は「共有>Debug>Command Line Arguments」で指定。)- Xojoフォルダ内のPluginsフォルダに、NSStringTest.rbxをコピー
 - Xojoを起動し、新規デスクトップアプリを作成(デフォルトでCocoaになっている筈)
 - PushButtonを配置して、Actionに「MsgBox CatString("Hello","World")」と記述
 - 実行
 
通知センターを使ってみる
早速、前項のサンプルに通知部分を実装してみたのですが、何も表示されませんでした。
どうも、「通知センターを利用するアプリケーションは、バンドル形式でなければならない」ということのようです。
そこで、何か回避方法がないか調べてみたら、以下のサイトがヒットしました。
参考サイト(2):norio-nomura/usernotification - GitHub
これはコマンドラインのアプリケーション用ですが、状況的にはよく似ていて応用できそうだったので、使わせて頂くことにしました。
実行してみたところ、自身が最前面にあっても、バナー表示されることを確認しました。
- 前項で作成したプロジェクトのフォルダを複製し、適当な名前にリネーム(プロジェクト/ファイル名も同様にリネーム)
 - 参考サイト(2)の「usernotification(フォルダアイコン)」をクリックし、「main.m(ファイルアイコン)」をクリック
 - main.mの中身を、前項と同様にcppファイルにペーストして、全文置き換え
 - 先頭部分に以下を追加
 #include "rb_plugin.h"- 「installNSBundleHook()」メソッド内の、変数の方の「class(全部小文字)」を全て(例えば)「class1」に置き換え
 - 「@interface NotificationCenterDelegate : NSObject
 」を以下に変更 @interface NotificationCenterDelegate : NSObject{BOOL keepRunning;} - 「@implementation NotificationCenterDelegate」の下に、以下を追加
 @synthesize keepRunning;- 「- (void)userNotificationCenter:(NSUserNotificationCenter *)center didDeliverNotification:(NSUserNotification *)notification」メソッドの次に、以下を追加
 - (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification { return YES; }- 「int main(int argc, const char * argv[])」を以下に置き換え
 static void SendNotification(REALstring str1, REALstring str2)- 「NSUserNotification *note = [[NSUserNotification alloc] init];」から「whileの閉じ括弧」までを削除
 - 代わりに以下を追加
 const char* cstr1 = REALCString(str1); NSString* nsstr1 = [NSString stringWithCString:cstr1 encoding:NSUTF8StringEncoding]; const char* cstr2 = REALCString(str2); NSString* nsstr2 = [NSString stringWithCString:cstr2 encoding:NSUTF8StringEncoding]; NSUserNotification *notification = [[NSUserNotification alloc] init]; [notification setTitle:nsstr1]; [notification setInformativeText:nsstr2]; [notification setDeliveryDate:[NSDate dateWithTimeInterval:5 sinceDate:[NSDate date]]]; [notification setSoundName:NSUserNotificationDefaultSoundName]; NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter]; [center scheduleNotification:notification];- 「return 0;」を削除
 - 最下段に以下を追加
 REALmethodDefinition SendNotificationDefn = { (REALproc) SendNotification, REALnoImplementation, "SendNotification(str1 as string, str2 as string)" }; void PluginEntry(void) { REALRegisterMethod(&SendNotificationDefn); }- ビルド後、前項の12.迄、同様に処理
 - PushButtonを配置して、Actionに「SendNotification("Hello World","comment from myApp")」と記述
 
考察および留意点
当初の目標であった「アプリが最前面にあってもバナー表示」は、プラグインでは実現可能であることが確認できました。
ただし、「システム環境設定」の「通知」では、実行中以外は表示項目にアプリ名が表示されない、といった問題もあるので、更なる調査/実験は必要と思われます。
(追記:アプリをビルドしておけば問題ありませんでした。)(2013.09.17)
また、バッジ制御は通知センターとは別物のようですが、(時間指定時の)バナー表示とバッジの連携等、まだ不明な点もあり、今後の課題となりそうです。
なお、今回作成したプラグインは、あくまで実験用で、体裁としては十分ではありません。
少なくともdeprecatedは解決し、Xcodeプロジェクト設定の最適化、Releaseへの変更も行うべきでしょう。(場合によってはCarbonへの対応も。)
実用目的で利用する場合は、それらを含めた総合的な対策が必要となります。
お世話になったサイト
貴重な情報をご提供頂いている皆様に、お礼申し上げます。(以下、順不同)
参考サイト(1):Xcode4のプロジェクト名変更方法 : NAGAOKA STATION
参考サイト(2):norio-nomura/usernotification - GitHub
更新履歴
2013.09.17 「考察および留意点」に追記を追加。
2013.09.10 新規作成
[Home] [MacSoft] [Donation] [History] [Privacy Policy] [Affiliate Policy]