Much like the Adobe AIR framework, PhoneGap supports native extensions that enhance what you can do with the platform. In the PhoneGap world these are called plugins and a good number of them, for Android, iOS, Blackberry, and Palm, already exist. You can find all of the currently supported plugins at their Github repo: https://github.com/phonegap/phonegap-plugins. I played with plugins this morning and here is what I found.
Installing plugins, at least for Android, is relatively simple.
- First you copy a JavaScript file to project. This is your interface to the lower level code.
- Then you copy a Java class. Remember to refresh your project. My code wasn't working at first and a refresh fixed it up right away.
- You edit one XML file to have the project recognize the plugin.
And that's it. Of course, you have to include the JavaScript wrapper and actually make use of the plugin. For my first experiment, I tried the TTS (Text To Speech) plugin, which worked great. Check out the code here.
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=320; user-scalable=no" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>TTS</title>
<script type="text/javascript" charset="utf-8" src="phonegap-1.1.0.js"></script>
<script type="text/javascript" charset="utf-8" src="tts.js"></script>
<script>
function readySpeak(){
window.plugins.tts.startup(doSpeak, errHandler);
}
function doSpeak() {
window.plugins.tts.speak("The TTS service is ready", {} , errHandler);
}
function errHandler(result){
alert('Error: ' + result);
}
function init(){
document.addEventListener("deviceready", readySpeak, false);
}
</script>
</head>
<body onload="init();">
</body>
</html>
As you can see I have a few things I need to do before using the plugin. I listen for the deviceready event (that's a PhoneGap event), then start up the TTS service. Once it is ready it is trivial then to actually make the device speak. The TTS plugin has a few interesting options and for the most part it should be easy to figure out.
Once I got this working, I decided to go a bit crazy. If I can do text to speech, I bet I can do speech to text. Turns out there is also a plugin for speech recognition. The API was a bit hard to grok (and the docs were minimal), but check out the result.
The full source is below. This is a big hack and won't scroll properly if you run it too long, but... it was fun as hell to build!
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=320; user-scalable=no" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>TTS</title>
<script type="text/javascript" charset="utf-8" src="phonegap-1.1.0.js"></script>
<script type="text/javascript" charset="utf-8" src="tts.js"></script>
<script type="text/javascript" charset="utf-8" src="SpeechRecognizer.js"></script>
<script src="jquery.js"></script>
<script src="elizabot.js"></script>
<script src="elizadata.js"></script>
<script>
var eliza = new ElizaBot();
//Start up stuff... should be chained...
function readySpeakService(){
window.plugins.tts.startup(doLanguage, errHandler);
}
//See if we can British, cuz Brits sound smart.
function doLanguage(result) {
if (result == TTS.STARTED) {
window.plugins.tts.isLanguageAvailable("en_GB", makeBritish, errHandler);
}
}
//Make me a brit. Cheerio!
function makeBritish(){
window.plugins.tts.setLanguage("en_GB", startRecog, errHandler);
}
//Done with all TTS, switch to recog
function startRecog() {
window.plugins.speechrecognizer.init(speechInitOk, errHandler)
}
function speechInitOk(){
startEliza();
}
function startEliza(){
var initial = eliza.getInitial();
window.plugins.tts.speak(initial, {} , errHandler);
addChat("Eliza: "+initial);
}
function addChat(str){
$("#chatBox").append(str+"<br/>");
}
function listen(){
var requestCode = 1234;
var maxMatches = 5;
var promptString = "Please say something...";
window.plugins.speechrecognizer.startRecognize(speechOk, errHandler, requestCode, maxMatches, promptString);
}
function speechOk(result) {
var match, respObj, requestCode;
if (result) {
respObj = JSON.parse(result);
if (respObj) {
// This is the code that was sent with the original request
requestCode = respObj.speechMatches.requestCode;
//assume one...
var response = respObj.speechMatches.speechMatch[0];
addChat("You said: "+response);
var reply = eliza.transform(response);
window.plugins.tts.speak(reply, {} , errHandler);
addChat("Eliza: " + reply);
}
}
}
function errHandler(err){
alert('Error: ' + err);
}
function init(){
document.addEventListener("deviceready", readySpeakService, false);
$("#speakButton").click(function() {
listen();
});
window.onerror = errHandler;
}
</script>
<style>
#chatBox {
width: 100%;
padding-left: 5px;
padding-right: 5px;
padding-top:5px;
height: 80%;
}
#speakButton {
width: 100%;
height: 20%;
}
</style>
</head>
<body onload="init();">
<div id="chatBox"></div>
<button id="speakButton">Speak</button>
</body>
</html>