ホームページ>開発ツール>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]