I've developed a module for my app using RecyclerView in Tabbed-Fragments.
There are multiple dynamically loaded images shown in each fragment using RecyclerView. When user taps on any image, system speaks out some information about it using TextToSpeech.
I'm using an adapter class for RecyclerView that successfully loads images to views. Here's the code:
import android.speech.tts.TextToSpeech;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{
private ArrayList<CreateList> galleryList;
private Context context;
TextToSpeech tts;
public MyAdapter(Context context, ArrayList<CreateList> galleryList) {
this.galleryList = galleryList;
this.context = context;
}
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
.....
}
@Override
public void onBindViewHolder(MyAdapter.ViewHolder viewHolder, int i) {
.....
.....
viewHolder.img.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
.....
.....
tts=new TextToSpeech(context, new TextToSpeech.OnInitListener() {
@Override
public void onInit(int status) {
// TODO Auto-generated method stub
if(status !=TextToSpeech.ERROR){
tts.setLanguage(Locale.UK);
}
}
});
tts.setPitch(pitch);
tts.setSpeechRate(speechRate);
tts.speak(StringToSpeak, TextToSpeech.QUEUE_FLUSH, null);
}
@Override
public int getItemCount() {
return galleryList.size();
}
.....
.....
}
As you can see I've added a OnClickListener
on viewHolder, which initializes TTS object with onInitListener
and speaks information. But whenever i click on any image/view/item in Fragment it doesn't speaks out anything. There's no crash, no exception in LogCat, all i get is following message with other messages:
I/TextToSpeech: Sucessfully bound to com.google.android.tts
W/TextToSpeech: speak failed: not bound to TTS engine
I tried debugging the application and found out that while initializing TTS object it returns engine=Null
at this line:
tts=new TextToSpeech(context, new TextToSpeech.OnInitListener() {
....});
In other classes that extend Activity, code and TTS is working prefectly but in my Adapter/Non-Activity class it doesn't initiate TTS because it is unable to bind to TTS engine. I've tried to implement interface implements TextToSpeech.OnInitListener
in my adapter class with following function:
@Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
tts.setLanguage(Locale.UK);
}
}
But no results :( I've also tried to create an abstract class extending Activity, that implements TTS in its OnCreate()
and includes a custom function SpeakMessage()
which i tried calling in my Adapter Class but failed. It's been several hours i'm trying to figure out the problem and it's solution, deeply studied every TTS related question on StackOverFlow and other sites but couldn't find any solution for my problem. Please help me with identifying the problem and its proper solution. Thanks alot in advance. One more thing, in same action listener for Views, Playing recorded audio message using MediaPlayer works perfect. The only problem is with speaking string messages using TTS.
I have implemented Text to speech successfully
Below is my Code
I have implemented two method one for <20 api and one is for >21api
@SuppressWarnings("deprecation")
private void ttsUnder20(String text) {
HashMap<String, String> map = new HashMap<>();
map.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "MessageId");
tts.speak(text, TextToSpeech.QUEUE_FLUSH, map);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void ttsGreater21(String text) {
String utteranceId = this.hashCode() + "";
Bundle params = new Bundle();
params.putString(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "");
tts.speak(text, TextToSpeech.QUEUE_FLUSH, params, utteranceId);
}
Here is method which calling this methods.
private void playNextChunk(String text) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ttsGreater21(text);
} else {
ttsUnder20(text);
}}
Call playChunk method from onInit method
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
playNextChunk(String text)
}
}
One more suggestion text to speech is able to speak 4000 character at a time if you have string with >4000 character you need to play it in chunks. for that you need to implement this listener tts.setOnUtteranceProgressListener