Google Mobile’s Private API Use
I’ve not had a chance to actually put together a test app for this yet, but having read John Gruber’s piece on the use of a private API within Google’s much-reported new iPhone application, I felt an urge to put my oar in here. My experiences with iPhone programming and Apple’s private APIs ought to count for something, after all.
The article lays out evidence that Google is implementing an undocumented UIApplication delegate call, proximityStateChanged. Upon first reading what the end function was, however, I assumed that it had been written to check the value of -[UIApplication isIgnoringInteractionEvents]. At first, my dim memory suggested that this could be done using Key-Value Observation, registering an observer of the ‘isIgnoringInteractionEvents’ or maybe just ‘ignoringInteractionEvents’ key paths on the UIApplication instance. However, a glance at the header file would suggest that this isn’t just a KVO-compliant variable; it seems to be a calculated property based on other internal states.
Thinking about the problem a little more, however, and I believe I could have a public-API implementation. According to the article linked above, it would seem that the application is checking only for proximity state changes following some spatial movement of the phone1. This means that the following might well provide the same details:
- Receive movement notification.
- Note state of
[[UIApplication sharedApplication] isIgnoringInteractionEvents]. - Set a timer with a one-second (or similar) duration.
- When the timer fires, check the state of
-isIgnoringInteractionEventsagain and compare against the earlier result.
Assuming that your accelerometer code simply calls a single function to note the beginning of a possible bring-to-ear movement, the code would look something like this:
- (void) potentialMoveToEarStarting
{
self.startingInteractionState = [[UIApplication sharedApplication] isIgnoringInteractionEvents];
[NSTimer scheduledTimerWithTimeInterval: 0.7
target: self
selector: @selector(moveToEarCheck)
userInfo: nil
repeats: NO];
}
- (void) moveToEarCheck
{
BOOL isIgnoring = [[UIApplication sharedApplication] isIgnoringInteractionEvents];
// if the value hasn't changed, we're not interested
if ( isIgnoring == self.startingInteractionState )
return;
if ( isIgnoring )
[self activateMicrophone];
else
[self deactivateMicrophone];
}
That example is fairly simplistic (the accelerometer code would need to be more involved than a simple ‘movement started’ callback) but I have a hard time believing that this was a problem so difficult that it couldn’t be implemented with the published APIs.
-
John has a footnote mentioning that Google couldn’t implement both bring-to-ear handling and standard UI rotation. This is a limitation of the API itself: requesting low-level accelerometer data means that the UIApplication instance won’t be getting it any more, and so you’d have to detect and implement your own UI rotation code. ↩
No Responses