iPhone Notifications

iPhone Notifications


Several months ago, I wrote about the iPhone's onboard Core Telephony notification system. That post explored how to catch and respond to iPhone interruptions. After writing that, I remained curious about the standard iPhone notification system. I didn't get far. And this is why: The iPhone relies primarily on Darwin Notifications to communicate between applications.

Listening to notifications isn't hard. Just call CFNotificationCenterAddObserver and add your application as a listener. Unfortunately, unlike standard notification centers, the Darwin forbids eavesdropping. You must specify exactly which notification token you want to listen for.

With that roadblock seemingly insurmountable, I moved onto other projects. This week, I stumbled once again across Daniel "Pumpkin" Peebles who encouraged me to try again. So I did.

What I did was this. I went to /System/Library and ran the strings command on just about every file I could find, particularly the frameworks and Core Services folders. I then grepped through those strings for "^com.apple", the pattern that identifies most inter-application notifications.

I then repeated this for /Applications. Finally, I sorted and uniq'ed my results to create as comprehensive a list as possible of Apple notifications. It took many hours but once I got it automated, it ran pretty quickly.

My list contained quite a number of tokens. These included power notifications (fully charged, etc), sync notifications (sync begun, canceled, etc), and other system events. I was going to look for events using a hammer rather than a paintbrush.

I built the following tool using the open SDK toolchain. In this, I feed notifications into a loop, creating an observer for each notification token type. The source code (omitting the actual notification list) follows below.

The results were gratifying in that they allowed me to listen in to my system in a way I hadn't before. I could sense when apps launched and quit, when the battery charger came on line. I could detect when system notifications appeared on-screen, and more. No, this didn't provide a full or exhaustive view -- the notification list is still a work in progress -- but it was at least a step forward in interacting with the iPhone at a deeper level.

#include <stdio.h>
#include <notify.h>
#include <unistd.h>
#include <stdarg.h>

static void callback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
    fprintf(stderr, "Notification intercepted: %s/n", [name UTF8String]);
    if (userInfo) CFShow(userInfo);
    return;
}

static void signalHandler(int sigraised)
{
    printf("/nInterrupted./n");
    _exit(0);
}

void usage(char *appname)
{
    printf("%s : options /n", appname);
    printf("-s     listen to standard notifications/n");
    printf("-t     listen to core telephony notifications/n");
}

int main(int argc, char **argv)
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    if (argc < 2) {usage(argv[0]); exit(0);}

    NSString *readNotifications = NOTSTRING;
    NSArray *notifications = [readNotifications componentsSeparatedByString:@"BOUNDARY"];

    opterr = 0;
    int c;
    id results;
    BOOL isTelephony = NO;
    BOOL isStandard = NO;

    while ((c = getopt (argc, argv, "ts")) != -1)
     switch (c)
     {
        case 's': 
            isStandard = YES;
             break;
        case 't': 
            isTelephony = YES;
            break;
        case '?':
         if (isprint (optopt))
            fprintf (stderr, "Unknown option `-%c'./n", optopt);
         else
            fprintf (stderr,
            "Unknown option character `//x%x'./n",
            optopt);
         return 1;
        default:
         return 0;
     }

    if ((!isStandard) && (!isTelephony))
    {
        printf("Listen either to standard (-s), telephony (-t) notifications or both/n");
        printf("No notification type selected. Exiting./n");
        exit(-1);
    }

    if (isStandard)
    {
        printf("Watching for Standard Notifications (%d notifications)/n", [notifications count]);

        for (id *notification in notifications)
        {
            CFNotificationCenterAddObserver(
                CFNotificationCenterGetDarwinNotifyCenter(), //center
                NULL, // observer
                callback, // callback
                notification, // name
                NULL, // object
                CFNotificationSuspensionBehaviorHold
             ); 
        }
    }

    if (isTelephony)
    {
        printf("Watching for Core Telephony notifications/n");
        id ct = CTTelephonyCenterGetDefault();
        CTTelephonyCenterAddObserver(
            ct, 
            NULL, 
            callback,
            NULL,
            NULL,
            CFNotificationSuspensionBehaviorHold);
    }

    // Set up a signal handler so we can clean up when we're interrupted from the command line
    sig_t oldHandler = signal(SIGINT, signalHandler);
    if (oldHandler == SIG_ERR) {
        printf("Could not establish new signal handler");
        exit(1);
    }

    // Start the run loop. Now we'll receive notifications.
    printf("Starting Notification Scan. ^C to quit./n");
    CFRunLoopRun();
        
    printf("Unexpectedly back from CFRunLoopRun()!/n");
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值