Detect and receive notification of more iOS accessibility features

Adds following methods for detecting iOS accessibility features:
MobileAccessibility.isGuidedAccessEnabled()
MobileAccessibility.isInvertColorsEnabled()
MobileAccessibility.isGuidedAccessEnabled()
MobileAccessibility.isInvertColorsEnabled()
MobileAccessibility.isMonoAudioEnabled()

Adds corresponding window events to subscribe to notifications of
accessibility feature status updates:
“guidedaccessstatusdidchange”,
"invertcolorsstatusdidchange”,
"monoaudiostatusdidchange"

Adds following method for posting a notification as a string to be
announced by VoiceOver:
MobileAccessibility.postAnnouncementNotification()
This commit is contained in:
Michael Jordan
2014-01-17 16:48:22 -05:00
parent 97dd76c7df
commit 2643674b7f
3 changed files with 262 additions and 37 deletions
+16
View File
@@ -21,12 +21,28 @@
@interface CDVMobileAccessibility : CDVPlugin {
NSString* callbackId;
NSString* commandCallbackId;
BOOL voiceOverRunning;
BOOL closeCaptioningEnabled;
BOOL guidedAccessEnabled;
BOOL invertColorsEnabled;
BOOL monoAudioEnabled;
}
@property (strong) NSString* callbackId;
@property (strong) NSString* commandCallbackId;
@property BOOL voiceOverRunning;
@property BOOL closeCaptioningEnabled;
@property BOOL guidedAccessEnabled;
@property BOOL invertColorsEnabled;
@property BOOL monoAudioEnabled;
- (void) isVoiceOverRunning:(CDVInvokedUrlCommand*)command;
- (void) isClosedCaptioningEnabled:(CDVInvokedUrlCommand*)command;
- (void) isGuidedAccessEnabled:(CDVInvokedUrlCommand*)command;
- (void) isInvertColorsEnabled:(CDVInvokedUrlCommand*)command;
- (void) isMonoAudioEnabled:(CDVInvokedUrlCommand*)command;
- (void) postAnnouncementNotification:(CDVInvokedUrlCommand*)command;
- (void) start:(CDVInvokedUrlCommand*)command;
- (void) stop:(CDVInvokedUrlCommand*)command;
+160 -25
View File
@@ -19,6 +19,7 @@
#import "CDVMobileAccessibility.h"
#import <Cordova/CDVAvailability.h>
#import <MediaAccessibility/MediaAccessibility.h>
@interface CDVMobileAccessibility ()
// add any property overrides
@@ -27,6 +28,12 @@
@implementation CDVMobileAccessibility
@synthesize callbackId;
@synthesize commandCallbackId;
@synthesize voiceOverRunning;
@synthesize closeCaptioningEnabled;
@synthesize guidedAccessEnabled;
@synthesize invertColorsEnabled;
@synthesize monoAudioEnabled;
// //////////////////////////////////////////////////
@@ -45,6 +52,8 @@
if ([self settingForKey:setting]) {
// set your setting, other init here
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onPause) name:UIApplicationDidEnterBackgroundNotification object:nil];
}
// //////////////////////////////////////////////////
@@ -52,6 +61,9 @@
- (void)dealloc
{
[self stop:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];
}
- (void)onReset
@@ -59,24 +71,126 @@
[self stop:nil];
}
- (void) onPause {
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onResume) name:UIApplicationWillEnterForegroundNotification object:nil];
}
- (void)onResume
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onPause) name:UIApplicationDidEnterBackgroundNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onApplicationDidBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];
}
- (void)onApplicationDidBecomeActive
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];
[self performSelector:@selector(sendMobileAccessibilityStatusChangedCallback) withObject:nil afterDelay:0.1 ];
}
// //////////////////////////////////////////////////
#pragma Plugin interface
- (void)isVoiceOverRunning:(CDVInvokedUrlCommand*)command
{
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:UIAccessibilityIsVoiceOverRunning()];
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
[self.commandDelegate runInBackground:^{
self.voiceOverRunning = UIAccessibilityIsVoiceOverRunning();
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:self.voiceOverRunning];
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
}];
}
- (void)isClosedCaptioningEnabled:(CDVInvokedUrlCommand*)command
{
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:UIAccessibilityIsClosedCaptioningEnabled()];
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
[self.commandDelegate runInBackground:^{
self.closeCaptioningEnabled = [self getClosedCaptioningEnabledStatus];
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:self.closeCaptioningEnabled];
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
}];
}
- (void)isGuidedAccessEnabled:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate runInBackground:^{
self.guidedAccessEnabled = UIAccessibilityIsGuidedAccessEnabled();
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:self.guidedAccessEnabled];
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
}];
}
- (void)isInvertColorsEnabled:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate runInBackground:^{
self.invertColorsEnabled = UIAccessibilityIsInvertColorsEnabled();
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:self.invertColorsEnabled];
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
}];
}
- (void)isMonoAudioEnabled:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate runInBackground:^{
self.monoAudioEnabled = UIAccessibilityIsMonoAudioEnabled();
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:self.monoAudioEnabled];
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
}];
}
- (void)postAnnouncementNotification:(CDVInvokedUrlCommand *)command
{
CDVPluginResult* result = nil;
NSString* notificationString = [command.arguments objectAtIndex:0];
if (UIAccessibilityIsVoiceOverRunning() &&
notificationString != nil && [notificationString length] > 0) {
self.commandCallbackId = command.callbackId;
[self.commandDelegate runInBackground:^{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mobileAccessibilityAnnouncementDidFinish:) name:UIAccessibilityAnnouncementDidFinishNotification object:nil];
UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, notificationString);
}];
} else {
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR];
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
}
}
- (void)mobileAccessibilityAnnouncementDidFinish:(NSNotification *)dict
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityAnnouncementDidFinishNotification object:nil];
NSString* valueSpoken = [[dict userInfo] objectForKey:UIAccessibilityAnnouncementKeyStringValue];
NSString* wasSuccessful = [[dict userInfo] objectForKey:UIAccessibilityAnnouncementKeyWasSuccessful];
NSMutableDictionary* data = [NSMutableDictionary dictionaryWithCapacity:2];
[data setObject:valueSpoken forKey:@"stringValue"];
[data setObject:wasSuccessful forKey:@"wasSuccessful"];
if (self.commandCallbackId) {
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:data];
[self.commandDelegate sendPluginResult:result callbackId:self.commandCallbackId];
self.commandCallbackId = nil;
}
}
- (BOOL)getClosedCaptioningEnabledStatus
{
BOOL status = false;
if (&MACaptionAppearanceGetDisplayType) {
status = (MACaptionAppearanceGetDisplayType(kMACaptionAppearanceDomainUser) > kMACaptionAppearanceDisplayTypeAutomatic);
} else {
status = UIAccessibilityIsClosedCaptioningEnabled();
}
return status;
}
- (void)mobileAccessibilityStatusChanged:(NSNotification *)notification
{
[self sendMobileAccessibilityStatusChangedCallback];
}
- (void)sendMobileAccessibilityStatusChangedCallback
{
if (self.callbackId) {
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[self getMobileAccessibilityStatus]];
@@ -88,38 +202,59 @@
/* Get the current mobile accessibility status. */
- (NSDictionary*)getMobileAccessibilityStatus
{
NSMutableDictionary* mobileAccessibilityData = [NSMutableDictionary dictionaryWithCapacity:2];
[mobileAccessibilityData setObject:[NSNumber numberWithBool:UIAccessibilityIsVoiceOverRunning()] forKey:@"isVoiceOverRunning"];
[mobileAccessibilityData setObject:[NSNumber numberWithBool:UIAccessibilityIsClosedCaptioningEnabled()] forKey:@"isClosedCaptioningEnabled"];
self.voiceOverRunning = UIAccessibilityIsVoiceOverRunning();
self.closeCaptioningEnabled = [self getClosedCaptioningEnabledStatus];
self.guidedAccessEnabled = UIAccessibilityIsGuidedAccessEnabled();
self.invertColorsEnabled = UIAccessibilityIsInvertColorsEnabled();
self.monoAudioEnabled = UIAccessibilityIsMonoAudioEnabled();
NSMutableDictionary* mobileAccessibilityData = [NSMutableDictionary dictionaryWithCapacity:5];
[mobileAccessibilityData setObject:[NSNumber numberWithBool:self.voiceOverRunning] forKey:@"isVoiceOverRunning"];
[mobileAccessibilityData setObject:[NSNumber numberWithBool:self.closeCaptioningEnabled] forKey:@"isClosedCaptioningEnabled"];
[mobileAccessibilityData setObject:[NSNumber numberWithBool:self.guidedAccessEnabled] forKey:@"isGuidedAccessEnabled"];
[mobileAccessibilityData setObject:[NSNumber numberWithBool:self.invertColorsEnabled] forKey:@"isInvertColorsEnabled"];
[mobileAccessibilityData setObject:[NSNumber numberWithBool:self.monoAudioEnabled] forKey:@"isMonoAudioEnabled"];
return mobileAccessibilityData;
}
/* turn on MobileAccessibility monitoring*/
/* start MobileAccessibility monitoring */
- (void)start:(CDVInvokedUrlCommand*)command
{
self.callbackId = command.callbackId;
[self.commandDelegate runInBackground:^{
self.callbackId = command.callbackId;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mobileAccessibilityStatusChanged:) name:UIAccessibilityVoiceOverStatusChanged object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mobileAccessibilityStatusChanged:) name:UIAccessibilityClosedCaptioningStatusDidChangeNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mobileAccessibilityStatusChanged:) name:UIAccessibilityGuidedAccessStatusDidChangeNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mobileAccessibilityStatusChanged:) name:UIAccessibilityInvertColorsStatusDidChangeNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mobileAccessibilityStatusChanged:) name:UIAccessibilityMonoAudioStatusDidChangeNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mobileAccessibilityStatusChanged:)
name:UIAccessibilityVoiceOverStatusChanged object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mobileAccessibilityStatusChanged:)
name:UIAccessibilityClosedCaptioningStatusDidChangeNotification object:nil];
// Update the callback on start
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[self getMobileAccessibilityStatus]];
[result setKeepCallbackAsBool:YES];
[self.commandDelegate sendPluginResult:result callbackId:self.callbackId];
}];
}
/* stop MobileAccessibility monitoring */
- (void)stop:(CDVInvokedUrlCommand*)command
{
// callback one last time to clear the callback function on JS side
if (self.callbackId)
{
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[self getMobileAccessibilityStatus]];
[result setKeepCallbackAsBool:NO];
[self.commandDelegate sendPluginResult:result callbackId:self.callbackId];
}
self.callbackId = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIAccessibilityVoiceOverStatusChanged object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIAccessibilityClosedCaptioningStatusDidChangeNotification object:nil];
[self.commandDelegate runInBackground:^{
// callback one last time to clear the callback function on JS side
if (self.callbackId)
{
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[self getMobileAccessibilityStatus]];
[result setKeepCallbackAsBool:NO];
[self.commandDelegate sendPluginResult:result callbackId:self.callbackId];
}
self.callbackId = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityVoiceOverStatusChanged object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityClosedCaptioningStatusDidChangeNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityGuidedAccessStatusDidChangeNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityInvertColorsStatusDidChangeNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityAnnouncementDidFinishNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityMonoAudioStatusDidChangeNotification object:nil];
}];
}
@end