I've a viewpager in my application. When the user swipes to the right/left I use TTS engine to speak the text and MediaPlayer to play a sound.
The problem is both plays simultaneously.. How do I play the sound once TTS engine speaks the text is over?
P.S: I don't want to use sleep or wait.
Update:
Here is my code:
#SuppressLint("NewApi")
#SuppressWarnings("deprecation")
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
if (result == TextToSpeech.LANG_MISSING_DATA
|| result == TextToSpeech.LANG_NOT_SUPPORTED) {
} else {
//Do Something here
}
if(Build.VERSION.SDK_INT >= 15 ){
UtteranceProgressListener listener = new UtteranceProgressListener() {
#Override
public void onStart(String utteranceId) {
// TODO Auto-generated method stub
}
#Override
public void onError(String utteranceId) {
// TODO Auto-generated method stub
}
#Override
public void onDone(String utteranceId) {
// TODO Auto-generated method stub
//start MediaPlayer
playMedia(viewPager.getCurrentItem());
}
};
tts.setOnUtteranceProgressListener(listener);
}
else{
tts.setOnUtteranceCompletedListener(new OnUtteranceCompletedListener(){
#Override
public void onUtteranceCompleted(String arg0) {
playMedia(viewPager.getCurrentItem());
}
});
}
} else {
Intent installIntent = new Intent();
installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installIntent);
}
}
You have to give it an id param. Otherwise it doesn't call the listeners:
HashMap<String, String> params = new HashMap<String, String>();
params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,"stringId");
textToSpeech.speak(string,TextToSpeech.QUEUE_ADD, params);
In android their are two APIs to detect if the TTS engine finished speaking:
> Android 4 (ICS)
UtteranceProgressListener listener = new UtteranceProgressListener() {
#Override
public void onStart(String utteranceId) {
// TODO Auto-generated method stub
}
#Override
public void onError(String utteranceId) {
// TODO Auto-generated method stub
}
#Override
public void onDone(String utteranceId) {
// TODO Auto-generated method stub
//start MediaPlayer
}
};
yourTTSObject.setOnUtteranceProgressListener(listener);
Perior to ICS Android 4.0 you can use :
yourTTSObject.setOnUtteranceCompletedListener(new OnUtteranceCompletedListener(){
#Override
public void onUtteranceCompleted(String arg0) {
// start your mediaplayer here
}
});
take a look at the documentations here
Related
I am trying to show flurry interstitial but getting following message in debug screen and I am not receiving interstitial on my screen.
07-14 15:55:31.390: W/webview(10588): java.lang.Throwable: Warning: A
WebView method was called on thread 'FlurryAgent'. All WebView methods
must be called on the UI thread. Future versions of WebView may not
support use on other threads.
I have followed this tutorial completely :
Android Integration
At present I am working on AndEngine. As error replying I put my all code in UI thread but result is same.
Here is my code for displaying ads :
protected void onCreate(Bundle pSavedInstanceState) {
super.onCreate(pSavedInstanceState);
// configure Flurry
FlurryAgent.setLogEnabled(false);
// init Flurry
FlurryAgent.init(MainGameActivity.this, MY_FLURRY_APIKEY);
mFlurryAdInterstitial = new FlurryAdInterstitial(MainGameActivity.this,
MY_ADSPACE_NAME);
FlurryAdTargeting adTargeting = new FlurryAdTargeting();
// enable test mode for this interstitial ad unit
adTargeting.setEnableTestAds(true);
mFlurryAdInterstitial.setTargeting(adTargeting);
// allow us to get callbacks for ad events
mFlurryAdInterstitial.setListener(interstitialAdListener);
mFlurryAdInterstitial.fetchAd();
}
FlurryAdInterstitialListener interstitialAdListener = new FlurryAdInterstitialListener() {
#Override
public void onFetched(final FlurryAdInterstitial adInterstitial) {
adInterstitial.displayAd();
}
#Override
public void onError(final FlurryAdInterstitial adInterstitial,
FlurryAdErrorType adErrorType, int errorCode) {
adInterstitial.destroy();
}
#Override
public void onAppExit(FlurryAdInterstitial arg0) {
// TODO Auto-generated method stub
}
#Override
public void onClicked(FlurryAdInterstitial arg0) {
// TODO Auto-generated method stub
}
#Override
public void onClose(FlurryAdInterstitial arg0) {
// TODO Auto-generated method stub
}
#Override
public void onDisplay(FlurryAdInterstitial arg0) {
// TODO Auto-generated method stub
}
#Override
public void onRendered(FlurryAdInterstitial arg0) {
// TODO Auto-generated method stub
}
#Override
public void onVideoCompleted(FlurryAdInterstitial arg0) {
// TODO Auto-generated method stub
}
};
#Override
protected void onStart() {
super.onStart();
FlurryAgent.onStartSession(MainGameActivity.this);
}
#Override
protected void onStop() {
super.onStop();
FlurryAgent.onEndSession(MainGameActivity.this);
}
#Override
public void onDestroy() {
super.onDestroy();
mFlurryAdInterstitial.destroy();
}
So what can I do in this situation?
I know there are quite a few posts about this already and I have read pretty much all of them (or so it feels at least). Yet my service refuses to work, at all.
In short: I have a widget that should launch the speecrecognizer service when clicked on. The service should then listen to input and (for now) print it out to logcat.
The service starts correctly (the logs in oncreate and ondestroy are printed) but the actual voice recognition part doesn't work.
I have added the service in the android manifest and added the "android.permission.RECORD_AUDIO" permission.
Part of the issue is that
SpeechRecognizer.isRecognitionAvailable(this)
returns false.
Here's the important bit of code from the service:
#Override
public void onCreate() {
super.onCreate();
mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(this);
mSpeechRecognizer.setRecognitionListener(mListener);
if (SpeechRecognizer.isRecognitionAvailable(this))
Log.d(TAG, "we are go for speech recognition");
else
Log.d(TAG, "red light for speech recognition :c");
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "i'm being destroyed :c");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "we made it");
playTtsForMessage("We made it", true);
speechIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
speechIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
speechIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, this.getPackageName());
mSpeechRecognizer.startListening(speechIntent);
Log.d(TAG, "started listening");
return super.onStartCommand(intent, flags, startId);
}
private void broadcastStopIntent() {
Intent intent = new Intent(Intents.ACTION_VOICE_COMMANDS_STOP);
AddApplication.getInstance().sendBroadcast(intent, null);
}
All the log outputs get printed, apart from the ones i've placed inside the listener.
If interested, here's the listener:
private RecognitionListener mListener = new RecognitionListener() {
#Override
public void onReadyForSpeech(Bundle params) {
// TODO Auto-generated method stub
}
#Override
public void onBeginningOfSpeech() {
// TODO Auto-generated method stub
Log.d(TAG, "speech started");
}
#Override
public void onRmsChanged(float rmsdB) {
// TODO Auto-generated method stub
}
#Override
public void onBufferReceived(byte[] buffer) {
// TODO Auto-generated method stub
}
#Override
public void onEndOfSpeech() {
// TODO Auto-generated method stub
Log.d(TAG, "speech ended");
broadcastStopIntent();
}
#Override
public void onError(int error) {
// TODO Auto-generated method stub
}
#Override
public void onResults(Bundle results) {
// TODO Auto-generated method stub
ArrayList<String> spoken = results
.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
String msg = "";
for (String s : spoken) {
msg += s + " ";
}
Log.d(TAG, "what i understood from that was: " + msg);
WidgetVoiceCommandProviderIntentService.this.stopSelf();
}
#Override
public void onPartialResults(Bundle partialResults) {
// TODO Auto-generated method stub
}
#Override
public void onEvent(int eventType, Bundle params) {
// TODO Auto-generated method stub
}
};
I tried this guy's workaround: Android Speech Recognition as a service on Android 4.1 & 4.2
Which yielded no results. Any suggestions?
I was wondering, how can I keep the device listening for voice commands with voice recognition while the device is asleep? The idea I have is that I would like the device to respond to my voice, even if I have the screen locked or the screen has timed out.
Is this possible? I have tried using this as a service and an interface and it stops listening once the screen locks. Can I receive any help with this? This is my class.
public class VoiceEngineService extends Activity {
private boolean isSpeakingDone = false; // default setting
private SpeechRecognizer sr = SpeechRecognizer.createSpeechRecognizer(this);
private AudioManager mAudioManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.wait_for_speech);
// mute beep sound
mAudioManager.setStreamSolo(AudioManager.STREAM_VOICE_CALL, true);
sr.setRecognitionListener(new listener());
Intent i = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
i.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); // LANGUAGE_MODEL_WEB_SEARCH
i.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, getApplication()
.getClass().getName());
i.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 6);
i.putExtra(RecognizerIntent.EXTRA_PROMPT, "");
i.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 5500);
sr.startListening(i);
}
class listener implements RecognitionListener {
#Override
public void onReadyForSpeech(Bundle params) {
// TODO Auto-generated method stub
}
#Override
public void onBeginningOfSpeech() {
// TODO Auto-generated method stub
}
#Override
public void onRmsChanged(float rmsdB) {
// TODO Auto-generated method stub
}
#Override
public void onBufferReceived(byte[] buffer) {
// TODO Auto-generated method stub
}
#Override
public void onEndOfSpeech() {
// TODO Auto-generated method stub
}
#Override
public void onError(int error) {
// TODO Auto-generated method stub
if (SharedPref.getVoiceController() == false) {
sr.cancel();
Intent i = new Intent();
sr.startListening(i);
} else {
sr.stopListening();
sr.destroy();
finish();
}
}
#Override
public void onResults(Bundle results) {
// TODO Auto-generated method stub
isSpeakingDone = true;
ArrayList<String> mDataList = results
.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
Intent i = new Intent();
i.putStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS, mDataList);
setResult(RESULT_OK, i);
finish();
}
#Override
public void onPartialResults(Bundle partialResults) {
// TODO Auto-generated method stub
}
#Override
public void onEvent(int eventType, Bundle params) {
// TODO Auto-generated method stub
}
} // end listener class
#Override
protected void onPause() {
if ((isSpeakingDone == false)) {
finish();
}
super.onPause();
}
#Override
protected void onStop() {
// when speaking is true finish() has already been called
if (isSpeakingDone == false) {
finish();
}
super.onStop();
}
#Override
protected void onDestroy() {
sr.stopListening();
sr.destroy();
super.onDestroy();
}
}
You have to implement your voice listener in a service. Create a class that extends 'Service' and make up some logic to take care of recording.
If you tried already the service, then it might be that you tried to redirect commands to an activity which most likely has been stopped by Android OS. Generally when talking about doing stuff when phone is in lock mode, you only can hope to accomplish tasks in one or more services coupled togethe.
When you are in Activity, of course wen the activity goes out of scope it will be shut down by Android OS. but services can still run in background unless shut dow mm explicitly by your own code or in rare cases that Android will recognize that it needs memory and processor power for other tasks.
I'm using the TextToSpeech API in my code and it doesn't work when I try to call .speak() function from OnStart(), however it works when I call it from a button onClickListener(). Any idea why? Thank you.
public class TtsDemoActivity extends Activity {
private TextToSpeech mTts;
private OnClickListener buttonListener = new View.OnClickListener() {
#Override
public void onClick(View arg0) {
PlaySound();
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.ttsdemo);
// Initialize Text To speech
mTts = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
#Override
public void onInit(int arg0) {
// TODO Auto-generated method stub
}
});
Button myButton = (Button)findViewById(R.id.buttontts1);
myButton.setOnClickListener(buttonListener);
}
#Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
PlaySound();
}
protected void PlaySound()
{
String word = "Hello world";
mTts.speak(word, TextToSpeech.QUEUE_FLUSH, null);
}
You must wait until the TTS subsystem signals that it is ready: if it isn't ready when onStart is called, it will fail. If you are trying to speak as soon as it is ready call PlaySound from inside the OnInitListener:
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.ttsdemo);
// Initialize Text To speech
mTts = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
#Override
public void onInit(int arg0) {
if(arg0 == TextToSpeech.SUCCESS) PlaySound();
}
});
Button myButton = (Button)findViewById(R.id.buttontts1);
myButton.setOnClickListener(buttonListener);
}
Maybe I am blind, but in your onStart method, you aren't ever calling
PlaySound()
Like you are in
#Override
public void onClick(View arg0) {
PlaySound();
}
I'm implementing an Interactive Voice Response application on Android. I would like to know how to determine when the tts.speak() function has done talking so I can call my speech recognizer function.
public class TTSActivity extends Activity implements OnInitListener, OnUtteranceCompletedListener, ... {
private TextToSpeech mTts;
...........
private void speak(String text) {
if(text != null) {
HashMap<String, String> myHashAlarm = new HashMap<String, String>();
myHashAlarm.put(TextToSpeech.Engine.KEY_PARAM_STREAM, String.valueOf(AudioManager.STREAM_ALARM));
myHashAlarm.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "SOME MESSAGE");
mTts.speak(text, TextToSpeech.QUEUE_FLUSH, myHashAlarm);
}
}
// Fired after TTS initialization
public void onInit(int status) {
if(status == TextToSpeech.SUCCESS) {
mTts.setOnUtteranceCompletedListener(this);
}
}
// It's callback
public void onUtteranceCompleted(String utteranceId) {
Log.i(TAG, utteranceId); //utteranceId == "SOME MESSAGE"
}
...........
}
Read A good tutorial
The setOnUtteranceCompletedListener is deprecated since API level 15. Instead, use setOnUtteranceProgressListener.
I found a code snippet (here) that made it really easy for me to know when text to speech is finished:
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
myTTS.setOnUtteranceProgressListener(new UtteranceProgressListener() {
#Override
public void onDone(String utteranceId) {
// Log.d("MainActivity", "TTS finished");
}
#Override
public void onError(String utteranceId) {
}
#Override
public void onStart(String utteranceId) {
}
});
} else {
Log.e("MainActivity", "Initilization Failed!");
}
}
http://www.codota.com/android/scenarios/52fcbd34da0ae25e0f855408/android.speech.tts.TextToSpeech?tag=dragonfly
To know when TTS is finished you have to call the setOnUtteranceProgressListener which has 3 call back methods onStart,onDone and onError
then include a Utterance Id to the speak method
Code Snippet
textToSpeech=new TextToSpeech(this, new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status==TextToSpeech.SUCCESS){
int result=textToSpeech.setLanguage(Locale.ENGLISH);
if (result==TextToSpeech.LANG_MISSING_DATA||result==TextToSpeech.LANG_NOT_SUPPORTED){
Log.i("TextToSpeech","Language Not Supported");
}
textToSpeech.setOnUtteranceProgressListener(new UtteranceProgressListener() {
#Override
public void onStart(String utteranceId) {
Log.i("TextToSpeech","On Start");
}
#Override
public void onDone(String utteranceId) {
Log.i("TextToSpeech","On Done");
}
#Override
public void onError(String utteranceId) {
Log.i("TextToSpeech","On Error");
}
});
}else {
Log.i("TextToSpeech","Initialization Failed");
}
}
});
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
textToSpeech.speak(text,TextToSpeech.QUEUE_FLUSH,null,TextToSpeech.ACTION_TTS_QUEUE_PROCESSING_COMPLETED);
}
I noticed that there are people having problems in the use of TextToSpeech to ask that the solution to you
How to know when TTS is finished?
without use setOnUtteranceCompletedListener
public void isTTSSpeaking(){
final Handler h =new Handler();
Runnable r = new Runnable() {
public void run() {
if (!tts.isSpeaking()) {
onTTSSpeechFinished();
}
h.postDelayed(this, 1000);
}
};
h.postDelayed(r, 1000);
}
Try this following code which shows a toast after TTS completed. Replace toast with your own action.
public class MainActivity extends AppCompatActivity implements TextToSpeech.OnInitListener{
private boolean initialized;
private String queuedText;
private String TAG = "TTS";
private TextToSpeech tts;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tts = new TextToSpeech(this /* context */, this /* listener */);
tts.setOnUtteranceProgressListener(mProgressListener);
speak("hello world");
}
public void speak(String text) {
if (!initialized) {
queuedText = text;
return;
}
queuedText = null;
setTtsListener(); // no longer creates a new UtteranceProgressListener each time
HashMap<String, String> map = new HashMap<String, String>();
map.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "MessageId");
tts.speak(text, TextToSpeech.QUEUE_ADD, map);
}
private void setTtsListener() {
}
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
initialized = true;
tts.setLanguage(Locale.ENGLISH);
if (queuedText != null) {
speak(queuedText);
}
}
}
private abstract class runnable implements Runnable {
}
private UtteranceProgressListener mProgressListener = new UtteranceProgressListener() {
#Override
public void onStart(String utteranceId) {
} // Do nothing
#Override
public void onError(String utteranceId) {
} // Do nothing.
#Override
public void onDone(String utteranceId) {
new Thread()
{
public void run()
{
MainActivity.this.runOnUiThread(new runnable()
{
public void run()
{
Toast.makeText(getBaseContext(), "TTS Completed", Toast.LENGTH_SHORT).show();
}
});
}
}.start();
}
}; }
With this code I solved the problem. I wanted the start button to stay lit as long as someone was speaking. Maybe this will help someone.
public void _tts_speak_lenght() {
t2 = new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (TTS.isSpeaking()) {
isSpeaking = true;
}
else {
if (!TTS.isSpeaking()) {
t2.cancel();
isSpeaking = false;
imgBtn_startReader.setImageResource(R.drawable.ic_start_off);
}
}
}
});
}
};
_timer.scheduleAtFixedRate(t2, (int)(0), (int)(100));
}
use a SpeakableListener when do text to speak.
private volatile boolean finished;
private SpeakableListener listener = new SpeakableListener() {
#Override
public void markerReached(SpeakableEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void speakableCancelled(SpeakableEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void speakableEnded(SpeakableEvent arg0) {
TestSpeaker.this.finished = true;
}
#Override
public void speakablePaused(SpeakableEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void speakableResumed(SpeakableEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void speakableStarted(SpeakableEvent arg0) {
TestSpeaker.this.finished = false;
}
#Override
public void topOfQueue(SpeakableEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void wordStarted(SpeakableEvent arg0) {
// TODO Auto-generated method stub
}
};
/** Speak the following string. */
public void sayIt(String str) {
System.out.print(" " + str + " ");
/* The the synthesizer to speak. */
synthesizer.speakPlainText(str, listener);