Java tutorial
/* This file is part of HomeGenie for Adnroid. HomeGenie for Adnroid is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. HomeGenie for Adnroid is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with HomeGenie for Adnroid. If not, see <http://www.gnu.org/licenses/>. */ /* * Author: Generoso Martello <gene@homegenie.it> */ package com.glabs.homegenie.util; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.speech.RecognitionListener; import android.speech.RecognizerIntent; import android.speech.SpeechRecognizer; import android.util.Log; import android.widget.Toast; import com.glabs.homegenie.R; import com.glabs.homegenie.StartActivity; import com.glabs.homegenie.client.Control; import com.glabs.homegenie.client.data.Group; import com.glabs.homegenie.client.data.Module; import org.apache.http.HttpEntity; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; import org.apache.http.client.HttpResponseException; import org.apache.http.client.ResponseHandler; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import org.json.JSONArray; import org.json.JSONObject; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; import java.util.List; import java.util.Locale; /** * Created by Gene on 09/01/14. */ public class VoiceControl implements RecognitionListener { private StartActivity _hgcontext; private SpeechRecognizer _recognizer; private String _currentInput = ""; private LingoData _lingodata; private ResponseHandler<String> _response_handler = new ResponseHandler<String>() { public String handleResponse(final HttpResponse response) throws HttpResponseException, IOException { StatusLine statusLine = response.getStatusLine(); if (statusLine.getStatusCode() >= 300) { throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase()); } HttpEntity entity = response.getEntity(); return entity == null ? null : EntityUtils.toString(entity, "UTF-8"); } }; class RetrieveLingoDataTask extends AsyncTask<Void, Void, String> { private Exception exception; protected String doInBackground(Void... noargs) { try { HttpGet getRequest = Control.getHttpGetRequest(Control.getHgBaseHttpAddress() + "hg/html/locales/" + Locale.getDefault().getLanguage() + ".lingo.json"); DefaultHttpClient client = new DefaultHttpClient(); String data = client.execute(getRequest, _response_handler); if (data.trim().equals("")) { // fallback to english lingo definitions getRequest = Control .getHttpGetRequest(Control.getHgBaseHttpAddress() + "hg/html/locales/en.lingo.json"); client = new DefaultHttpClient(); data = client.execute(getRequest, _response_handler); } return data; } catch (Exception e) { this.exception = e; return ""; } } protected void onPostExecute(String data) { try { // Parse the data into jsonobject to get original data in form of json. JSONObject jobject = new JSONObject(data); JSONArray jtypes = jobject.getJSONArray("Types"); JSONArray jcommands = jobject.getJSONArray("Commands"); // for (int i = 0; i < jtypes.length(); i++) { JSONObject type = jtypes.getJSONObject(i); LingoType ltype = new LingoType(); ltype.Type = type.getString("Type"); JSONArray aliases = type.getJSONArray("Aliases"); for (int a = 0; a < aliases.length(); a++) { ltype.Aliases.add(aliases.getString(a)); } _lingodata.Types.add(ltype); } for (int i = 0; i < jcommands.length(); i++) { JSONObject command = jcommands.getJSONObject(i); LingoCommand lcmd = new LingoCommand(); lcmd.Command = command.getString("Command"); JSONArray aliases = command.getJSONArray("Aliases"); for (int a = 0; a < aliases.length(); a++) { lcmd.Aliases.add(aliases.getString(a)); } _lingodata.Commands.add(lcmd); } } catch (Exception e) { e.printStackTrace(); } } } public VoiceControl(StartActivity hgactivity) { _hgcontext = hgactivity; //find out whether speech recognition is supported PackageManager packManager = _hgcontext.getPackageManager(); List<ResolveInfo> intActivities = packManager .queryIntentActivities(new Intent(RecognizerIntent.ACTION_WEB_SEARCH), 0); if (intActivities.size() != 0) { // TODO ok speech recognition supported } else { //speech recognition not supported, disable button and output message Toast.makeText(_hgcontext, "Oops - Speech recognition not supported!", Toast.LENGTH_LONG).show(); } _lingodata = new LingoData(); new RetrieveLingoDataTask().execute(); } public void startListen() { _recognizer = getSpeechRecognizer(); _recognizer.setRecognitionListener(this); // //speech recognition is supported - detect user button clicks //start the speech recognition intent passing required data Intent recognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); //indicate package //recognizerIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, getClass().getPackage().getName()); //message to display while listening recognizerIntent.putExtra(RecognizerIntent.EXTRA_PROMPT, "Your wish is my command!"); //set speech model recognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); //specify number of results to retrieve recognizerIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1); //start listening //startActivityForResult(listenIntent, VR_REQUEST); //startActivityForResult(recognizerIntent, VR_REQUEST); _recognizer.startListening(recognizerIntent); } public void interpretInput(String sentence) { _currentInput = sentence; Handler hnd = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message message) { return false; } }); hnd.postDelayed(new Runnable() { @Override public void run() { _doInterpretInput(); } }, 100); } private void _doInterpretInput() { boolean continueparsing = true; while (continueparsing) { continueparsing = false; // String command = searchCommandMatch(); LingoMatch nextcommand = getCommandMatch(); String type = searchTypeMatch(false); String group = searchGroupMatch(nextcommand.StartIndex); // if (!command.equals("") && !type.equals("")) { String[] types = type.split(","); ArrayList<Module> groupmodules = getGroupModules(group); // for (Module module : groupmodules) { for (int t = 0; t < types.length; t++) { if (module.DeviceType != null && types[t].toLowerCase().equals(module.DeviceType.toLowerCase())) { module.control(command, new Control.ServiceCallCallback() { @Override public void serviceCallCompleted(String response) { } }); continueparsing = true; // try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } } } else { Module module = searchSubjectMatch(group, nextcommand.StartIndex); // if (module != null && !command.equals("")) { module.control(command, new Control.ServiceCallCallback() { @Override public void serviceCallCompleted(String response) { } }); continueparsing = true; // try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } //alert(group + ' ' + command + ' ' + module.Name); } // } } public String searchTypeMatch(boolean keepsentence) { String result = ""; LingoMatch curmatch = new LingoMatch("", -1); for (LingoType t : getTypes()) { for (int c = 0; c < t.Aliases.size(); c++) { LingoMatch res = findMatchingInput(t.Aliases.get(c)); if (res.StartIndex != -1 && (res.StartIndex < curmatch.StartIndex || curmatch.StartIndex == -1)) { result = t.Type; curmatch = res; // break; } } } // if (!keepsentence && curmatch.StartIndex != -1) { removeInputMatch(curmatch); } return result; } public LingoMatch getCommandMatch() { LingoMatch curmatch = new LingoMatch("", -1); for (LingoCommand cmd : getCommands()) { for (int c = 0; c < cmd.Aliases.size(); c++) { LingoMatch res = findMatchingInput(cmd.Aliases.get(c)); if (res.StartIndex != -1 && (res.StartIndex < curmatch.StartIndex || curmatch.StartIndex == -1)) { curmatch = res; // break; } } } // return curmatch; } public String searchCommandMatch() { String result = ""; LingoMatch curmatch = new LingoMatch("", -1); for (LingoCommand cmd : getCommands()) { for (int c = 0; c < cmd.Aliases.size(); c++) { LingoMatch res = findMatchingInput(cmd.Aliases.get(c)); if (res.StartIndex != -1 && (res.StartIndex < curmatch.StartIndex || curmatch.StartIndex == -1)) { result = cmd.Command; curmatch = res; // break; } } } // if (curmatch.StartIndex != -1) { removeInputMatch(curmatch); } return result; } public String searchGroupMatch(int limitindex) { String result = ""; LingoMatch curmatch = new LingoMatch("", -1); for (Group g : Control.getGroups()) { LingoMatch res = findMatchingInput(g.Name); if (res.StartIndex != -1 && (res.StartIndex < limitindex || limitindex == -1) && (res.StartIndex < curmatch.StartIndex || curmatch.StartIndex == -1)) { result = g.Name; curmatch = res; //break; } } if (curmatch.StartIndex != -1) { removeInputMatch(curmatch); } return result; } public Module searchSubjectMatch(String group, int limitindex) { Module result = null; ArrayList<Module> groupmodules; groupmodules = getGroupModules(group); // try finding a module name / address LingoMatch curmatch = new LingoMatch("", -1); for (Module module : groupmodules) { LingoMatch res = findMatchingInput(module.Name); if (res.StartIndex == -1) res = findMatchingInput(module.Address); // if (res.StartIndex != -1 && (res.Words.length() >= curmatch.Words.length()) && (res.StartIndex < limitindex || limitindex == -1) && (res.StartIndex <= curmatch.StartIndex || curmatch.StartIndex == -1)) { result = module; curmatch = res; //break; } } if (curmatch.StartIndex != -1) { removeInputMatch(curmatch); } return result; } public void removeInputMatch(LingoMatch wordsmatch) { if (wordsmatch.StartIndex > -1 && wordsmatch.Words.length() > 0) { _currentInput = _currentInput.substring(0, wordsmatch.StartIndex) + ' ' + _currentInput.substring(wordsmatch.StartIndex + wordsmatch.Words.length() - 1); } } public LingoMatch findMatchingInput(String words) { LingoMatch wordsmatch = new LingoMatch(words, -1); words = ' ' + words.toLowerCase() + ' '; int idx = (' ' + _currentInput.toLowerCase() + ' ').indexOf(words); if (idx >= 0 && !words.trim().equals("")) { wordsmatch.StartIndex = idx; return wordsmatch; } return wordsmatch; } private ArrayList<LingoCommand> getCommands() { return _lingodata.Commands; } private ArrayList<LingoType> getTypes() { return _lingodata.Types; } private ArrayList<Module> getGroupModules(String group) { ArrayList<Module> modules = new ArrayList<Module>(); if (group == null || group.equals("")) { modules = Control.getModules(); } else for (Group g : Control.getGroups()) { if (g.Name.toLowerCase().equals(group.toLowerCase())) { for (Module m : g.Modules) { if (m != null) { for (Module im : Control.getModules()) { if (m.Domain.equals(im.Domain) && m.Address.equals(im.Address)) { modules.add(im); } } } } break; } } return modules; } /* */ /** * lazy initialize the speech recognizer */ private SpeechRecognizer getSpeechRecognizer() { if (_recognizer == null) { _recognizer = SpeechRecognizer.createSpeechRecognizer(_hgcontext); _recognizer.setRecognitionListener(this); } return _recognizer; } public class LingoData { public ArrayList<LingoCommand> Commands = new ArrayList<LingoCommand>(); public ArrayList<LingoType> Types = new ArrayList<LingoType>(); } public class LingoCommand { public String Command; public ArrayList<String> Aliases = new ArrayList<String>(); } public class LingoType { public String Type; public ArrayList<String> Aliases = new ArrayList<String>(); } public class LingoMatch { public String Words = ""; public int StartIndex = -1; public LingoMatch(String words, int idx) { this.Words = words; this.StartIndex = idx; } } @Override public void onReadyForSpeech(Bundle bundle) { } @Override public void onBeginningOfSpeech() { } @Override public void onRmsChanged(float v) { } @Override public void onBufferReceived(byte[] bytes) { } @Override public void onEndOfSpeech() { } @Override public void onError(int i) { String message; switch (i) { case SpeechRecognizer.ERROR_AUDIO: message = "Audio recording error"; break; case SpeechRecognizer.ERROR_CLIENT: message = "Client side error"; //restart = false; break; case SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS: message = "Insufficient permissions"; //restart = false; break; case SpeechRecognizer.ERROR_NETWORK: message = "Network error"; break; case SpeechRecognizer.ERROR_NETWORK_TIMEOUT: message = "Network timeout"; break; case SpeechRecognizer.ERROR_NO_MATCH: message = "No match"; break; case SpeechRecognizer.ERROR_RECOGNIZER_BUSY: message = "RecognitionService busy"; break; case SpeechRecognizer.ERROR_SERVER: message = "error from server"; break; case SpeechRecognizer.ERROR_SPEECH_TIMEOUT: message = "No speech input"; break; default: message = "Not recognised"; break; } Toast.makeText(_hgcontext.getApplicationContext(), "Recognizer: " + message, 10000).show(); _recognizer.destroy(); _recognizer = null; } @Override public void onResults(Bundle results) { if ((results != null) && results.containsKey(SpeechRecognizer.RESULTS_RECOGNITION)) { List<String> heard = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); float[] scores = results.getFloatArray(SpeechRecognizer.CONFIDENCE_SCORES); String msg = ""; for (String s : heard) { Toast.makeText(_hgcontext.getApplicationContext(), "Executing: " + s, 20000).show(); interpretInput(s); // msg += s; break; } } } @Override public void onPartialResults(Bundle bundle) { } @Override public void onEvent(int i, Bundle bundle) { } }