Search code examples
androidandroid-recyclerviewnullpointerexceptiongoogle-text-to-speech

TextToSpeech throws NullPointerException


I'm writing recycler view which contains editable list of words. ViewHolder for RecyclerView contains 2 objects: editText and sound image icon. My idea is that when I push sound icon, I expect to hear the pronunciation of the word, which I'm realizing with the help of SDK's TextToSpeech class. To reduce amount of code I've created the follow class;

public class SpeechController {

private String pronounce;
private Context context;

public TextToSpeech tts = new TextToSpeech(context,
        new TextToSpeech.OnInitListener() {
            @Override
            public void onInit(int status) {
                if (status != TextToSpeech.ERROR) {
                    tts.setLanguage(Locale.UK);
                }
            }
        });

public SpeechController(Context context, String pronounce) {
    this.context = context;
    this.pronounce = pronounce;
}

public void speakOut() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        tts.speak(pronounce, TextToSpeech.QUEUE_FLUSH, null, null);
        tts.stop();
        tts.shutdown();
    } else {
        tts.speak(pronounce, TextToSpeech.QUEUE_FLUSH, null);
        tts.stop();
        tts.shutdown();
    }
}
}

Then I create instance of this class in my adapter's onBindViewHolder method for recyclerView like that:

@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
    if (mGroupsVc != null) {
        GroupVc current = mGroupsVc.get(position);
        holder.nameView.setText(current.getNameGroup());
        holder.imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SpeechController mSpeechController = new SpeechController(holder.nameView.getContext(),
                        holder.nameView.getText().toString());
                mSpeechController.speakOut();
            }
        });
    } else {
        // Covers the case of data not being ready yet.
        holder.nameView.setText("No Word");
    }
}

My application is get compiled but when I'm trying to click sound button NullPointerException appears and gives reference to these operators in both classes:

SpeechController mSpeechController = new SpeechController(holder.nameView.getContext(),
                        holder.nameView.getText().toString());


public TextToSpeech tts = new TextToSpeech(context,

I know the meaning of this Exception but I don't where I'm getting wrong with the initialization of object. I need your help to define it. Below I affix the complete error-logcat

03-14 17:48:52.168 21719-21719/com.hfad.singleton E/AndroidRuntime: FATAL EXCEPTION: main
                                                                java.lang.NullPointerException
                                                                    at android.speech.tts.TextToSpeech.<init>(TextToSpeech.java:606)
                                                                    at android.speech.tts.TextToSpeech.<init>(TextToSpeech.java:582)
                                                                    at android.speech.tts.TextToSpeech.<init>(TextToSpeech.java:567)
                                                                    at com.hfad.singleton.groupsActivityController.SpeechController.<init>(SpeechController.java:14)
                                                                    at com.hfad.singleton.adapter.GroupsVcAdapter$1.onClick(GroupsVcAdapter.java:52)
                                                                    at android.view.View.performClick(View.java:4421)
                                                                    at android.view.View$PerformClick.run(View.java:17903)
                                                                    at android.os.Handler.handleCallback(Handler.java:730)
                                                                    at android.os.Handler.dispatchMessage(Handler.java:92)
                                                                    at android.os.Looper.loop(Looper.java:213)
                                                                    at android.app.ActivityThread.main(ActivityThread.java:5225)
                                                                    at java.lang.reflect.Method.invokeNative(Native Method)
                                                                    at java.lang.reflect.Method.invoke(Method.java:525)
                                                                    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:741)
                                                                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
                                                                    at dalvik.system.NativeStart.main(Native Method)

Solution

  • After initialising the SpeechController object in the adapter:

    SpeechController mSpeechController = new SpeechController(holder.nameView.getContext(),
                        holder.nameView.getText().toString());
    mSpeechController.speakOut();
    

    You call its method speakout() which tries to access the variable tts:

    tts.speak()
    

    This object has not been initialised in the adapter's current scope, so throws an NPE.

    So what you could do is initialise the tts object in the constructor of the SpeechController object:

    private String pronounce;
    private Context context;
    public TextToSpeech tts;
    
    public SpeechController(Context context, String pronounce) {
    this.context = context;
    this.pronounce = pronounce;
    tts = new TextToSpeech(context,
        new TextToSpeech.OnInitListener() {
            @Override
            public void onInit(int status) {
                if (status != TextToSpeech.ERROR) {
                    tts.setLanguage(Locale.UK);
                }
            }
        });
    }
    

    This will fix the NPE crash as tts is no longer null in the current context.