The Cordova
engine provides a hardware-accelerated wrapper around HTML5.
-
Before the
Cordova
projects can be created, be sure to install theCordova
Command-Line Interface. -
Install
Node.js
.
On Windows, Node.js
can be installed from an MSI
installer and be sure to add 'Node and npm' to the path.
- Be sure to install a
GIT
source-control client.Cordova
will report errors ifgit
is missing from the path.
- Open a new terminal to install
Cordova
globally.
On Mac:
sudo npm install -g cordova
On Windows:
npm install -g cordova
- Be sure to update to the latest version of
Android Studio
.
The Virtual Controller example shows 4 images of the OUYA Controller which moves axises and highlights buttons when the physical controller is manipulated.
- The initial
VirtualController
project was created with the command-line from theCordova
folder.
cordova create VirtualController tv.ouya.examples.cordova.virtualcontroller VirtualController
Android
support is added to theCordova
project with the following command-line from theCordova/VirtualController
folder.
cordova platform add android
- Use the
Cordova
command-line to add thecordova-plugin-ouya-sdk
plugin.
cordova plugin add https://github.com/ouya/cordova-plugin-ouya-sdk.git#master
- To build and run the
Virtual Controller Example
run the following command from theCordova/VirtualController
folder.
cordova run android
- Manually copy
plugins\cordova-plugin-ouya-sdk\src\android\MainActivity.java
toplatforms\android\src\tv\ouya\examples\cordova\virtualcontroller\MainActivity.java
and edit the package name to betv.ouya.examples.cordova.virtualcontroller
.Cordova
auto-configs cannot replaceXML
nodes making this manual one-off necessary.
package tv.ouya.examples.cordova.virtualcontroller;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.util.SparseArray;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import java.util.HashMap;
import org.apache.cordova.*;
import tv.ouya.console.api.OuyaController;
import tv.ouya.sdk.CordovaOuyaPlugin;
import tv.ouya.sdk.OuyaInputView;
public class MainActivity extends CordovaActivity
{
...
}
- Replace the
Cordova\VirtualController\www
content folder with the Virtual Controller example HTML5 so that thecordova run android
command will embed the files into theAndroid
platform.
a.png
controller.png
dpad_down.png
dpad_left.png
dpad_right.png
dpad_up.png
index.html
lb.png
lt.png
l_stick.png
menu.png
o.png
rb.png
rt.png
r_stick.png
thumbl.png
thumbr.png
u.png
y.png
Cordova
projects can import into Android Studio as aGradle
project.
- The example project can be imported from the
Cordova/VirtualController/platforms/android
folder.
- Customize the
AndroidManifest.xml
to include the leanback-icon. Cordova requires a target version of22
.
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="22" />
The In-App-Purchases example shows making purchases, checking receipts, adjusting the safe area, and exiting the app.
- The initial
InAppPurchases
project was created with the command-line from theCordova
folder.
cordova create InAppPurchases tv.ouya.examples.cordova.inapppurchases InAppPurchases
Android
support is added to theCordova
project with the following command-line from theCordova/InAppPurchases
folder.
cordova platform add android
- Use the
Cordova
command-line to add thecordova-plugin-ouya-sdk
plugin.
cordova plugin add https://github.com/ouya/cordova-plugin-ouya-sdk.git#master
- To build and run the
In-App-Purchases Example
run the following command from theCordova/InAppPurchases
folder.
cordova run android
- Manually copy
plugins\cordova-plugin-ouya-sdk\src\android\MainActivity.java
toplatforms\android\src\tv\ouya\examples\cordova\inapppurchases\MainActivity.java
and edit the package name to betv.ouya.examples.cordova.inapppurchases
.Cordova
auto-configs cannot replaceXML
nodes making this manual one-off necessary.
package tv.ouya.examples.cordova.inapppurchases;
-
The example
HTML5
contents are placed within theCordova\InAppPurchases\www
folder so that the above command will copy the files to theAndroid
platform. -
Cordova
projects can import into Android Studio as aGradle
project.
- The example project can be imported from the
Cordova/InAppPurchases/platforms/android
folder.
To interact with Cordova plugins, first add Cordova
includes in the head
.
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/index.js"></script>
Register the Cordova
input hooks to receive HTML5
input.
function onLoad() {
if (cordova.exec == undefined) {
onFailure(0, "Wait for plugin to load!");
setTimeout(function(){ onLoad() }, 1000);
return;
}
cordova.exec(
function(jsonData) {
var jsonObject = JSON.parse(jsonData);
var playerNum = jsonObject.playerNum;
var axis = jsonObject.axis;
var val = jsonObject.val;
//console.log("HTML5 CallbackOnGenericMotionEvent playerNum="+playerNum+" axis="+axis+" val="+val);
onGenericMotionEvent(playerNum, axis, val);
},
function(err) {
console.error("HTML5 setCallbackOnGenericMotionEvent Failed: "+err);
},
"OuyaSDK", "setCallbackOnGenericMotionEvent", [ "" ]);
cordova.exec(
function(jsonData) {
var jsonObject = JSON.parse(jsonData);
var playerNum = jsonObject.playerNum;
var button = jsonObject.button;
//console.log("HTML5 CallbackOnKeyUp playerNum="+playerNum+" button="+button);
onKeyUp(playerNum, button);
},
function(err) {
console.error("HTML5 setCallbackOnKeyUp Failed: "+err);
},
"OuyaSDK", "setCallbackOnKeyUp", [ "" ]);
cordova.exec(
function(jsonData) {
var jsonObject = JSON.parse(jsonData);
var playerNum = jsonObject.playerNum;
var button = jsonObject.button;
//console.log("HTML5 CallbackonKeyDown playerNum="+playerNum+" button="+button);
onKeyDown(playerNum, button);
},
function(err) {
console.error("HTML5 setCallbackOnKeyDown Failed: "+err);
},
"OuyaSDK", "setCallbackOnKeyDown", [ "" ]);
}
Wait for the document to load before making calls to the Cordova
API, by using the body
to register the onload
callback.
<body onload="onLoad()">
Your HTML5 page can set callbacks in order to receive events from Cordova
for Axis and Button events.
The Integer PlayerNum is zero based (0, 1, 2, 3)
and indicates which controller had the axis event.
The Axis is the integer Axis Number.
var OuyaController = {
AXIS_LS_X: 0,
AXIS_LS_Y: 1,
AXIS_RS_X: 11,
AXIS_RS_Y: 14,
AXIS_L2: 17,
AXIS_R2: 18};
Val is the float value of the input for that axis.
function onGenericMotionEvent(playerNum, axis, val) {
if (axis == OuyaController.AXIS_LS_X) {
}
if (axis == OuyaController.AXIS_LS_Y) {
}
if (axis == OuyaController.AXIS_RS_X) {
}
if (axis == OuyaController.AXIS_RS_Y) {
}
if (axis == OuyaController.AXIS_L2) {
}
if (axis == OuyaController.AXIS_R2) {
}
}
The Integer PlayerNum
is zero based (0, 1, 2, 3)
and indicates which controller had the axis event.
The Integer Button
is the button in the event.
var OuyaController = {
BUTTON_O: 96,
BUTTON_U: 99,
BUTTON_Y: 100,
BUTTON_A: 97,
BUTTON_L1: 102,
BUTTON_R1: 103,
BUTTON_L3: 106,
BUTTON_R3: 107,
BUTTON_DPAD_UP: 19,
BUTTON_DPAD_DOWN: 20,
BUTTON_DPAD_RIGHT: 22,
BUTTON_DPAD_LEFT: 21,
BUTTON_MENU: 82};
The key down event indicates a button was just pressed.
function onKeyDown(playerNum, button) {
if (button == OuyaController.BUTTON_O) {
}
if (button == OuyaController.BUTTON_U) {
}
if (button == OuyaController.BUTTON_Y) {
}
if (button == OuyaController.BUTTON_A) {
}
if (button == OuyaController.BUTTON_L1) {
}
if (button == OuyaController.BUTTON_R1) {
}
if (button == OuyaController.BUTTON_L3) {
}
if (button == OuyaController.BUTTON_R3) {
}
if (button == OuyaController.BUTTON_DPAD_UP) {
}
if (button == OuyaController.BUTTON_DPAD_DOWN) {
}
if (button == OuyaController.BUTTON_DPAD_RIGHT) {
}
if (button == OuyaController.BUTTON_DPAD_LEFT) {
}
if (button == OuyaController.BUTTON_MENU) {
}
}
The key up event indicates a button was just released.
function onKeyUp(playerNum, button) {
if (button == OuyaController.BUTTON_O) {
}
if (button == OuyaController.BUTTON_U) {
}
if (button == OuyaController.BUTTON_Y) {
}
if (button == OuyaController.BUTTON_A) {
}
if (button == OuyaController.BUTTON_L1) {
}
if (button == OuyaController.BUTTON_R1) {
}
if (button == OuyaController.BUTTON_L3) {
}
if (button == OuyaController.BUTTON_R3) {
}
if (button == OuyaController.BUTTON_DPAD_UP) {
}
if (button == OuyaController.BUTTON_DPAD_DOWN) {
}
if (button == OuyaController.BUTTON_DPAD_RIGHT) {
}
if (button == OuyaController.BUTTON_DPAD_LEFT) {
}
if (button == OuyaController.BUTTON_MENU) {
}
}
The plugin methods are defined on the OuyaSDK object.
var OuyaSDK = new Object();
The developer id is displayed in the developer portal and is used to initialize the OUYA Plugin.
Avoid invoking IAP methods until after the OUYA Plugin has been initialized.
Upon success, the onSuccess callback will be invoked.
If the initialization fails, the onFailure callback will be invoked.
// Plugin method definition
OuyaSDK.initOuyaPlugin = function(jsonData, onSuccess, onFailure) {
if (cordova.exec == undefined) {
onFailure(0, "Wait for plugin to load!");
return;
}
cordova.exec(
function(status) {
console.log("HTML5 initOuyaPlugin: SUCCESS status="+status);
if (status == "WAIT") {
//console.log("**********************HTML5 initOuyaPlugin: Waiting for result...");
} else if (status == "SUCCESS") {
onSuccess();
} else {
onFailure(0, "Unknown success state!");
}
},
function(jsonObject) {
var errorCode = jsonObject.errorCode;
var errorMessage = jsonObject.errorMessage;
console.error("HTML5 initOuyaPlugin: FAILURE errorCode="+errorCode+" errorMessage="+errorMessage);
onFailure(errorCode, errorMessage);
},
"OuyaSDK", "initOuyaPlugin", [ jsonData ]);
};
// Prepare the plugin initialization values
var data = Array();
data[0] =
{
'key': 'tv.ouya.developer_id',
'value': '310a8f51-4d6e-4ae5-bda0-b93878e5f5d0'
};
var jsonData = JSON.stringify(data);
// Invoke the plugin method
OuyaSDK.initOuyaPlugin(jsonData, onSuccessInitOuyaPlugin, onFailureInitOuyaPlugin);
initOuyaPlugin
supports additional strings to make the game compatible with OUYA Everywhere devices.
-
tv.ouya.developer_id
- The developer UUID can be found in the developer portal after logging in. -
com.xiaomi.app_id
- The Xiaomi App Id is provided by the content team, email[email protected]
to obtain your key. -
com.xiaomi.app_key
- The Xiaomi App Key is provided by the content team, email[email protected]
to obtain your key. -
tv.ouya.product_id_list
- The product id list is a comma separated list of product ids that can be purchased in the game.
// Plugin method definition
OuyaSDK.initOuyaPlugin = function(jsonData, onSuccess, onFailure) {
if (cordova.exec == undefined) {
onFailure(0, "Wait for plugin to load!");
return;
}
cordova.exec(
function(status) {
console.log("HTML5 initOuyaPlugin: SUCCESS status="+status);
if (status == "WAIT") {
//console.log("**********************HTML5 initOuyaPlugin: Waiting for result...");
} else if (status == "SUCCESS") {
onSuccess();
} else {
onFailure(0, "Unknown success state!");
}
},
function(jsonObject) {
var errorCode = jsonObject.errorCode;
var errorMessage = jsonObject.errorMessage;
console.error("HTML5 initOuyaPlugin: FAILURE errorCode="+errorCode+" errorMessage="+errorMessage);
onFailure(errorCode, errorMessage);
},
"OuyaSDK", "initOuyaPlugin", [ jsonData ]);
};
// Prepare the plugin initialization values
var data = Array();
data[0] =
{
'key': 'tv.ouya.developer_id',
'value': '00000000-0000-0000-0000-000000000000'
};
data[1] =
{
'key': 'com.xiaomi.app_id',
'value': '0000000000000'
};
data[2] =
{
'key': 'com.xiaomi.app_key',
'value': '000000000000000000'
};
data[3] =
{
'key': 'tv.ouya.product_id_list',
'value': 'long_sword,sharp_axe,cool_level,awesome_sauce'
};
var jsonData = JSON.stringify(data);
// Invoke the plugin method
OuyaSDK.initOuyaPlugin(jsonData, onSuccessInitOuyaPlugin, onFailureInitOuyaPlugin);
The gamer info contains the username and gamer uuid.
The onSuccess callback receives the gamer info.
The onFailure callback receives an error code and error message.
The onCancel callback invokes if the request was cancelled.
// Plugin method definition
OuyaSDK.requestGamerInfo = function(onSuccess, onFailure, onCancel) {
if (cordova.exec == undefined) {
onFailure(0, "Wait for plugin to load!");
return;
}
cordova.exec(
function(jsonObject) {
//console.log("HTML5 requestGamerInfo: SUCCESS");
onSuccess(jsonObject);
},
function(jsonObject) {
var errorCode = jsonObject.errorCode;
var errorMessage = jsonObject.errorMessage;
console.error("HTML5 requestGamerInfo: FAILURE errorCode="+errorCode+" errorMessage="+errorMessage);
onFailure(errorCode, errorMessage);
},
"OuyaSDK", "requestGamerInfo", [ ]);
};
// Invoke the plugin method
OuyaSDK.requestGamerInfo(onSuccessRequestGamerInfo, onFailureRequestGamerInfo, onCancelRequestGamerInfo);
The product info contains the description price information.
The product parameter is passed an array of product identifiers.
The onSuccess callback receives an array of product details.
The onFailure callback receives an error code and error message.
The onCancel callback invokes if the request was cancelled.
// Plugin method definition
OuyaSDK.requestProducts = function(products, onSuccess, onFailure, onCancel) {
if (cordova.exec == undefined) {
onFailure(0, "Wait for plugin to load!");
return;
}
cordova.exec(
function(jsonObject) {
//console.log("HTML5 requestProducts: SUCCESS: products="+jsonObject.toString());
onSuccess(jsonObject);
},
function(jsonObject) {
var errorCode = jsonObject.errorCode;
var errorMessage = jsonObject.errorMessage;
console.error("HTML5 requestProducts: FAILURE errorCode="+errorCode+" errorMessage="+errorMessage);
onFailure(errorCode, errorMessage);
},
"OuyaSDK", "requestProducts", [ products ]);
};
// Invoke the plugin method
var products = Array("YOUR_PRODUCT_1", "YOUR_PRODUCT_2", "YOUR_PRODUCT3");
OuyaSDK.requestProducts(products, onSuccessRequestProducts, onFailureRequestProducts, onCancelRequestProducts)
The purchable parameter is the product identifier being purchased.
The onSuccess callback indicates successful purchase.
The onFailure callback indicates the purchase failed.
The onCancel callback indicates the purchase was cancelled.
// Plugin method definition
OuyaSDK.requestPurchase = function(purchasable, onSuccess, onFailure, onCancel) {
if (cordova.exec == undefined) {
onFailure(0, "Wait for plugin to load!");
return;
}
cordova.exec(
function(jsonObject) {
//console.log("HTML5 requestPurchase: SUCCESS: identifier="+jsonObject.productIdentifier);
onSuccess(jsonObject.productIdentifier);
},
function(jsonObject) {
var errorCode = jsonObject.errorCode;
var errorMessage = jsonObject.errorMessage;
console.error("HTML5 requestPurchase: FAILURE errorCode="+errorCode+" errorMessage="+errorMessage);
onFailure(errorCode, errorMessage);
},
"OuyaSDK", "requestPurchase", [ purchasable ]);
};
// Invoke the plugin method
var purchasable = "YOUR_PRODUCT_ID";
OuyaSDK.requestPurchase(purchasable, onSuccessRequestPurchase, onFailureRequestPurchase, onCancelRequestPurchase);
The onSuccess callback receives an array of receipts that the gamer purchased from the developer.
The onSuccess callback receives an error code and error message about why the request failed.
The onCancel callback indicates the request was cancelled.
// Plugin method definition
OuyaSDK.requestReceipts = function(onSuccess, onFailure, onCancel) {
if (cordova.exec == undefined) {
onFailure(0, "Wait for plugin to load!");
return;
}
cordova.exec(
function(jsonArray) {
//console.log("HTML5 requestReceipts: SUCCESS: jsonObject="+jsonArray.toString());
onSuccess(jsonArray);
},
function(jsonObject) {
var errorCode = jsonObject.errorCode;
var errorMessage = jsonObject.errorMessage;
console.error("HTML5 requestReceipts: FAILURE errorCode="+errorCode+" errorMessage="+errorMessage);
onFailure(errorCode, errorMessage);
},
"OuyaSDK", "requestReceipts", [ ]);
};
// Invoke the plugin method
OuyaSDK.requestReceipts(onSuccessRequestReceipts, onFailureRequestReceipts, onCancelRequestReceipts);
The safe area is explained in detail in the content-review-guidelines.
The safe area for HTML5 apps can be adjusted with setSafeArea.
The amount parameter adds full padding with 0.0 and no padding with 1.0.
The onSuccess callback indicates the safe area was set.
The onFailure callback indicates the request to set the safe area failed.
// Plugin method definition
OuyaSDK.setSafeArea = function(amount, onSuccess, onFailure) {
if (cordova.exec == undefined) {
onFailure(0, "Wait for plugin to load!");
return;
}
cordova.exec(
function() {
console.log("HTML5 setSafeArea: SUCCESS");
onSuccess();
},
function(jsonObject) {
var errorCode = jsonObject.errorCode;
var errorMessage = jsonObject.errorMessage;
console.error("HTML5 setSafeArea: FAILURE errorCode="+errorCode+" errorMessage="+errorMessage);
onFailure(errorCode, errorMessage);
},
"OuyaSDK", "setSafeArea", [ amount ]);
}
// Invoke the plugin method
var safeAreaAmount = 0.0; //full border padding
OuyaSDK.setSafeArea(safeAreaAmount, onSuccessSetSafeArea, onFailureSetSafeArea);
Device identification is part of OUYA-Everywhere. HTML5 apps can use device specific game logic and media using the name from getDeviceHardware.
The onSuccess callback receives the name of the device hardware.
The onFailure callback indicates the request to get the device hardware failed.
// Plugin method definition
OuyaSDK.getDeviceHardware = function(onSuccess, onFailure) {
if (cordova.exec == undefined) {
onFailure(0, "Wait for plugin to load!");
return;
}
cordova.exec(
function(jsonObject) {
//console.log("HTML5 getDeviceHardware: SUCCESS");
onSuccess(jsonObject.deviceHardware);
},
function(jsonObject) {
var errorCode = jsonObject.errorCode;
var errorMessage = jsonObject.errorMessage;
console.error("HTML5 getDeviceHardware: FAILURE errorCode="+errorCode+" errorMessage="+errorMessage);
onFailure(errorCode, errorMessage);
},
"OuyaSDK", "getDeviceHardware", [ ]);
}
// Invoke the plugin method
OuyaSDK.getDeviceHardware(onSuccessGetDeviceHardware, onFailureGetDeviceHardware);
The onSuccess callback receives the String
name of the device hardware. The device name
can be used to show an alternate set of buttons, for example.
function onSuccessGetDeviceHardware(name) {
deviceHardware = name;
lblStatus = "received device hardware="+deviceHardware;
redraw = true;
}
Shutdown provides a way to exit the HTML5 application.
The onSuccess callback indicates the shutdown is about to happen.
The onFailure callback indicates the request to shutdown failed.
// Plugin method definition
OuyaSDK.shutdown = function(onSuccess, onFailure) {
if (cordova.exec == undefined) {
onFailure(0, "Wait for plugin to load!");
return;
}
cordova.exec(
function() {
console.log("HTML5 shutdown: SUCCESS");
onSuccess();
},
function(jsonObject) {
var errorCode = jsonObject.errorCode;
var errorMessage = jsonObject.errorMessage;
console.error("HTML5 shutdown: FAILURE errorCode="+errorCode+" errorMessage="+errorMessage);
onFailure(errorCode, errorMessage);
},
"OuyaSDK", "shutdown", [ ]);
}
// Invoke the plugin method
OuyaSDK.shutdown(onSuccessShutdown, onFailureShutdown);