cordova-plugin-apple-watch-link
Version:
Cordova Plugin for the Apple Watch (WatchKit) to allow communication between a Cordova app and an Apple WatchKit Extension (and vice versa).
1,312 lines (1,152 loc) • 99.5 kB
JavaScript
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
/* global cordova */
/*
Apple watch communication plugin for Cordova.
Access as window.cordova.plugins.watchLink
*/
function watchLink() {
var _watchLink = this;
// Watch session initialization
/*
watchLink.initialized is true if initialization of the Swift layer is complete
*/
_watchLink.initialized = false;
var watchLinkReadyProcs = [];
/*
watchLink.ready(f) adds the function f to the list of functions
to execute when initialization of the Swift layer is complete.
*/
this.ready = function(f) {
if (typeof f !== 'function') {
_watchLink.errorLog('watchLink.ready: parameter is not a function: ' + typeof f);
return;
}
watchLinkReadyProcs.push(f);
if (_watchLink.initialized) {
f();
}
};
var lastTimestamp = 0;
function newTimestamp() {
var timestamp = (new Date()).getTime();
if (timestamp <= lastTimestamp) {
timestamp = lastTimestamp + 1;
}
lastTimestamp = timestamp;
return timestamp;
}
// Watch availability
/*
watchLink availability states
*/
_watchLink.watchUnavailable = false;
_watchLink.watchAvailable = true;
_watchLink.watchNotPaired = "NOTPAIRED";
_watchLink.watchNotInstalled = "NOTINSTALLED";
/*
watchLink.available is the availability state.
null: yet to be initialized
watchLink.watchUnavailable: watch session is not available
watchLink.watchAvailable: watch sesion is available, watch is paired and
watch companion app installed
watchLink.watchNotPaired: watch sesion is available but watch is not paired to phone
watchLink.watchNotInstalled: watch sesion is available but
watch companion app has not been installed
*/
/*
watchLink.available stores the current availability state
*/
_watchLink.available = null;
/*
watchLink.availability updates and returns the current availability state of the
watch session. It is not normally required to call this since watchLink.available
is kept up to date.
Parameter
callback: function(availability)
The callback parameter represents the current availability state
Using the traditional Cordova callback method:
watchLink.availability(
function (availability) {
...
});
Using the Promise construct:
watchLink.availability().then(
function (availability) {
...
});
*/
_watchLink.availability = function(callback, error) {
if (!_watchLink.initialized) {
_watchLink.errorLog('watchLink.availability: watch session not initialized');
if (callback === undefined && error === undefined) {
return new Promise(
function(resolve, reject) {
reject('uninitialized');
});
}
else
if (error) {
error('uninitialized');
}
return;
}
if (callback === undefined && error === undefined) {
return new Promise(
function(resolve) {
cordova.exec(
function(state) {
_watchLink.available = state;
resolve(state);
}, null, 'WatchLink', 'availability');
});
}
cordova.exec(
function(state) {
_watchLink.available = state;
if (callback) {
callback(state);
}
}, error, 'WatchLink', 'availability');
};
/*
watchLink.availabilityChanged registers a callback to invoke when the availability
state changes. The callback parameter represents the new availability state.
Parameter
callback: function(availability)
Returns: true if registration succeeded, false otherwise
Supply null to deregister a previously set callback. You can overwrite a previously
set callback with a different callback.
*/
var availabilityChangedCallback = null;
_watchLink.availabilityChanged = function(callback) {
availabilityChangedCallback = null;
if (callback == null) {
return true;
}
if (typeof callback === 'function') {
availabilityChangedCallback = callback;
if (_watchLink.available != null) {
callback(_watchLink.available);
}
return true;
}
_watchLink.errorLog('watchLink.availabilityChanged: parameter is not a function',
callback);
return false;
};
// Watch reachability
/*
watchLink.reachable is the reachability state.
null: yet to be initialized
true: watch is reachable
false: watch is not reachable
Note that watchLink.reachable is false if watchLink.available is not true.
*/
_watchLink.reachable = null;
/*
watchLink.reachability updates and returns the current reachability state of the
watch session. It is not normally required to call this since watchLink.reachable
is kept up to date.
Parameter
callback: function(reachability)
The callback parameter represents the new reachability state:
true: watch is reachable
false: watch is not reachable
Using the traditional Cordova callback method:
watchLink.reachability(
function (reachability) {
...
});
Using the Promise construct:
watchLink.reachability().then(
function (reachability) {
...
});
*/
_watchLink.reachability = function(callback, error) {
if (!_watchLink.initialized) {
_watchLink.errorLog('watchLink.reachability: watch session not initialized');
if (callback === undefined && error === undefined) {
return new Promise(
function(resolve, reject) {
reject('uninitialized');
});
}
else
if (error) {
error('uninitialized');
}
return;
}
if (callback === undefined) {
return new Promise(
function(resolve) {
cordova.exec(
function(state) {
_watchLink.reachable = state;
resolve(state);
}, null, 'WatchLink', 'reachability');
});
}
cordova.exec(
function(state) {
_watchLink.reachable = state;
if (callback) {
callback(state);
}
}, null, 'WatchLink', 'reachability');
};
/*
watchLink.reachabilityChanged registers a callback to invoke when the reachibility
state changes. The callback parameter represents the new reachability state.
Parameter
callback: function(<boolean>)
Returns : true if registration succeeded, false otherwise
Supply null to deregister a previously set callback. You can overwrite a previously
set callback with a different callback.
*/
var reachabilityChangedCallback = null;
_watchLink.reachabilityChanged = function(callback) {
reachabilityChangedCallback = null;
if (callback == null) {
return true;
}
if (typeof callback === 'function') {
reachabilityChangedCallback = callback;
if (_watchLink.reachable != null) {
callback(_watchLink.reachable);
}
return true;
}
_watchLink.errorLog('watchLink.reachabilityChanged: parameter is not a function', callback);
return false;
};
// Watch application state
/*
Watch application state
*/
_watchLink.watchApplicationActive = "ACTIVE";
_watchLink.watchApplicationInactive = "INACTIVE";
_watchLink.watchAapplicationBackground = "BACKGROUND";
_watchLink.complicationEnabled = false;
_watchLink.isPaired = false;
_watchLink.isAppInstalled = false;
_watchLink.directoryURL = "";
/*
watchLink.applicationState is the Watch application state.
null: yet to be initialized, otherwise
watchLink.applicationState = { state: <state>, complication: <Boolean>
directoryURL: <string> }
watchLink.applicationState.state
false: watch is not available, or the application is not not running or suspended
watchLink.watchApplicationActive: The Watch app is running in foreground
and responding to events
watchLink.watchApplicationInactive: The Watch app is running in foreground
but not yet responding to events
watchLink.watchApplicationBackground: The watch app is running in the background
watchLink.applicationState.complication
true: complication is enabled
false: complication is not enabled
watchLink.applicationState.isPaired
true: watch is paired
false: watch is not paired
watchLink.applicationState.isAppInstalled
true: watch app is installed
false: watch app is not installed
watchLink.applicationState.directoryURL
The URL of a directory for storing information specific to the currently
paired and active Watch
Note that watchLink.applicationState.state is false if watchLink.available is not true.
*/
_watchLink.applicationState = null;
/*
watchLink.watchApplicationState updates and returns the current applicationState
state of the Watch app. It is not normally required to call this since
watchLink.applicationState is kept up to date.
Parameter
callback: function(state)
The callback parameter represents the new application state:
false: watch is not available, or the application is not not running or suspended
_watchLink.applicationActive: The Watch app is running in foreground and responding
to events
_watchLink.applicationInactive: The Watch app is running in foreground but
not yet responding to events
_watchLink.applicationBackground: The watch app is running in the background
Using the traditional Cordova callback method:
watchLink.watchAppState(
function (state) {
...
});
Using the Promise construct:
watchLink.watchAppState().then(
function (state) {
...
});
*/
_watchLink.watchApplicationState = function(callback, error) {
if (!_watchLink.initialized) {
_watchLink.errorLog('watchLink.watchApplicationState: watch session not initialized');
if (callback === undefined && error === undefined) {
return new Promise(
function(resolve, reject) {
reject('uninitialized');
});
}
else
if (error) {
error('uninitialized');
}
return;
}
if (callback === undefined) {
return new Promise(
function(resolve) {
cordova.exec(
function(state) {
_watchLink.applicationState = state;
resolve(state);
}, null, 'WatchLink', 'watchApplicationState');
});
}
cordova.exec(
function(state) {
_watchLink.applicationState = state;
if (callback) {
callback(_watchLink.applicationState);
}
}, null, 'WatchLink', 'watchApplicationState');
};
/*
watchLink.applicationStateChanged registers a callback to invoke when the
application state changes. The callback parameter represents the new application state.
Parameter
callback: function(state)
Returns : true if registration succeeded, false otherwise
Supply null to deregister a previously set callback. You can overwrite a previously
set callback with a different callback.
*/
var applicationStateChangedCallback = null;
_watchLink.applicationStateChanged = function(callback) {
applicationStateChangedCallback = null;
if (callback == null) {
return true;
}
if (typeof callback === 'function') {
applicationStateChangedCallback = callback;
callback(_watchLink.applicationState);
return true;
}
_watchLink.errorLog('watchLink.applicationStateChanged: parameter is not a function', callback);
return false;
};
// Message session management
/*
watchLink.resetSession resets the current messaging session. Messages waiting
for transmission at the host and watch are discarded. Any messages arriving
from the watch with and obsolete session ID are discarded.
watchLink.resetSession is called by watchLink initialization code because
restarting the Cordova app does not restart the Swift layer. Therefore,
the session reset is required to ensure messages dispatched but not processed
before the restart are discarded.
*/
_watchLink.resetSession = function(completion, reason) {
reason = reason || 'resetSession';
if (!_watchLink.initialized) {
_watchLink.errorLog('watchLink.resetSession ignored: watch session not initialized');
if (completion) {
completion('uninitialized');
}
}
cordova.exec(
function() {
_watchLink.log('Session RESET');
if (completion) {
completion(true);
}
},
function(msg) {
if (!/^sessionreset/.test(msg)) {
_watchLink.errorLog('watchLink.resetSession failed: ' + msg);
}
},
'WatchLink', 'resetSession', [reason]);
};
// Dictionary message passing
/*
The following are reserved message types and should not be used as message types
or as keys at the top level of user information, context or complication dictionaries
*/
var reservedMsgTypes = new RegExp(
"^(" +
"ACK" + "|" +
"DATA" + "|" +
"SESSION" + "|" +
"RESET" + "|" +
"SETLOGLEVEL" + "|" +
"SETPRINTLOGLEVEL" + "|" +
"UPDATEDCONTEXT" + "|" +
"UPDATEDUSERINFO" + "|" +
"WATCHLOG" + "|" +
"WATCHERRORLOG" + "|" +
"WATCHAPPLOG" + "|" +
"WCSESSION" + "|" +
"IOSINITIALIZED" + "|" +
"IOSTERMINATED" + ")$"
);
/*
watchLink.sendMessage sends a message to the watch. If the watch is available but
not reachable, the message is queued until the watch becomes reachable.
Messages are acknowledged by the watch and the success callback will not be
invoked until acknowlegement has been received.
Messages are acknowledged by the watch and the success callback will not be
invoked until acknowlegement has been received.
Note: if you want to omit acknowledgement, use the traditional Cordova
callback method and supply null for the success callback.
Using the traditional Cordova callback method:
// send with acknowledgement
watchLink.sendMessage(msgType, msgBody, success, error);
// send without acknowledgement
watchLink.sendMessage(msgType, msgBody, null, error);
Using the Promise construct:
watchLink.sendMessage(msgType, msgBody)
.then(success)
.catch(error);
*/
_watchLink.sendMessage = function(msgType, msgBody, success, error) {
if (!_watchLink.initialized || _watchLink.available !== true) {
_watchLink.errorLog('watchLink.sendMessage: watch session not ' + (_watchLink.initialized ? 'available' : 'initialized'));
if (success === undefined && error === undefined) {
return new Promise(
function(resolve, reject) {
reject(_watchLink.initialized ? 'not available' : 'uninitialized');
});
}
else
if (error) {
error(_watchLink.initialized ? 'not available' : 'uninitialized');
}
return;
}
var err = '';
if (typeof msgType !== 'string') {
err = 'watchLink.sendMessage msgType is not a string: ' + typeof msgType;
}
else
if (typeof msgBody !== 'object') {
err = 'watchLink.sendMessage msgBody is not an object: ' + typeof msgBody;
}
else
if (success != null && typeof success !== 'function') {
err = 'watchLink.sendMessage success parameter is not a function: '
+ typeof success;
}
else
if (error != null && typeof error !== 'function') {
err = 'watchLink.sendMessage error parameter is not a function: '
+ typeof error;
}
else
if (reservedMsgTypes.test(msgType)) {
err = 'watchLink.sendMessage msgType is reserved: ' + typeof msgType;
}
if (err) {
_watchLink.errorLog(err);
return;
}
msgBody.TIMESTAMP = newTimestamp();
if (typeof success === 'undefined' && typeof error === 'undefined') {
return new Promise(
function(resolve, reject) {
cordova.exec(resolve, reject, 'WatchLink', 'sendMessage',
[msgType || '', msgBody]);
});
}
if (success === null) {
cordova.exec(success, error, 'WatchLink', 'sendMessageNoAck',
[msgType || '', msgBody]);
}
else {
cordova.exec(success, error, 'WatchLink', 'sendMessage',
[msgType || '', msgBody]);
}
};
/*
watchLink.flushMessages flushes all outstanding messages from the queue. The
error handlers for flushed messages are NOT invoked and any acknowledgements
that subsequently arrive will be ignored (the success handlers will NOT be invoked).
Note: messages sent via watchLink.transferMessage that have been sent via user
information transfer but not yet transmited and/or acknowledged will also be
flushed by this call.
*/
_watchLink.flushMessages = function() {
if (!_watchLink.initialized || _watchLink.available !== true) {
_watchLink.errorLog('watchLink.flushMessages ignored: watch session not ' + (_watchLink.initialized ? 'available' : 'initialized'));
return;
}
cordova.exec(null, null, 'WatchLink', 'flushMessages', []);
};
/*
watchLink.transferMessage sends a message to the watch. If the watch is available but
not reachable, the message is sent via user information transfer which can take place in background.
Messages are acknowledged by the watch and the success callback will not be
invoked until acknowlegement has been received.
Messages are acknowledged by the watch and the success callback will not be
invoked until acknowlegement has been received.
Note: if you want to omit acknowledgement, use the traditional Cordova
callback method and supply null for the success callback.
Using the traditional Cordova callback method:
// send with acknowledgement
watchLink.transferMessage(msgType, msgBody, success, error);
// send without acknowledgement
watchLink.transferMessage(msgType, msgBody, null, error);
Using the Promise construct:
watchLink.transferMessage(msgType, msgBody)
.then(success)
.catch(error);
*/
_watchLink.transferMessage = function(msgType, msgBody, success, error) {
if (!_watchLink.initialized || _watchLink.available !== true) {
_watchLink.errorLog('watchLink.sendMessage: watch session not ' + (_watchLink.initialized ? 'available' : 'initialized'));
if (success === undefined && error === undefined) {
return new Promise(
function(resolve, reject) {
reject(_watchLink.initialized ? 'not available' : 'uninitialized');
});
}
else
if (error) {
error(_watchLink.initialized ? 'not available' : 'uninitialized');
}
return;
}
var err = '';
if (typeof msgType !== 'string') {
err = 'watchLink.transferMessage msgType is not a string: ' + typeof msgType;
}
else
if (typeof msgBody !== 'object') {
err = 'watchLink.transferMessage msgBody is not an object: ' + typeof msgBody;
}
else
if (success != null && typeof success !== 'function') {
err = 'watchLink.transferMessage success parameter is not a function: '
+ typeof success;
}
else
if (error != null && typeof error !== 'function') {
err = 'watchLink.transferMessage error parameter is not a function: '
+ typeof error;
}
else
if (reservedMsgTypes.test(msgType)) {
err = 'watchLink.transferMessage msgType is reserved: ' + typeof msgType;
}
if (err) {
_watchLink.errorLog(err);
return;
}
msgBody.TIMESTAMP = newTimestamp();
if (typeof success === 'undefined' && typeof error === 'undefined') {
return new Promise(
function(resolve, reject) {
cordova.exec(resolve, reject, 'WatchLink', 'transferMessage',
[msgType || '', msgBody]);
});
}
if (success === null) {
cordova.exec(success, error, 'WatchLink', 'transferMessageNoAck',
[msgType || '', msgBody]);
}
else {
cordova.exec(success, error, 'WatchLink', 'transferMessage',
[msgType || '', msgBody]);
}
};
/*
watchLink.bindMessageHandler establishes a handler to process messages from the
watch of a matching message type.
To handle an incoming message, the message type is extracted and each handler
with a matching expression is invoked with the message type and message body
as parameters.
Processing continues until all matching expressions have been checked, or until
a handler returns false to halt processing.
Parameters
expr: <string> | <RegExp>
handler: function(<string>, <object>)
Returns : nothing
The expression can be a string (requires an exact match) or a RegExp.
Supplying null for the handler will unbind a previously bound handler.
Supplying a handler for an existing match expression will overwrite the existing
handler for that expression.
Supplying null for the match expression will set the default handler, unless it
is null also in which case the default handler will be unbound.
*/
var messageHandlers = [],
defaultMessageHandler = null;
_watchLink.bindMessageHandler = function(expr, handler) {
var reg,
i,
err = '';
if (expr == null) {
if (handler == null) {
defaultMessageHandler = null;
_watchLink.log('watchLink.bindMessageHandler deregistered default handler');
return;
}
if (typeof handler !== 'function') {
err = 'watchLink.bindMessageHandler parameter is not a function: '
+ typeof handler;
_watchLink.errorLog(err);
return;
}
defaultMessageHandler = handler;
_watchLink.log('watchLink.bindMessageHandler registered default handler');
return;
}
if (typeof expr === 'string') {
reg = new RegExp('^' + expr + '$');
}
else
if (!(expr instanceof RegExp)) {
err = 'watchLink.bindMessageHandler expr is not a string or RegExp: '
+ typeof expr;
_watchLink.errorLog(err);
return;
}
if (reservedMsgTypes.test(expr.toString())) {
err = 'watchLink.bindMessageHandler expr uses reserved word ',
expr.toString();
_watchLink.errorLog(err);
return;
}
if (handler == null) {
for (i = 0; i < messageHandlers.length; i++) {
if (reg.toString() === messageHandlers[i].reg.toString()) {
messageHandlers.splice(i, 1);
_watchLink.log('watchLink.bindMessageHandler deregistered for ' +
reg.toString());
return;
}
}
_watchLink.errorLog('watchLink.bindMessageHandler: cannot locate handler for RegExp: ',
reg.toString());
return;
}
if (typeof handler !== 'function') {
err = 'watchLink.bindMessageHandler: parameter is not a function: '
+ typeof handler;
_watchLink.errorLog(err);
return;
}
for (i = 0; i < messageHandlers.length; i++) {
if (reg.toString() === messageHandlers[i].reg.toString()) {
messageHandlers[i].handler = handler;
return;
}
}
messageHandlers.push({ reg: reg, handler: handler });
};
// Data message passing
/*
watchLink.sendDataMessage sends a data message to the watch. If the watch is
available but not reachable, the message is queued until the watch becomes reachable.
Data messages are acknowledged by the watch and the success callback will not be
invoked until acknowlegement has been received.
Note: if you want to omit acknowledgement, use the traditional Cordova callback
method and supply null for the success callback.
Using the traditional Cordova callback method:
// send with acknowledgement
watchLink.sendDataMessage(msgData, success, error);
// send without acknowledgement
watchLink.sendDataMessage(msgData, null, error);
Using the Promise construct:
watchLink.sendDataMessage(msgData)
.then(success)
.catch(error);
*/
_watchLink.sendDataMessage = function(msgData, success, error) {
if (!_watchLink.initialized || _watchLink.available !== true) {
_watchLink.errorLog('watchLink.sendDataMessage: watch session not ' + (_watchLink.initialized ? 'available' : 'initialized'));
if (success === undefined && error === undefined) {
return new Promise(
function(resolve, reject) {
reject(_watchLink.initialized ? 'not available' : 'uninitialized');
});
}
else
if (error) {
error(_watchLink.initialized ? 'not available' : 'uninitialized');
}
return;
}
var err = '';
if (msgData == null) {
err = 'watchLink.sendDataMessage msgData is null';
}
else
if (typeof msgData !== 'object') {
err = 'watchLink.sendDataMessage msgData is not an object: ' + typeof msgBody;
}
else
if (success != null && typeof success !== 'function') {
err = 'watchLink.sendDataMessage success parameter is not a function: '
+ typeof success;
}
else
if (error != null && typeof error !== 'function') {
err = 'watchLink.sendDataMessage error parameter is not a function: '
+ typeof error;
}
if (err) {
_watchLink.errorLog(err);
return;
}
if (typeof success === 'undefined' && typeof error === 'undefined') {
return new Promise(
function(resolve, reject) {
cordova.exec(resolve, reject, 'WatchLink', 'sendDataMessage', [msgData]);
});
}
if (success === null) {
cordova.exec(success, error, 'WatchLink', 'sendDataMessageNoAck', [msgData]);
}
else {
cordova.exec(success, error, 'WatchLink', 'sendDataMessage', [msgData]);
}
};
/*
watchLink.flushDataMessages flushes all outstanding data messages from the queue.
The error handlers for flushed data messages are NOT invoked and any acknowledgements
that subsequently arrive will be ignored (the success handlers will NOT be invoked).
*/
_watchLink.flushDataMessages = function() {
if (!_watchLink.initialized || _watchLink.available !== true) {
_watchLink.errorLog('watchLink.flushDataMessages ignored: watch session not ' + (_watchLink.initialized ? 'available' : 'initialized'));
return;
}
cordova.exec(null, null, 'WatchLink', 'flushDataMessages', []);
};
/*
watchLink.bindDataMessageHandler establishes a handler to process data messages
from the watch.
Parameters
handler: function(<ArrayBuffer>)
Returns : nothing
Supplying null for the handler will unbind a previously bound handler.
Supplying a handler will overwrite an existing handler.
*/
var dataMessageHandler = null;
_watchLink.bindDataMessageHandler = function(handler) {
var err = '';
if (handler == null) {
dataMessageHandler = null;
_watchLink.log('watchLink.bindDataMessageHandler deregistered handler');
return;
}
if (typeof handler !== 'function') {
err = 'watchLink.bindDataMessageHandler parameter is not a function: '
+ typeof handler;
_watchLink.errorLog(err);
return;
}
dataMessageHandler = handler;
_watchLink.log('watchLink.bindDataMessageHandler registered handler');
};
// User information transfers
/*
watchLink.sendUserInfo sends a user information update to the watch. If the watch
is available but not reachable, the information is transmitted in background and
acknowledged when the watch becomes reachable and processes the update.
User information updates are acknowledged by the watch and the success callback will
not be invoked until acknowlegement has been received.
Note: if you want to omit acknowledgement, use the traditional Cordova callback
method and supply null for the success callback.
Using the traditional Cordova callback method:
// send with acknowledgement
watchLink.sendUserInfo(userInfo, success, error);
// send without acknowledgement
watchLink.sendUserInfo(userInfo, null, error);
Using the Promise construct:
watchLink.sendUserInfo(userInfo)
.then(success)
.catch(error);
*/
_watchLink.sendUserInfo = function(userInfo, success, error) {
if (!_watchLink.initialized || _watchLink.available !== true) {
_watchLink.errorLog('watchLink.sendUserInfo: watch session not ' + (_watchLink.initialized ? 'available' : 'initialized'));
if (success === undefined && error === undefined) {
return new Promise(
function(resolve, reject) {
reject(_watchLink.initialized ? 'not available' : 'uninitialized');
});
}
else
if (error) {
error(_watchLink.initialized ? 'not available' : 'uninitialized');
}
return;
}
var err = '';
if (userInfo == null) {
err = 'watchLink.sendUserInfo userInfo is null';
}
else
if (typeof userInfo !== 'object') {
err = 'watchLink.sendUserInfo userInfo is not an object: ' + typeof userInfo;
}
else
if (success != null && typeof success !== 'function') {
err = 'watchLink.sendUserInfo success parameter is not a function: '
+ typeof success;
return;
}
else
if (error != null && typeof error !== 'function') {
err = 'watchLink.sendUserInfo error parameter is not a function: '
+ typeof error;
}
if (err) {
_watchLink.errorLog(err);
return;
}
userInfo.TIMESTAMP = newTimestamp();
if (typeof success === 'undefined' && typeof error === 'undefined') {
return new Promise(
function(resolve, reject) {
cordova.exec(resolve, reject, 'WatchLink', 'sendUserInfo', [userInfo]);
});
}
if (success === null) {
cordova.exec(success, error, 'WatchLink', 'sendUserInfoNoAck', [userInfo]);
}
else {
cordova.exec(success, error, 'WatchLink', 'sendUserInfo', [userInfo]);
}
};
/*
watchLink.queryUserInfo obtains the status of a user information transfer
via the TIMESTAMP set by watchLink.sendUserInfo.
*/
_watchLink.queryUserInfo = function(timestamp, success, error) {
if (!_watchLink.initialized || _watchLink.available !== true) {
_watchLink.errorLog('watchLink.queryUserInfo: watch session not ' + (_watchLink.initialized ? 'available' : 'initialized'));
if (success === undefined && error === undefined) {
return new Promise(
function(resolve, reject) {
reject(_watchLink.initialized ? 'not available' : 'uninitialized');
});
}
else
if (error) {
error(_watchLink.initialized ? 'not available' : 'uninitialized');
}
return;
}
var err = '';
if (typeof timestamp !== 'number') {
err = 'watchLink.queryUserInfo timestamp is not a number: '
+ typeof timestamp;
}
else
if (success != null && typeof success !== 'function') {
err = 'watchLink.queryUserInfo success parameter is not a function: '
+ typeof success;
}
else
if (error != null && typeof error !== 'function') {
err = 'watchLink.queryUserInfo error parameter is not a function: '
+ typeof error;
}
if (err) {
_watchLink.errorLog(err);
return;
}
if (success === undefined && error === undefined) {
return new Promise(
function(resolve, reject) {
cordova.exec(resolve, reject, 'WatchLink', 'queryUserInfo',
[timestamp]);
});
}
cordova.exec(success, error, 'WatchLink', 'queryUserInfo', [timestamp]);
};
/*
watchLink.cancelUserInfo cancels a user information transfer via the TIMESTAMP
set by watchLink.sendUserInfo.
*/
_watchLink.cancelUserInfo = function(timestamp, success, error) {
if (!_watchLink.initialized || _watchLink.available !== true) {
_watchLink.errorLog('watchLink.cancelUserInfo: watch session not ' + (_watchLink.initialized ? 'available' : 'initialized'));
if (success === undefined && error === undefined) {
return new Promise(
function(resolve, reject) {
reject(_watchLink.initialized ? 'not available' : 'uninitialized');
});
}
else
if (error) {
error(_watchLink.initialized ? 'not available' : 'uninitialized');
}
return;
}
var err = '';
if (typeof timestamp !== 'number') {
err = 'watchLink.cancelUserInfo timestamp is not a number: '
+ typeof timestamp;
}
else
if (success != null && typeof success !== 'function') {
err = 'watchLink.cancelUserInfo success parameter is not a function: '
+ typeof success;
}
else
if (error != null && typeof error !== 'function') {
err = 'watchLink.cancelUserInfo error parameter is not a function: '
+ typeof error;
}
if (err) {
_watchLink.errorLog(err);
return;
}
if (success === undefined && error === undefined) {
return new Promise(
function(resolve, reject) {
cordova.exec(resolve, reject, 'WatchLink', 'cancelUserInfo',
[timestamp]);
});
}
cordova.exec(success, error, 'WatchLink', 'cancelUserInfo', [timestamp]);
};
/*
watchLink.flushUserInfoTransfers flushes all outstanding user information transfers
from the queue. The error handlers for flushed user information transfers are NOT
invoked and any acknowledgements that subsequently arrive will be ignored (the success
handlers will NOT be invoked).
*/
_watchLink.flushUserInfoTransfers = function() {
if (!_watchLink.initialized || _watchLink.available !== true) {
_watchLink.errorLog('watchLink.flushUserInfoTransfers ignored: watch session not ' + (_watchLink.initialized ? 'available' : 'initialized'));
return;
}
cordova.exec(null, null, 'WatchLink', 'flushUserInfo', []);
};
/*
watchLink.outstandingUserInfoTransfers obtains the status of all in-progress
user information transfers.
*/
_watchLink.outstandingUserInfoTransfers = function(success, error) {
if (!_watchLink.initialized || _watchLink.available !== true) {
_watchLink.errorLog('watchLink.outstandingUserInfoTransfers: watch session not ' + (_watchLink.initialized ? 'available' : 'initialized'));
if (success === undefined && error === undefined) {
return new Promise(
function(resolve, reject) {
reject(_watchLink.initialized ? 'not available' : 'uninitialized');
});
}
else
if (error) {
error(_watchLink.initialized ? 'not available' : 'uninitialized');
}
return;
}
var err = '';
if (success != null && typeof success !== 'function') {
err = 'watchLink.outstandingUserInfoTransfers success parameter is not a function: '
+ typeof success;
}
else
if (error != null && typeof error !== 'function') {
err = 'watchLink.outstandingUserInfoTransfers error parameter is not a function: '
+ typeof error;
}
if (err) {
_watchLink.errorLog(err);
return;
}
if (success == null && error == null) {
return new Promise(
function(resolve, reject) {
cordova.exec(resolve, reject, 'WatchLink',
'outstandingUserInfoTransfers', []);
});
}
cordova.exec(success, error, 'WatchLink', 'outstandingUserInfoTransfers', []);
};
/*
watchLink.bindUserInfoHandler establishes a handler to process application user
information updates from the watch.
Parameter
handler: function(<object>)
Returns : nothing
Supply null to deregister a previously set callback. You can overwrite a previously set
handler with a different handler.
The handler parameter represents the updated user information object.
*/
var userInfoHandler = null;
_watchLink.bindUserInfoHandler = function(handler) {
var err = '';
userInfoHandler = null;
if (handler == null) {
return;
}
if (typeof handler !== 'function') {
err = 'watchLink.bindUserInfoHandler parameter is not a function: '
+ typeof handler;
_watchLink.errorLog(err);
return;
}
userInfoHandler = handler;
_watchLink.log('watchLink.bindUserInfoHandler registered user information handler');
};
// Application context transfers
/*
watchLink.sendContext sends an application context update to the watch. If the watch is
available but not reachable, the application context is transmitted in background
and acknowledged when the watch becomes reachable and processes the update.
Application context updates are acknowledged by the watch and the success callback will
not be invoked until acknowlegement has been received.
Note: if you want to omit acknowledgement, use the traditional Cordova callback method
and supply null for the success callback.
Using the traditional Cordova callback method:
// send with acknowledgement
watchLink.sendContext(userInfo, success, error);
// send without acknowledgement
watchLink.sendContext(userInfo, null, error);
Using the Promise construct:
watchLink.sendContext(userInfo)
.then(success)
.catch(error);
*/
_watchLink.sendContext = function(context, success, error) {
if (!_watchLink.initialized || _watchLink.available !== true) {
_watchLink.errorLog('watchLink.sendContext: watch session not ' + (_watchLink.initialized ? 'available' : 'initialized'));
if (success === undefined && error === undefined) {
return new Promise(
function(resolve, reject) {
reject(_watchLink.initialized ? 'not available' : 'uninitialized');
});
}
else
if (error) {
error(_watchLink.initialized ? 'not available' : 'uninitialized');
}
return;
}
var err = '';
if (context == null) {
err = 'watchLink.sendContext context is null';
}
else
if (typeof context !== 'object') {
err = 'watchLink.sendUserInfo userInfo is not an object: ' + typeof context;
}
else
if (success != null && typeof success !== 'function') {
err = 'watchLink.sendContext success parameter is not a function: '
+ typeof success;
return;
}
else
if (error != null && typeof error !== 'function') {
err = 'watchLink.sendContext error parameter is not a function: '
+ typeof error;
}
else
if (context.ACK != null || context.SESSION != null) {
err = 'watchLink.sendContext userinfo contains reserved keys';
}
if (err) {
_watchLink.errorLog(err);
return;
}
context.TIMESTAMP = newTimestamp();
if (typeof success === 'undefined' && typeof error === 'undefined') {
return new Promise(
function(resolve, reject) {
cordova.exec(resolve, reject, 'WatchLink', 'sendContext', [context]);
});
}
if (success === null) {
cordova.exec(success, error, 'WatchLink', 'sendContextNoAck', [context]);
}
else {
cordova.exec(success, error, 'WatchLink', 'sendContext', [context]);
}
};
/*
watchLink.latestContextSent obtains the latest context transmitted.
Using the traditional Cordova callback method:
watchLink.latestContextSent(success, error);
Using the Promise construct:
watchLink.latestContextSent()
.then(success)
.catch(error);
*/
_watchLink.latestContextSent = function(success, error) {
if (!_watchLink.initialized || _watchLink.available !== true) {
_watchLink.errorLog('watchLink.latestContextSent: watch session not ' + (_watchLink.initialized ? 'available' : 'initialized'));
if (success === undefined && error === undefined) {
return new Promise(
function(resolve, reject) {
reject(_watchLink.initialized ? 'not available' : 'uninitialized');
});
}
else
if (error) {
error(_watchLink.initialized ? 'not available' : 'uninitialized');
}
return;
}
var err = '';
if (success != null && typeof success !== 'function') {
err = 'watchLink.latestContextSent success parameter is not a function: '
+ typeof success;
}
else
if (error != null && typeof error !== 'function') {
err = 'watchLink.latestContextSent error parameter is not a function: '
+ typeof error;
}
if (err) {
_watchLink.errorLog(err);
return;
}
if (success === undefined && error === undefined) {
return new Promise(
function(resolve, reject) {
cordova.exec(resolve, reject, 'WatchLink', 'latestContextSent', []);
});
}
cordova.exec(success, error, 'WatchLink', 'latestContextSent', []);
};
/*
watchLink.latestContextReceived obtains the latest context received.
Using the traditional Cordova callback method:
watchLink.latestContextReceived(success, error);
Using the Promise construct:
watchLink.latestContextReceived()
.then(success)
.catch(error);
*/
_watchLink.latestContextReceived = function(success, error) {
if (!_watchLink.initialized || _watchLink.available !== true) {
_watchLink.errorLog('watchLink.latestContextReceived: watch session not ' + (_watchLink.initialized ? 'available' : 'initialized'));
if (success === undefined && error === undefined) {
return new Promise(
function(resolve, reject) {
reject(_watchLink.initiali