分散通知をリッスンする SpringBoard フックがあります。SpringBoard で受信したポスト通知をフックした他のさまざまなアプリ。
userInfo を null として渡すと、SpringBoard はすべてのアプリから通知を受け取ります。CFDictionaryRef を userInfo として渡すと、SpringBoard は SpringBoard と SystemApps からのみ通知を受け取ります。ただし、ユーザー アプリは通知を送信できません。(というか、Springboard によって受信されません)。
CFDictionaryRef は無実であり、犯人ではありません。送信者と受信者がシステム アプリである場合に渡すことができるからです。
User Apps が userInfo オブジェクトを System Apps に送信できないという制限はありますか?
編集: コードを添付します。iOSOpenDev を使用してコンパイルします。NSLog に依存してデバッグします。 シナリオ 1: SpringBoard に触れると、通知送信と通知受信の 2 つのログが表示されます。 シナリオ 2:時計などのシステム アプリを呼び出すと、両方のログが表示されます。 シナリオ 3: SketchBookX などのアプリ ストアからの任意のアプリで、通知送信用に 1 つのログのみが出力されます。受け取っていません。
CFNotificationCenterPostNotification のすべてのフレーバーを試しましたが、何も機能しません。
#import <UIKit/UIKit.h>
#include <CoreFoundation/CoreFoundation.h>
#include <CoreFoundation/CFNotificationCenter.h>
#include "GraphicsServices/GSEvent.h"
#define GS_EVENT_TYPE_OFFSET 2
#define HOME_DOWN 1000
#define HOME_UP 1001
#define VOL_DOWN_KEY_DOWN 1008
#define VOL_DOWN_KEY_UP 1009
extern "C" CFNotificationCenterRef CFNotificationCenterGetDistributedCenter(void);
void LogEvent(CFNotificationCenterRef center,
void *observer,
CFStringRef name,
const void *object,
CFDictionaryRef userInfo)
{
NSString *str = [[NSString alloc]initWithFormat:@"%@,%@,%d,%d,%d,%d,%d\r\n",
(NSString*)CFDictionaryGetValue(userInfo,@"strWindow"),
(NSString*)CFDictionaryGetValue(userInfo,@"strView"),
[(NSNumber*)CFDictionaryGetValue(userInfo,@"phase") intValue],
[(NSNumber*)CFDictionaryGetValue(userInfo,@"xInView") intValue],
[(NSNumber*)CFDictionaryGetValue(userInfo,@"yInView") intValue],
[(NSNumber*)CFDictionaryGetValue(userInfo,@"xInWindow") intValue],
[(NSNumber*)CFDictionaryGetValue(userInfo,@"yInWindow") intValue]];
NSLog(@"Area51 Notification Received: %@",str);
}
%hook UIApplication
-(void) sendEvent:(UIEvent*)event
{
if( [NSStringFromClass([event class]) isEqualToString:@"UITouchesEvent"] )
{
NSSet *touches = [event allTouches];
NSEnumerator *enumerator = [touches objectEnumerator];
id value;
while ((value = [enumerator nextObject])) {
UITouch *touch = value;
NSString *strViewClassName;
if(!touch.view)
strViewClassName = @" ";
else
strViewClassName = [NSString stringWithString:NSStringFromClass([[touch view] class])];
CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(NULL,0,&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionaryAddValue(dictionary, @"phase", [NSNumber numberWithInt:[touch phase]] );
CFDictionaryAddValue(dictionary, @"strWindow", NSStringFromClass([[touch window] class]) );
CFDictionaryAddValue(dictionary, @"strView", strViewClassName);
CFDictionaryAddValue(dictionary, @"xInView", [NSNumber numberWithInt:[touch locationInView:touch.view].x]) ;
CFDictionaryAddValue(dictionary, @"yInView", [NSNumber numberWithInt:[touch locationInView:touch.view].y]) ;
CFDictionaryAddValue(dictionary, @"xInWindow", [NSNumber numberWithInt:[touch locationInView:nil].x]) ;
CFDictionaryAddValue(dictionary, @"yInWindow", [NSNumber numberWithInt:[touch locationInView:nil].y]) ;
CFNotificationCenterPostNotificationWithOptions(
CFNotificationCenterGetDistributedCenter(),
(CFStringRef)@"RecordTouch",
NULL,
dictionary,
kCFNotificationDeliverImmediately|kCFNotificationPostToAllSessions);
NSLog(@"Area 51: Notification Send for App: %@",[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"] );
}
}
%orig;
}
%end
%hook SpringBoard
-(void)applicationDidFinishLaunching:(UIApplication*) application
{
CFNotificationCenterAddObserver(
CFNotificationCenterGetDistributedCenter(),
NULL,
LogEvent,
NULL,
NULL,
CFNotificationSuspensionBehaviorDeliverImmediately);
NSLog(@"Area51: ObserverAdded");
%orig;
}
%end
__attribute__((constructor)) void area51init() {
%init;
}