TextToSpeech only works when button is pressed, not when called separately - java

I tried to do something extremely simple or I thought it was.
In my BluetoothChat, I set
public static boolean potato = false;
In the onCreateBundle of my MainActivity, I have
talker = new TextToSpeech(getApplicationContext(),new TextToSpeech.OnInitListener()
{
#Override
public void onInit(int status)
{
if(status != TextToSpeech.ERROR)
{
talker.setLanguage(Locale.US);
}
}
});
if(BluetoothChat.potato == false)
{
speakOut();
}
When speakOut(); is called by a button or separately by itself it works.
public void speakOut()
{
String original ="You will have a seizure in thirty seconds.";
talker.speak(original,TextToSpeech.QUEUE_FLUSH,null);
}
However, this does not work. Can someone explain why?

Thanks to the help from Payeli. Here is the solution! Place the if statement within the onInit.
talker = new TextToSpeech(getApplicationContext(),new TextToSpeech.OnInitListener()
{
#Override
public void onInit(int status)
{
if(status != TextToSpeech.ERROR)
{
talker.setLanguage(Locale.US);
}
if(BluetoothChat.potato == false)
{
speakOut();
}
}
});

Related

Single Value Listener happening more than once

I have a simple multiplayer game for my app, and the game play is super simple. Each player has to press 'ready' and then the game starts.
Once both players are ready, gameStarted is set to true and the gameplay (which is not controlled by the players at all) is supposed to happen. This works, but the problem is it happens more than once on a loop. This is the value event listener I have in place.
games.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull final DataSnapshot dataSnapshot) {
HomePage.getCurrentGameID(new HomePage.CallbackID() {
#Override
public void onSuccess(String currentGameID) {
if (dataSnapshot.child(currentGameID).child("player1").child("ready").getValue().equals(true)
&& dataSnapshot.child(currentGameID).child("player2").child("ready").getValue().equals(true)) {
counter.run();
}
if (dataSnapshot.child(currentGameID).child("gameStarted").getValue().equals(true) &&
dataSnapshot.child(currentGameID).child("horT").getValue(Integer.class).equals(1)) {
headsOrTails.setText("Heads");
Log.i("FlipCoin", ";;happened");
flipHeads();
getResults();
endGame();
} else if (dataSnapshot.child(currentGameID).child("gameStarted").getValue().equals(true) &&
dataSnapshot.child(currentGameID).child("horT").getValue(Integer.class).equals(2)) {
headsOrTails.setText("Tails");
Log.i("FlipCoin", ";;happened");
flipTails();
getResults();
endGame();
}
Here is my getResults() method. I am putting it here to show that I have another value event listener being called from my addListenerForSingleValueEvent that I have shown above
private void getResults() {
games.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull final DataSnapshot dataSnapshot) {
HomePage.getCurrentGameID(new HomePage.CallbackID() {
#Override
public void onSuccess(final String currentGameID) {
final String horT1 = dataSnapshot.child(currentGameID).child("player1").child("horT").getValue().toString();
final String horT2 = dataSnapshot.child(currentGameID).child("player2").child("horT").getValue().toString();
final double wager = Double.parseDouble(dataSnapshot.child(currentGameID).child("wager").getValue().toString());
HomePage.getUserPosition(new HomePage.CallbackPosition() {
#Override
public void onSuccess(int position) {
if(position == 1) {
if(horT1.equals("Heads") && dataSnapshot.child(currentGameID).child("horT").getValue(Integer.class).equals(1)
|| horT1.equals("Tails") && dataSnapshot.child(currentGameID).child("horT").getValue(Integer.class).equals(2)) {
getWinner(FirebaseAuth.getInstance().getUid(), wager);
} else {
getLoser(FirebaseAuth.getInstance().getUid(), wager);
}
}
if(position == 2) {
if(horT2.equals("Heads") && dataSnapshot.child(currentGameID).child("horT").getValue(Integer.class).equals(1)
|| horT2.equals("Tails") && dataSnapshot.child(currentGameID).child("horT").getValue(Integer.class).equals(2)) {
getWinner(FirebaseAuth.getInstance().getUid(), wager);
} else {
getLoser(FirebaseAuth.getInstance().getUid(), wager);
}
}
if(dataSnapshot.child(currentGameID).child("gameFinished").getValue().equals(true)) {
//games.child(currentGameID).removeValue();
}
endGame();
}
});
}
});
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
});
I thought that setting it as a Single value event listener would make it only happen once, but I have a log in there that when I run the game, is called on a loop.
How can I make this event just happen one time?

button click not responding

This is the demo code and when I add onClickListener in fill function it is not working and if i set any other property like background color it works fine.
private void fillHolder(FriendsHolder holder, final Friend friend) {
if (friend == null)
return;
Iterator<Button> iViews = holder.interests.iterator();
Iterator<String> iInterests = friend.getInterests().iterator();
while (iViews.hasNext() && iInterests.hasNext()) {
iViews.next().setText(iInterests.next());
}
Iterator<Button> iViewss = holder.interests.iterator();
while (iViewss.hasNext()) {
iViewss.next().setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getActivity(), friend.getNickname(), Toast.LENGTH_SHORT).show();
}
});
}
holder.infoPage.setBackgroundColor(getResources().getColor(friend.getBackground()));
holder.nickName.setText(friend.getNickname());
}
}
You're iterating through iViewss (with double S in the end) and you're setting the listener to iViews(with single S in the end).
It's not the same object.
iViews.next().setOnClickListener() will throw a NoSuchElementException because there is not a next element.
Change your code like that:
private void fillHolder(FriendsHolder holder, final Friend friend) {
if (friend == null)
return;
Iterator<Button> iViews = holder.interests.iterator();
Iterator<String> iInterests = friend.getInterests().iterator();
while (iViews.hasNext() && iInterests.hasNext()) {
iViews.next().setText(iInterests.next());
}
while (iViews.hasNext()) {
iViews.next().setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getActivity(), friend.getNickname(), Toast.LENGTH_SHORT).show();
}
});
}
holder.infoPage.setBackgroundColor(getResources().getColor(friend.getBackground()));
holder.nickName.setText(friend.getNickname());
}
EDIT:
You can also combine the two while-loops (as cricket_007 suggestion):
private void fillHolder(FriendsHolder holder, final Friend friend) {
if (friend == null)
return;
Iterator<Button> iViews = holder.interests.iterator();
Iterator<String> iInterests = friend.getInterests().iterator();
while (iViews.hasNext()) {
Button button = iViews.next();
if (iInterests.hasNext()) {
button.setText(iInterests.next());
}
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getActivity(), friend.getNickname(), Toast.LENGTH_SHORT).show();
}
});
}
holder.infoPage.setBackgroundColor(getResources().getColor(friend.getBackground()));
holder.nickName.setText(friend.getNickname());
}
Along with the comments from the other answer, I think this code is more appropriate - it looks like you can combine the while-loops.
private void fillHolder(FriendsHolder holder, final Friend friend) {
if (friend == null)
return;
Iterator<Button> iViews = holder.interests.iterator();
Iterator<String> iInterests = friend.getInterests().iterator();
while (iViews.hasNext()) {
Button nextButton = iViews.next();
if (iInterests.hasNext()) {
nextButton.setText(iInterests.next());
}
nextButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getActivity(), friend.getNickname(), Toast.LENGTH_SHORT).show();
}
});
}
holder.infoPage.setBackgroundColor(getResources().getColor(friend.getBackground()));
holder.nickName.setText(friend.getNickname());
}

Text to Speak for Android not working

I'm trying to implement Text to Speech onto my app. I've followed the following guide but my app keeps crashing after the splash screen.
link: http://www.androidhive.info/2012/01/android-text-to-speech-tutorial/
Main Activity Class I have this
String alertMessage = AppResources.ALERT_MSG;
SpeakDemo speak = new SpeakDemo(null, alertMessage);
speak.speakOut();
If I remove the speak.speakOut(); line the app works fine.
App Resources is another class with the following message box
public static String ALERT_MSG = "Welcome!";
The SpeakDemo Class is:
import java.util.Locale;
import android.content.Context;
import android.speech.tts.TextToSpeech;
import android.util.Log;
public class SpeakDemo implements TextToSpeech.OnInitListener{
private TextToSpeech tts;
private Context context;
private String message;
public SpeakDemo(Context context, String message){
this.context = context;
this.message = message;
}
#Override
public void onInit(int status) {
// TODO Auto-generated method stub
if (status == TextToSpeech.SUCCESS) {
int result = tts.setLanguage(Locale.US);
if (result == TextToSpeech.LANG_MISSING_DATA
|| result == TextToSpeech.LANG_NOT_SUPPORTED) {
Log.e("TTS", "This Language is not supported");
} else {
speakOut();
}
} else {
Log.e("TTS", "Initilization Failed!");
}
}
public void speakOut(){
tts.speak(message, TextToSpeech.QUEUE_FLUSH, null);
}
}
Any Ideas?
Thanks
You need to instantiate the TextToSpeech.
Change
public SpeakDemo(Context context, String message){
this.context = context;
this.message = message;
tts = new TextToSpeech(context, this);
}
//FOR TEXT TO SPEECH
#Override
public void onInit(int status) {
// TODO Auto-generated method stub
String msg=text.getText().toString();
if(status==TextToSpeech.SUCCESS)
{
tts.setLanguage(Locale.US);
tts.speak(msg,TextToSpeech.QUEUE_FLUSH,null);
}
else
Log.e("TTS","INITILIZATION FAILED");
}
public void onDestroy()
{
if (tts!=null)
{
tts.stop();
tts.shutdown();
}
super.onDestroy();
}
Xml:
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Speak"
android:onClick="TTS"/>
Mainactivity:
TextToSpeech textToSpeech;
textToSpeech=new TextToSpeech(TTSpeech.this, new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if(status==TextToSpeech.SUCCESS)
{
result=textToSpeech.setLanguage(Locale.ENGLISH);
}
else
{
Toast.makeText(TTSpeech.this, "speech not work", Toast.LENGTH_SHORT).show();
}
}
});
}
public void TTS(View view) {
switch (view.getId())
{
case R.id.button:
if(result== TextToSpeech.LANG_NOT_SUPPORTED || result==TextToSpeech.LANG_MISSING_DATA)
{
Toast.makeText(TTSpeech.this, "speech not nt work", Toast.LENGTH_SHORT).show();
}
else
{
text=ed.getText().toString();
textToSpeech.speak(text,TextToSpeech.QUEUE_FLUSH,null);
}
break;
}
if you get problem you can comment me.

onUtteranceCompleted won't allow PhoneCallListener

For some reason I can't call a method that contains PhoneCallListener from onutteranceCompleted. There are no error messages, it just seems to stop executing the script. I've added some Logs and it gets to the "here" log in setUpPhone with PhoneCallListener. Without PhoneCallListener it will get to the final log "phone set up". Here is example code of how I have it implemented.
#Override
public void onInit(int status)
{
if(status == TextToSpeech.SUCCESS)
{
tts.setOnUtteranceCompletedListener(this);
int result = tts.setLanguage(Locale.US);
if(result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED)
{
//Language not supported
}
else
{
speakOut();
}
}
}
private void speakOut()
{
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, "Text to Speech");
tts.speak("blah blah", TextToSpeech.QUEUE_FLUSH, myHashAlarm);
}
#Override
public void onDestroy()
{
if(tts != null)
{
tts.stop();
tts.shutdown();
}
super.onDestroy();
}
public void onUtteranceCompleted(String utteranceId)
{
Log.i("TEST", utteranceId);
setUpPhone();
Log.i("TEST", "phone set up"); //this is never reached
}
private void setUpPhone()
{
Log.i("TEST", "here");
PhoneCallListener phoneListener = new PhoneCallListener(); //If I remove this line, the log "phone set up" displays.
}
I don't know why PhoneCallListener stops execution, however I solved this by putting "phoneListener = new PhoneCallListener();" in the onCreate method.

How do I reduce this code duplication

I'm stuck on how I can reduce this code duplication, I'm using the TextToSpeech engine and using locales so the user can select their language.
language is a Spinner.
language.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View arg1,
int pos, long id) {
System.out.println(parent.getItemAtPosition(pos).toString());
if (parent.getItemAtPosition(pos).toString().equals("UK")) {
textToSpeech = new TextToSpeech(MainActivity.this,
new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status != TextToSpeech.ERROR) {
textToSpeech.setLanguage(Locale.UK);
}
}
});
} else if (parent.getItemAtPosition(pos).toString()
.equals("US")) {
textToSpeech = new TextToSpeech(MainActivity.this,
new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status != TextToSpeech.ERROR) {
textToSpeech.setLanguage(Locale.US);
}
}
});
} else if (parent.getItemAtPosition(pos).toString()
.equals("French")) {
textToSpeech = new TextToSpeech(MainActivity.this,
new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status != TextToSpeech.ERROR) {
textToSpeech.setLanguage(Locale.FRANCE);
}
}
});
} else if (parent.getItemAtPosition(pos).toString()
.equals("Italian")) {
textToSpeech = new TextToSpeech(MainActivity.this,
new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status != TextToSpeech.ERROR) {
textToSpeech
.setLanguage(Locale.ITALIAN);
}
}
});
} else if (parent.getItemAtPosition(pos).toString()
.equals("German")) {
textToSpeech = new TextToSpeech(MainActivity.this,
new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status != TextToSpeech.ERROR) {
textToSpeech
.setLanguage(Locale.GERMAN);
}
}
});
}
}
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
}
Extract creation of the TextToSpeech object into a separate function:
private TextToSpeech createTextToSpeech(final Locale loc) {
return new TextToSpeech(MainActivity.this,
new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status != TextToSpeech.ERROR) {
setLanguage(loc);
}
}
});
}
Note that the argument loc must be declared final so that it can be used inside the anonymous class.
Usage:
...
} else if (parent.getItemAtPosition(pos).toString().equals("French")) {
textToSpeech = createTextToSpeech(Locale.FRANCE);
} ...
You can create a Map.
private static final Map<String, Locale> LOCALES = new LinkedHashMap<String, Locale>() {{
put("US", Locale.US);
// many more
}
final Locale locale = LOCALES.get(parent.getItemAtPosition(pos).toString());
if(locale != null)
textToSpeech = new TextToSpeech(MainActivity.this,
new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status != TextToSpeech.ERROR)
textToSpeech.setLanguage(locale);
}
});
from top of my head,
make a Map<String,Locale> where key will be name of country and value will be locale
then just do
textToSpeech = new TextToSpeech(MainActivity.this,
new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status != TextToSpeech.ERROR) {
textToSpeech
.setLanguage(localeMap.get(parent.getItemAtPosition(pos).toString()));
}
}
});
public class TextToSpeechFactory {
private static final Map<String, Locale> LOCALES = new HashMap<String, Locale>() {{
put("US", Locale.US);
// many more
}
};
public static TextToSpeech createInstance(String language){
Locale l = LOCALES.get(language);
if(l == null)
throw new Exception("Languange "+ language + "is not valid!");
else{
return new TextToSpeech(MainActivity.this,
new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status != TextToSpeech.ERROR) {
textToSpeech.setLanguage(l);
}
}
});
}
}
}
Try to use a enum as
public enum LANGLIST {
UK("uk", Locale.UK),
UK("swe", Locale.SWEIDHS);
public String lang;
public Locale loc;
private LANGLIST(String lang, Locale loc) {
this.lang = lang;
this.loc = loc;
}
}
And then loop through all elements in the enum.

Categories