Adding Android platform

This commit is contained in:
Michael Jordan
2014-02-10 17:28:17 -05:00
parent 7c7e8be5fc
commit ea97c1faa1
9 changed files with 576 additions and 12 deletions

4
.gitignore vendored
View File

@@ -18,3 +18,7 @@ DerivedData
.idea/
.project
src/android/.classpath
src/.gitignore

View File

@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:rim="http://www.blackberry.com/ns/widgets"
xmlns:android="http://schemas.android.com/apk/res/android"
@@ -13,10 +12,12 @@
<engines>
<engine name="cordova" version=">=3.0.0" />
</engines>
<js-module src="www/mobile-accessibility.js" name="mobile-accessibility">
<clobbers target="window.MobileAccessibility" />
</js-module>
<dependency id="org.apache.cordova.device" url="https://git-wip-us.apache.org/repos/asf/cordova-plugin-device.git" />
<!-- ios -->
<platform name="ios">
@@ -32,6 +33,18 @@
<!-- android -->
<platform name="android">
<config-file target="res/xml/config.xml" parent="/*">
<feature name="MobileAccessibility" >
<param name="android-package" value="com.phonegap.plugin.mobileaccessibility.MobileAccessibility"/>
</feature>
<access origin="https://ssl.gstatic.com/accessibility/javascript/android/*" />
</config-file>
<config-file target="assets/www/config.xml" parent="/*">
<feature name="MobileAccessibility" >
<param name="android-package" value="com.phonegap.plugin.mobileaccessibility.MobileAccessibility"/>
</feature>
<access origin="https://ssl.gstatic.com/accessibility/javascript/android/*" />
</config-file>
<source-file src="src/android/com/phonegap/plugin/mobileaccessibility/MobileAccessibility.java" target-dir="src/com/phonegap/plugin/mobileaccessibility" />
</platform>
</plugin>

View File

@@ -0,0 +1,18 @@
package com.phonegap.plugin.mobileaccessibility;
import android.view.ViewParent;
public abstract class AbstractMobileAccessibilityHelper {
protected MobileAccessibility mMobileAccessibility;
protected ViewParent mParent;
public abstract void initialize(MobileAccessibility mobileAccessibility);
public abstract boolean isClosedCaptioningEnabled();
public abstract boolean isScreenReaderRunning();
public abstract boolean isTouchExplorationEnabled();
public abstract void onAccessibilityStateChanged(boolean enabled);
public abstract void onCaptioningEnabledChanged(boolean enabled);
public abstract void onTouchExplorationStateChanged(boolean enabled);
public abstract void addStateChangeListeners();
public abstract void removeStateChangeListeners();
public abstract void announceForAccessibility(CharSequence text);
}

View File

@@ -0,0 +1,80 @@
package com.phonegap.plugin.mobileaccessibility;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.webkit.WebView;
@TargetApi(Build.VERSION_CODES.DONUT)
public class DonutMobileAccessibilityHelper extends
AbstractMobileAccessibilityHelper {
protected AccessibilityManager mAccessibilityManager;
protected WebView mWebView;
@Override
public void initialize(MobileAccessibility mobileAccessibility) {
mMobileAccessibility = mobileAccessibility;
mWebView = mobileAccessibility.webView;
mParent = mobileAccessibility.webView.getParentForAccessibility();
mAccessibilityManager = (AccessibilityManager) mMobileAccessibility.cordova.getActivity().getSystemService(Context.ACCESSIBILITY_SERVICE);
}
@Override
public boolean isClosedCaptioningEnabled() {
return false;
}
@Override
public boolean isScreenReaderRunning() {
return mAccessibilityManager.isEnabled();
}
@Override
public boolean isTouchExplorationEnabled() {
return false;
}
@Override
public void onAccessibilityStateChanged(boolean enabled) {
mMobileAccessibility.onAccessibilityStateChanged(enabled);
}
@Override
public void onCaptioningEnabledChanged(boolean enabled) {
mMobileAccessibility.onCaptioningEnabledChanged(enabled);
}
@Override
public void onTouchExplorationStateChanged(boolean enabled) {
mMobileAccessibility.onTouchExplorationStateChanged(enabled);
}
@Override
public void addStateChangeListeners() {
}
@Override
public void removeStateChangeListeners() {
}
@Override
public void announceForAccessibility(CharSequence text) {
if (!mAccessibilityManager.isEnabled()) {
return;
}
final int eventType = AccessibilityEvent.TYPE_VIEW_FOCUSED;
final AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
event.getText().add(text);
event.setEnabled(mWebView.isEnabled());
event.setClassName(mWebView.getClass().getName());
event.setPackageName(mWebView.getContext().getPackageName());
event.setContentDescription(null);
mAccessibilityManager.sendAccessibilityEvent(event);
}
}

View File

@@ -0,0 +1,40 @@
package com.phonegap.plugin.mobileaccessibility;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.TargetApi;
import android.os.Build;
import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public class IceCreamSandwichMobileAccessibilityHelper extends
DonutMobileAccessibilityHelper {
protected AccessibilityStateChangeListener mAccessibilityStateChangeListener;
@Override
public boolean isScreenReaderRunning() {
return mAccessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_SPOKEN).size() > 0;
}
@Override
public void addStateChangeListeners() {
if (mAccessibilityStateChangeListener == null) {
mAccessibilityStateChangeListener = new InternalAccessibilityStateChangeListener();
}
mAccessibilityManager.addAccessibilityStateChangeListener(mAccessibilityStateChangeListener);
}
@Override
public void removeStateChangeListeners() {
mAccessibilityManager.removeAccessibilityStateChangeListener(mAccessibilityStateChangeListener);
mAccessibilityStateChangeListener = null;
}
protected class InternalAccessibilityStateChangeListener
implements AccessibilityStateChangeListener {
@Override
public void onAccessibilityStateChanged(boolean enabled) {
mMobileAccessibility.onAccessibilityStateChanged(enabled);
}
}
}

View File

@@ -0,0 +1,22 @@
package com.phonegap.plugin.mobileaccessibility;
import android.annotation.TargetApi;
import android.os.Build;
import android.view.accessibility.AccessibilityEvent;
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public class JellyBeanMobileAccessibilityHelper extends
IceCreamSandwichMobileAccessibilityHelper {
@Override
public void announceForAccessibility(CharSequence text) {
if (mAccessibilityManager.isEnabled() && mParent != null) {
AccessibilityEvent event = AccessibilityEvent.obtain(
AccessibilityEvent.TYPE_ANNOUNCEMENT);
mWebView.onInitializeAccessibilityEvent(event);
event.getText().add(text);
event.setContentDescription(null);
mParent.requestSendAccessibilityEvent(mWebView, event);
}
}
}

View File

@@ -0,0 +1,79 @@
package com.phonegap.plugin.mobileaccessibility;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.TargetApi;
import android.content.Context;
import android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener;
import android.view.accessibility.CaptioningManager;
import android.view.accessibility.CaptioningManager.CaptioningChangeListener;
@TargetApi(19)
public class KitKatMobileAccessibilityHelper extends
JellyBeanMobileAccessibilityHelper {
protected CaptioningManager mCaptioningManager;
protected CaptioningChangeListener mCaptioningChangeListener;
protected TouchExplorationStateChangeListener mTouchExplorationStateChangeListener;
@Override
public void initialize(MobileAccessibility mobileAccessibility) {
super.initialize(mobileAccessibility);
mCaptioningManager = (CaptioningManager) mobileAccessibility.cordova.getActivity().getSystemService(Context.CAPTIONING_SERVICE);
}
@Override
public boolean isScreenReaderRunning() {
return mAccessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_BRAILLE | AccessibilityServiceInfo.FEEDBACK_SPOKEN).size() > 0;
}
@Override
public boolean isClosedCaptioningEnabled() {
return mCaptioningManager.isEnabled();
}
@Override
public boolean isTouchExplorationEnabled() {
return mAccessibilityManager.isTouchExplorationEnabled();
}
@Override
public void addStateChangeListeners() {
super.addStateChangeListeners();
if (mCaptioningChangeListener == null) {
mCaptioningChangeListener = new CaptioningChangeListener() {
/** @hide */
@Override
public void onEnabledChanged(boolean enabled) {
onCaptioningEnabledChanged(enabled);
}
};
}
mCaptioningManager.addCaptioningChangeListener(mCaptioningChangeListener);
if (mTouchExplorationStateChangeListener == null) {
mTouchExplorationStateChangeListener = new InternalTouchExplorationStateChangeListener();
}
mAccessibilityManager.addTouchExplorationStateChangeListener(mTouchExplorationStateChangeListener);
}
@Override
public void removeStateChangeListeners() {
super.removeStateChangeListeners();
if (mCaptioningChangeListener != null) {
mCaptioningManager.removeCaptioningChangeListener(mCaptioningChangeListener);
mCaptioningChangeListener = null;
}
if (mTouchExplorationStateChangeListener != null) {
mAccessibilityManager.removeTouchExplorationStateChangeListener(mTouchExplorationStateChangeListener);
mTouchExplorationStateChangeListener = null;
}
}
protected class InternalTouchExplorationStateChangeListener
implements TouchExplorationStateChangeListener {
@Override
public void onTouchExplorationStateChanged(boolean enabled) {
mMobileAccessibility.onTouchExplorationStateChanged(enabled);
}
}
}

View File

@@ -0,0 +1,240 @@
package com.phonegap.plugin.mobileaccessibility;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.os.Build;
import android.util.Log;
/**
* This class provides information on the status of native accessibility services to JavaScript.
*/
public class MobileAccessibility extends CordovaPlugin {
protected AbstractMobileAccessibilityHelper mMobileAccessibilityHelper;
protected CallbackContext mCallbackContext = null;
protected boolean mIsScreenReaderRunning = false;
protected boolean mClosedCaptioningEnabled = false;
protected boolean mTouchExplorationEnabled = false;
protected boolean mCachedIsScreenReaderRunning = false;
@Override
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
super.initialize(cordova, webView);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
mMobileAccessibilityHelper = new KitKatMobileAccessibilityHelper();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
mMobileAccessibilityHelper = new JellyBeanMobileAccessibilityHelper();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
mMobileAccessibilityHelper = new IceCreamSandwichMobileAccessibilityHelper();
} else {
mMobileAccessibilityHelper = new DonutMobileAccessibilityHelper();
}
mMobileAccessibilityHelper.initialize(this);
}
@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
try {
if (action.equals("isScreenReaderRunning")) {
isScreenReaderRunning(callbackContext);
return true;
} else if (action.equals("isClosedCaptioningEnabled")) {
isClosedCaptioningEnabled(callbackContext);
return true;
} else if (action.equals("isTouchExplorationEnabled")) {
isTouchExplorationEnabled(callbackContext);
return true;
} else if (action.equals("postNotification")) {
if (args.length() > 1) {
String string = args.getString(1);
if (!string.isEmpty()) {
announceForAccessibility(string, callbackContext);
}
}
return true;
} else if (action.equals("start")) {
start(callbackContext);
return true;
} else if (action.equals("stop")) {
stop();
return true;
}
} catch (JSONException e) {
e.printStackTrace();
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
}
return false;
}
/**
* Called when the system is about to start resuming a previous activity.
*
* @param multitasking Flag indicating if multitasking is turned on for app
*/
@Override
public void onPause(boolean multitasking) {
Log.i("MobileAccessibility", "onPause");
mCachedIsScreenReaderRunning = mIsScreenReaderRunning;
}
/**
* Called when the activity will start interacting with the user.
*
* @param multitasking Flag indicating if multitasking is turned on for app
*/
@Override
public void onResume(boolean multitasking) {
Log.i("MobileAccessibility", "onResume");
if (mIsScreenReaderRunning && !mCachedIsScreenReaderRunning) {
Log.i("MobileAccessibility", "Reloading page on reload because the Accessibility State has changed.");
mCachedIsScreenReaderRunning = mIsScreenReaderRunning;
stop();
cordova.getActivity().runOnUiThread(new Runnable() {
public void run() {
webView.reload();
}
});
}
}
/**
* The final call you receive before your activity is destroyed.
*/
public void onDestroy() {
stop();
}
protected boolean isScreenReaderRunning(final CallbackContext callbackContext) {
mIsScreenReaderRunning = mMobileAccessibilityHelper.isScreenReaderRunning();
cordova.getThreadPool().execute(new Runnable() {
public void run() {
callbackContext.success(mIsScreenReaderRunning ? 1 : 0);
}
});
return mIsScreenReaderRunning;
}
protected boolean isScreenReaderRunning() {
mIsScreenReaderRunning = mMobileAccessibilityHelper.isScreenReaderRunning();
return mIsScreenReaderRunning;
}
protected boolean isClosedCaptioningEnabled(final CallbackContext callbackContext) {
mClosedCaptioningEnabled = mMobileAccessibilityHelper.isClosedCaptioningEnabled();
cordova.getThreadPool().execute(new Runnable() {
public void run() {
callbackContext.success(mClosedCaptioningEnabled ? 1 : 0);
}
});
return mClosedCaptioningEnabled;
}
protected boolean isClosedCaptioningEnabled() {
mClosedCaptioningEnabled = mMobileAccessibilityHelper.isClosedCaptioningEnabled();
return mClosedCaptioningEnabled;
}
protected boolean isTouchExplorationEnabled(final CallbackContext callbackContext) {
mTouchExplorationEnabled= mMobileAccessibilityHelper.isTouchExplorationEnabled();
cordova.getThreadPool().execute(new Runnable() {
public void run() {
callbackContext.success(mTouchExplorationEnabled ? 1 : 0);
}
});
return mTouchExplorationEnabled;
}
protected boolean isTouchExplorationEnabled() {
mTouchExplorationEnabled = mMobileAccessibilityHelper.isTouchExplorationEnabled();
return mTouchExplorationEnabled;
}
protected void announceForAccessibility(CharSequence text, final CallbackContext callbackContext) {
mMobileAccessibilityHelper.announceForAccessibility(text);
if (callbackContext != null) {
JSONObject info = new JSONObject();
try {
info.put("stringValue", text);
info.put("wasSuccessful", mIsScreenReaderRunning);
} catch (JSONException e) {
e.printStackTrace();
}
callbackContext.success(info);
}
}
public void onAccessibilityStateChanged(boolean enabled) {
mIsScreenReaderRunning = enabled;
cordova.getActivity().runOnUiThread(new Runnable() {
public void run() {
sendMobileAccessibilityStatusChangedCallback();
}
});
}
public void onCaptioningEnabledChanged(boolean enabled) {
mClosedCaptioningEnabled = enabled;
cordova.getActivity().runOnUiThread(new Runnable() {
public void run() {
sendMobileAccessibilityStatusChangedCallback();
}
});
}
public void onTouchExplorationStateChanged(boolean enabled) {
mTouchExplorationEnabled = enabled;
cordova.getActivity().runOnUiThread(new Runnable() {
public void run() {
sendMobileAccessibilityStatusChangedCallback();
}
});
}
protected void sendMobileAccessibilityStatusChangedCallback() {
if (this.mCallbackContext != null) {
PluginResult result = new PluginResult(PluginResult.Status.OK, getMobileAccessibilityStatus());
result.setKeepCallback(true);
this.mCallbackContext.sendPluginResult(result);
}
}
/* Get the current mobile accessibility status. */
protected JSONObject getMobileAccessibilityStatus() {
JSONObject status = new JSONObject();
try {
status.put("isScreenReaderRunning", mIsScreenReaderRunning);
status.put("isClosedCaptioningEnabled", mClosedCaptioningEnabled);
status.put("isTouchExplorationEnabled", mTouchExplorationEnabled);
Log.i("MobileAccessibility", "MobileAccessibility.isScreenReaderRunning == " + status.getString("isScreenReaderRunning") +
"\nMobileAccessibility.isClosedCaptioningEnabled == " + status.getString("isClosedCaptioningEnabled") +
"\nMobileAccessibility.isTouchExplorationEnabled == " + status.getString("isTouchExplorationEnabled") );
} catch (JSONException e) {
e.printStackTrace();
}
return status;
}
protected void start(CallbackContext callbackContext) {
Log.i("MobileAccessibility", "MobileAccessibility.start");
mCallbackContext = callbackContext;
mMobileAccessibilityHelper.addStateChangeListeners();
sendMobileAccessibilityStatusChangedCallback();
}
protected void stop() {
Log.i("MobileAccessibility", "MobileAccessibility.stop");
if (mCallbackContext != null) {
sendMobileAccessibilityStatusChangedCallback();
mMobileAccessibilityHelper.removeStateChangeListeners();
mCallbackContext = null;
}
}
}

View File

@@ -21,7 +21,8 @@
var argscheck = require('cordova/argscheck'),
utils = require('cordova/utils'),
exec = require('cordova/exec');
exec = require('cordova/exec'),
device = require('org.apache.cordova.device.device');
var MobileAccessibility = function() {
this._isScreenReaderRunning = false;
@@ -29,13 +30,15 @@ var MobileAccessibility = function() {
this._isGuidedAccessEnabled = false;
this._isInvertColorsEnabled = false;
this._isMonoAudioEnabled = false;
this._isTouchExplorationEnabled = false;
// Create new event handlers on the window (returns a channel instance)
this.channels = {
screenreaderstatuschanged:cordova.addWindowEventHandler("screenreaderstatuschanged"),
closedcaptioningstatusdidchange:cordova.addWindowEventHandler("closedcaptioningstatusdidchange"),
guidedaccessstatusdidchange:cordova.addWindowEventHandler("guidedaccessstatusdidchange"),
invertcolorsstatusdidchange:cordova.addWindowEventHandler("invertcolorsstatusdidchange"),
monoaudiostatusdidchange:cordova.addWindowEventHandler("monoaudiostatusdidchange")
monoaudiostatusdidchange:cordova.addWindowEventHandler("monoaudiostatusdidchange"),
touchexplorationstatechanged:cordova.addWindowEventHandler("touchexplorationstatechanged")
};
for (var key in this.channels) {
this.channels[key].onHasSubscribersChange = MobileAccessibility.onHasSubscribersChange;
@@ -51,7 +54,8 @@ function handlers() {
mobileAccessibility.channels.closedcaptioningstatusdidchange.numHandlers +
mobileAccessibility.channels.invertcolorsstatusdidchange.numHandlers +
mobileAccessibility.channels.monoaudiostatusdidchange.numHandlers +
mobileAccessibility.channels.guidedaccessstatusdidchange.numHandlers;
mobileAccessibility.channels.guidedaccessstatusdidchange.numHandlers +
mobileAccessibility.channels.touchexplorationstatechanged.numHandlers;
};
/**
@@ -76,9 +80,25 @@ MobileAccessibility.onHasSubscribersChange = function() {
* @param {function} callback A callback method to receive the asynchronous result from the native MobileAccessibility.
*/
MobileAccessibility.prototype.isScreenReaderRunning = function(callback) {
exec(callback, null, "MobileAccessibility", "isScreenReaderRunning", []);
exec(function(bool) {
if (device.platform==="Android") {
if (typeof cvox === "undefined") {
if (bool) {
console.warn('A screen reader is running but ChromeVox has failed to initialize.');
}
} else {
// activate or deactivate ChromeVox based on whether or not or not the screen reader is running.
cvox.ChromeVox.host.activateOrDeactivateChromeVox(bool);
}
}
callback(Boolean(bool));
}, null, "MobileAccessibility", "isScreenReaderRunning", []);
};
MobileAccessibility.prototype.isVoiceOverRunning = MobileAccessibility.prototype.isScreenReaderRunning;
MobileAccessibility.prototype.isTalkBackRunning = MobileAccessibility.prototype.isScreenReaderRunning;
MobileAccessibility.prototype.isChromeVoxActive = function () {
return typeof cvox !== "undefined" && cvox.ChromeVox.host.ttsLoaded() && cvox.Api.isChromeVoxActive();
};
/**
* Asynchronous call to native MobileAccessibility to determine if closed captioning is enabled.
@@ -112,6 +132,14 @@ MobileAccessibility.prototype.isGuidedAccessEnabled = function(callback) {
exec(callback, null, "MobileAccessibility", "isGuidedAccessEnabled", []);
};
/**
* Asynchronous call to native MobileAccessibility to determine if Touch Exploration is enabled on Android.
* @param {function} callback A callback method to receive the asynchronous result from the native MobileAccessibility.
*/
MobileAccessibility.prototype.isTouchExplorationEnabled = function(callback) {
exec(callback, null, "MobileAccessibility", "isTouchExplorationEnabled", []);
};
MobileAccessibility.prototype.MobileAccessibilityNotifications = {
SCREEN_CHANGED : 1000,
LAYOUT_CHANGED : 1001,
@@ -129,20 +157,56 @@ MobileAccessibility.prototype.postNotification = function(mobileAccessibilityNot
exec(callback, null, "MobileAccessibility", "postNotification", [mobileAccessibilityNotification, string]);
};
/**
* Speaks the given string, and if ChromeVox is active, it will use the specified queueMode and properties.
* @param {string} string A string to be announced by a screen reader.
* @param {number} [queueMode] Optional number. Valid modes are 0 for flush; 1 for queue.
* @param {Object} [properties] Speech properties to use for this utterance.
*/
MobileAccessibility.prototype.speak = function(string, queueMode, properties) {
if (this.isChromeVoxActive()) {
cvox.ChromeVox.tts.speak(string, queueMode, properties);
} else {
exec(null, null, "MobileAccessibility", "postNotification", [mobileAccessibility.MobileAccessibilityNotifications.ANNOUNCEMENT, string]);
}
}
/**
* Stops speech.
*/
MobileAccessibility.prototype.stop = function() {
if (this.isChromeVoxActive()) {
cvox.ChromeVox.tts.stop();
} else {
exec(null, null, "MobileAccessibility", "postNotification", [mobileAccessibility.MobileAccessibilityNotifications.ANNOUNCEMENT]);
}
}
/**
* Callback from native MobileAccessibility returning an which describes the status of MobileAccessibility features.
*
* @param {Object} info
* @config {Boolean} [isScreenReaderRunning] Boolean to indicate screen reader status.
* @config {Boolean} [isClosedCaptioningEnabled] Boolean to indicate closed captioning status.
* @config {Boolean} [isGuidedAccessEnabled] Boolean to indicate guided access status.
* @config {Boolean} [isInvertColorsEnabled] Boolean to indicate invert colors status.
* @config {Boolean} [isMonoAudioEnabled] Boolean to indicate mono audio status.
* @config {Boolean} [isGuidedAccessEnabled] Boolean to indicate guided access status (ios).
* @config {Boolean} [isInvertColorsEnabled] Boolean to indicate invert colors status (ios).
* @config {Boolean} [isMonoAudioEnabled] Boolean to indicate mono audio status (ios).
* @config {Boolean} [isTouchExplorationEnabled] Boolean to indicate touch exploration status (android).
*/
MobileAccessibility.prototype._status = function(info) {
if (info) {
if (mobileAccessibility._isScreenReaderRunning !== info.isScreenReaderRunning) {
cordova.fireWindowEvent("screenreaderstatuschanged", info);
if (device.platform === "Android") {
if (typeof cvox === "undefined") {
if (info.isScreenReaderRunning) {
console.warn('A screen reader is running but ChromeVox has failed to initialize.');
}
} else {
// activate or deactivate ChromeVox based on whether or not or not the screen reader is running.
cvox.ChromeVox.host.activateOrDeactivateChromeVox(info.isScreenReaderRunning);
}
}
if (mobileAccessibility._isScreenReaderRunning !== info.isScreenReaderRunning) {
cordova.fireWindowEvent("screenreaderstatuschanged", info);
mobileAccessibility._isScreenReaderRunning = info.isScreenReaderRunning;
}
if (mobileAccessibility._isClosedCaptioningEnabled !== info.isClosedCaptioningEnabled) {
@@ -161,6 +225,10 @@ MobileAccessibility.prototype._status = function(info) {
cordova.fireWindowEvent("monoaudiostatusdidchange", info);
mobileAccessibility._isMonoAudioEnabled = info.isMonoAudioEnabled;
}
if (mobileAccessibility._isTouchExplorationEnabled !== info.isTouchExplorationEnabled) {
cordova.fireWindowEvent("touchexplorationstatechanged", info);
mobileAccessibility._isTouchExplorationEnabled = info.isTouchExplorationEnabled;
}
}
};