Author: kmorin Date: 2014-04-03 14:20:29 +0200 (Thu, 03 Apr 2014) New Revision: 41 Url: http://forge.chorem.org/projects/say-my-texts/repository/revisions/41 Log: refs #999 Answer to a sms Added: trunk/src/org/chorem/android/saymytexts/SayNextActionBroadcastReceiver.java Modified: trunk/res/values-fr/strings.xml trunk/res/values/strings.xml trunk/src/org/chorem/android/saymytexts/SayMyTextService.java Modified: trunk/res/values/strings.xml =================================================================== --- trunk/res/values/strings.xml 2014-04-02 11:59:25 UTC (rev 40) +++ trunk/res/values/strings.xml 2014-04-03 12:20:29 UTC (rev 41) @@ -29,6 +29,7 @@ <string name="crash_dialog_ok_toast">Thank you !</string> <!-- actions --> + <string name="ask_next_action">What would you like to do? Call, answer or quit?</string> <string name="call_action">call</string> <string name="answer_action">answer</string> <string name="quit_action">quit</string> Modified: trunk/res/values-fr/strings.xml =================================================================== --- trunk/res/values-fr/strings.xml 2014-04-02 11:59:25 UTC (rev 40) +++ trunk/res/values-fr/strings.xml 2014-04-03 12:20:29 UTC (rev 41) @@ -28,6 +28,8 @@ <string name="crash_dialog_ok_toast">Merci !</string> <!-- actions --> + <string name="ask_next_action">Que voulez-vous faire ? Appeler, répondre ou quitter ?</string> + <string name="call_action">appeler</string> <string name="answer_action">répondre</string> <string name="quit_action">quitter</string> Modified: trunk/src/org/chorem/android/saymytexts/SayMyTextService.java =================================================================== --- trunk/src/org/chorem/android/saymytexts/SayMyTextService.java 2014-04-02 11:59:25 UTC (rev 40) +++ trunk/src/org/chorem/android/saymytexts/SayMyTextService.java 2014-04-03 12:20:29 UTC (rev 41) @@ -24,34 +24,21 @@ * #L% */ -import android.app.PendingIntent; import android.app.Service; import android.bluetooth.BluetoothDevice; -import android.content.ActivityNotFoundException; import android.content.BroadcastReceiver; -import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; -import android.content.pm.PackageManager; -import android.database.Cursor; import android.media.AudioManager; -import android.net.Uri; -import android.os.Bundle; import android.os.IBinder; import android.preference.PreferenceManager; -import android.provider.BaseColumns; -import android.provider.ContactsContract; -import android.speech.RecognitionListener; -import android.speech.RecognizerIntent; -import android.speech.SpeechRecognizer; import android.speech.tts.TextToSpeech; import android.speech.tts.UtteranceProgressListener; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.util.Log; -import android.widget.Toast; import java.util.ArrayList; import java.util.Collections; @@ -79,7 +66,8 @@ /** utterance id when the bluetooth device is connected */ protected static final String BT_UTTERANCE_ID = "btUtteranceId"; - protected static final String OTHER_UTTERANCE_ID = "otherUtteranceId"; + protected static final String BT_ASK_NEXT_ACTION_UTTERANCE_ID = "btAskNextActionUtteranceId"; + protected static final String ASK_NEXT_ACTION_UTTERANCE_ID = "askNextActionUtteranceId"; protected AudioManager audioManager; @@ -88,8 +76,6 @@ protected TextToSpeech textToSpeech; - protected SpeechRecognizer speechRecognizer; - /** texts to read, received before the textospeech is ready or while a call is in progress */ protected List<SMS> awaitingTexts = new ArrayList<>(); @@ -114,12 +100,14 @@ super.onCreate(); textToSpeech = new TextToSpeech(this, this); - speechRecognizer = SpeechRecognizer.createSpeechRecognizer(SayMyTextService.this); audioManager = (AudioManager) getSystemService(AUDIO_SERVICE); TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); tm.listen(callStateListener, PhoneStateListener.LISTEN_CALL_STATE); + + IntentFilter intentFilter = new IntentFilter(SayNextActionBroadcastReceiver.ACTION_SAY_NEXT_ACTION); + registerReceiver(new SayNextActionBroadcastReceiver(), intentFilter); } @Override @@ -177,28 +165,6 @@ @Override public void onInit(int status) { if (status == TextToSpeech.SUCCESS) { - // init texttospeech - textToSpeech.setOnUtteranceProgressListener(new UtteranceProgressListener() { - @Override - public void onStart(String utteranceId) { - } - - @Override - public void onError(String utteranceId) { - Log.e(TAG, "Error speaking: " + utteranceId); - } - - @Override - public void onDone(String utteranceId) { - if (BT_UTTERANCE_ID.equals(utteranceId)) { - // when the text has been read by the bluetooth device, stop the connection - audioManager.stopBluetoothSco(); - audioManager.setMode(AudioManager.MODE_NORMAL); - } - waiting = false; - } - }); - TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); setCanSpeak(tm.getCallState() == TelephonyManager.CALL_STATE_IDLE); @@ -268,16 +234,48 @@ * @param btConnected if true, adds the utterance id for the bluetooth device */ protected void readText(List<SMS> smsList, boolean btConnected) { - HashMap<String, String> params = new HashMap<>(); - params.put(TextToSpeech.Engine.KEY_PARAM_STREAM, String.valueOf(AudioManager.STREAM_VOICE_CALL)); - params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, btConnected ? BT_UTTERANCE_ID : OTHER_UTTERANCE_ID); - SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); String heisendroidModeEnabledKey = getString(R.string.preference_enable_heisendroid_mode_key); boolean heisendroidModeEnabled = sharedPref.getBoolean(heisendroidModeEnabledKey, true); - for (SMS sms : smsList) { - waiting = true; + for (final SMS sms : smsList) { +// waiting = true; + + // init texttospeech + textToSpeech.setOnUtteranceProgressListener(new UtteranceProgressListener() { + @Override + public void onStart(String utteranceId) { + } + + @Override + public void onError(String utteranceId) { + Log.e(TAG, "Error speaking: " + utteranceId); + } + + @Override + public void onDone(String utteranceId) { + if (BT_UTTERANCE_ID.equals(utteranceId) || + BT_ASK_NEXT_ACTION_UTTERANCE_ID.equals(utteranceId)) { + // when the text has been read by the bluetooth device, stop the connection + audioManager.stopBluetoothSco(); + audioManager.setMode(AudioManager.MODE_NORMAL); + } + + if (ASK_NEXT_ACTION_UTTERANCE_ID.equals(utteranceId) || + BT_ASK_NEXT_ACTION_UTTERANCE_ID.equals(utteranceId)) { + Intent sayaction = new Intent(SayNextActionBroadcastReceiver.ACTION_SAY_NEXT_ACTION); + sayaction.putExtra(SayNextActionBroadcastReceiver.EXTRA_SMS, sms); + sendBroadcast(sayaction); + } + } + }); + + HashMap<String, String> params = new HashMap<>(); + params.put(TextToSpeech.Engine.KEY_PARAM_STREAM, String.valueOf(AudioManager.STREAM_VOICE_CALL)); + if (btConnected) { + params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, BT_UTTERANCE_ID); + } + if (heisendroidModeEnabled) { textToSpeech.setLanguage(Locale.US); textToSpeech.setSpeechRate(0.3f); @@ -298,91 +296,13 @@ textToSpeech.speak("You're goddamn right.", TextToSpeech.QUEUE_ADD, params); } - while (waiting) { - } - waiting = true; - recognizeVoice(sms); - while (waiting) { - } + params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, + btConnected ? BT_ASK_NEXT_ACTION_UTTERANCE_ID : ASK_NEXT_ACTION_UTTERANCE_ID); + textToSpeech.setLanguage(Locale.getDefault()); + textToSpeech.setSpeechRate(1f); + textToSpeech.setPitch(1f); + textToSpeech.speak(getString(R.string.ask_next_action), TextToSpeech.QUEUE_ADD, params); } } - protected void recognizeVoice(final SMS sms) { - Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); - // Specify free form input - intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, - RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); - - speechRecognizer.setRecognitionListener(new RecognitionListener() { - @Override - public void onReadyForSpeech(Bundle params) { - } - - @Override - public void onBeginningOfSpeech() { - } - - @Override - public void onRmsChanged(float rmsdB) { - } - - @Override - public void onBufferReceived(byte[] buffer) { - } - - @Override - public void onEndOfSpeech() { - } - - @Override - public void onError(int error) { - Log.d(TAG, "onError " + error); - waiting = false; - } - - @Override - public void onResults(Bundle data) { - List<String> results = data.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); - - Log.d(TAG, "results " + results); - if (results != null) { - - if (results.contains(getString(R.string.call_action))) { - try { - Intent callIntent = new Intent(Intent.ACTION_CALL); - callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - callIntent.setData(Uri.parse("tel:" + sms.getSenderNumber())); - startActivity(callIntent); - - } catch (ActivityNotFoundException activityException) { - Log.e("Calling a Phone Number", "Call failed", activityException); - } - - } else if (results.contains(getString(R.string.answer_action))) { - //TODO ask the user to dictate the message - } else if (results.contains(getString(R.string.quit_action))) { - // do nothing - } else { - //TODO add a counter to ask only twice (or 3 times, or it should be configurable) - recognizeVoice(sms); - } - } - - waiting = false; - } - - @Override - public void onPartialResults(Bundle partialResults) { - } - - @Override - public void onEvent(int eventType, Bundle params) { - } - }); - - speechRecognizer.startListening(intent); - } - - boolean waiting = false; - } Added: trunk/src/org/chorem/android/saymytexts/SayNextActionBroadcastReceiver.java =================================================================== --- trunk/src/org/chorem/android/saymytexts/SayNextActionBroadcastReceiver.java (rev 0) +++ trunk/src/org/chorem/android/saymytexts/SayNextActionBroadcastReceiver.java 2014-04-03 12:20:29 UTC (rev 41) @@ -0,0 +1,111 @@ +package org.chorem.android.saymytexts; + +import android.content.ActivityNotFoundException; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.speech.RecognitionListener; +import android.speech.RecognizerIntent; +import android.speech.SpeechRecognizer; +import android.util.Log; + +import java.util.List; + +/** + * @author Kevin Morin (Code Lutin) + * @since x.x + */ +public class SayNextActionBroadcastReceiver extends BroadcastReceiver { + + private static final String TAG = "SayNextActionBroadcastReceiver"; + + public static final String ACTION_SAY_NEXT_ACTION = "org.chorem.android.saymytexts.SAY_NEXT_ACTION"; + + public static final String EXTRA_SMS = "sms"; + + protected SpeechRecognizer speechRecognizer; + + @Override + public void onReceive(final Context context, Intent intent) { + Log.d(TAG, "next action ?"); + final SMS sms = (SMS) intent.getSerializableExtra(EXTRA_SMS); + + if (sms != null) { + speechRecognizer = SpeechRecognizer.createSpeechRecognizer(context); + speechRecognizer.setRecognitionListener(new RecognitionListener() { + @Override + public void onReadyForSpeech(Bundle params) { + } + + @Override + public void onBeginningOfSpeech() { + } + + @Override + public void onRmsChanged(float rmsdB) { + } + + @Override + public void onBufferReceived(byte[] buffer) {} + + @Override + public void onEndOfSpeech() {} + + @Override + public void onError(int error) { + Log.d(TAG, "onError " + error); + //TODO if error 6 ERROR_SPEECH_TIMEOUT ask to say it again + //TODO if error 7 ERROR_NO_MATCH ask to say it again + //TODO if other error say there is an error + } + + @Override + public void onResults(Bundle data) { + List<String> results = data.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); + + Log.d(TAG, "results " + results); + if (results != null) { + + if (results.contains(context.getString(R.string.call_action))) { + try { + Intent callIntent = new Intent(Intent.ACTION_CALL); + callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + callIntent.setData(Uri.parse("tel:" + sms.getSenderNumber())); + context.startActivity(callIntent); + + } catch (ActivityNotFoundException activityException) { + Log.e(TAG, "Calling a Phone Number failed", activityException); + } + + } else if (results.contains(context.getString(R.string.answer_action))) { + //TODO ask the user to dictate the message + Log.d(TAG, "Répondre"); + + } else if (results.contains(context.getString(R.string.quit_action))) { + // do nothing + + } else { + //TODO add a counter to ask only twice (or 3 times, or it should be configurable) + // recognizeVoice(sms); + } + } + } + + @Override + public void onPartialResults(Bundle partialResults) {} + + @Override + public void onEvent(int eventType, Bundle params) {} + }); + + Intent recognizeIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); + // Specify free form input + recognizeIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, + RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); + + speechRecognizer.startListening(recognizeIntent); + } + } +}