Обратитесь к объекту TTS внутри внутреннего метода

#android #text-to-speech

#Android #преобразование текста в речь

Вопрос:

Хорошо… Я пытаюсь создать приложение, используя движок TTS.

Я уже могу это сделать, работать, без проблем. Однако мне нужно, чтобы мои кнопки были динамическими, они будут поступать из базы данных.

До сих пор вы, ребята, мне очень помогли, так как теперь я могу это сделать благодаря советам, которые я получил от вас, ребята.

Хорошо.. теперь я снова застрял.

К каждой новой кнопке, которую я создаю, я прикрепляю OnClickListener, чтобы он мог запускать TTS и что-то говорить.

Однако это внутренний метод, поэтому, когда я пытаюсь запустить приведенный ниже код, он выдает исключение NullPointerException, когда он пытается «говорить» с помощью TTS. Я знаю, что объект TTS находится вне контекста, итак, как я могу это решить?

Ниже приведен код. Это немного великовато, так как я хотел включить все:

ПОЖАЛУЙСТА, ПЕРЕЙДИТЕ К комментарию «ВОТ МОЯ ПРОБЛЕМА !!!», чтобы вы, ребята, могли точно увидеть, в чем моя проблема. Я знаю, где это, но я не знаю, как это решить = (

Любая помощь приветствуется! =)

 public class LivoxTesteActivity extends Activity implements OnInitListener{
    /** Called when the activity is first created. */
    private int MY_DATA_CHECK_CODE = 0;
    public TextToSpeech tts;


    @Override
    public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE); 
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
            WindowManager.LayoutParams.FLAG_FULLSCREEN);  
    setContentView(R.layout.main);


    LinearLayout lgeral = new LinearLayout (this);
    lgeral.setOrientation(LinearLayout.VERTICAL);
    lgeral.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT, 1f));

    String array[][] = {{"Comer","eat", "Eu quero comer", "1"},
            {"Abraço","hug", "Eu quero um abraço", "2"},
            {"Assustado","afraid", "Eu estou com medo", "3"},
            {"Beber","drink", "Eu quero beber", "4"}};
    int x = array.length;

    int qtdeLinhas = 2;
    for (int j = 0; j < qtdeLinhas; j  ) {        

        LinearLayout l1 = new LinearLayout (this);
        l1.setOrientation(LinearLayout.HORIZONTAL);
        l1.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT, 1f));

        FrameLayout fl;
        for (int i = 0; i < array.length; i  ) {

            fl = (FrameLayout)LayoutInflater.from(getBaseContext()).inflate(R.layout.framelayoutstyle, l1, false);

            TextView textoEscrito;
            textoEscrito = (TextView)LayoutInflater.from(getBaseContext()).inflate(R.layout.textviewstyle, fl, false);

            textoEscrito.setText(array[i][0]);

            final String texto = textoEscrito.getText().toString();        
            final String textoFalar = array[i][2];

            ImageButton btn;
            btn = (ImageButton)LayoutInflater.from(getBaseContext()).inflate(R.layout.imagebuttonstyle, fl, false);

            btn.setImageResource(this.getResources().getIdentifier("drawable/"   array[i][1], null, this.getPackageName()));


            btn.setOnClickListener(new Button.OnClickListener(){
                public void onClick (View v){


                    Toast.makeText(getBaseContext(), texto, Toast.LENGTH_SHORT).show();
                    //*******************************
                    //HERE IS MY PROBLEM!!!
                    //*******************************
                    tts.speak(txtFl, TextToSpeech.QUEUE_ADD, null);
                    //*******************************
                    //WHEN I TRY TO RUN THE ABOVE IT GIVES A NULLPOINTEREXCEPTION!!!
                    //*******************************



                }

            });


            fl.addView(btn);
            fl.addView(textoEscrito);

            l1.addView(fl);
        }

        lgeral.addView(l1);
    }

    setContentView(lgeral);        

}


protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == MY_DATA_CHECK_CODE) {
        if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
            // success, create the TTS instance
            tts = new TextToSpeech(this, this);
        }
        else {
            // missing data, install it
            Intent installIntent = new Intent();
            installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
            startActivity(installIntent);
        }
    }

}
@Override
public void onInit(int status) {       
    if (status == TextToSpeech.SUCCESS) {
    }
    else if (status == TextToSpeech.ERROR) {
    }
}


@Override
public void onDestroy() {
if (tts != null) {
tts.stop();
tts.shutdown();
}
super.onDestroy();
} 

}
 

Кстати … метод Toast.makeText(getBaseContext(), texto, Toast .LENGTH_SHORT).show(); работает нормально. Я полагаю, это потому, что Toast является статическим классом.

Итак, может быть, решение состоит в том, чтобы создать статический класс с методом to speak? Идеи? Как я могу это сделать?

Ответ №1:

onActivityResult Перед синтезированием речи убедитесь, что вызываются оба onInit и. Если вы получаете исключение NullPointerException, наиболее вероятной причиной является то, что к моменту нажатия кнопки tts объект еще не был создан.

Правильный подход заключается в настройке очереди фраз для разговора (например, an ArrayList<String> ), и как только TTS будет инициализирован (т. Е. В УСПЕШНОЙ ветке OnInit), начните говорить.

РЕДАКТИРОВАТЬ: теперь, когда я смотрю на ваш код… Где вы вызываете какие-либо действия, которые могут вызвать onActivityResult вызов? В руководстве по разработке предлагается выполнить следующее как часть процесса инициализации:

 Intent checkIntent = new Intent();
checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
startActivityForResult(checkIntent, MY_DATA_CHECK_CODE);
 

В вставленном фрагменте нет ничего на этот счет.

Комментарии:

1. Привет, Сева Алексеев! Спасибо за ваш ответ…. Хорошо.. это именно моя проблема! Как я могу заставить onActivityResult и OnInit вызываться раньше? У меня есть свой метод onCreate, в котором я создаю свои кнопки и добавляю к каждой из них OnClickListener с правильным словом, которое нужно произнести. Однако методы onActivityResult и OnInit находятся ЗА ПРЕДЕЛАМИ onCreate . Исключение NullPointerException возникает только тогда, когда я пытаюсь использовать tts. Как вы можете видеть в исходном коде, я вызываю тост, и он работает нормально. Может быть, потому, что это статический метод. Итак … как я могу сделать то же самое с tts?

Ответ №2:

Объявите tts как final, и он станет доступным. В качестве альтернативы вы можете сделать его переменной экземпляра класса. Судя по тому, как вы его используете, последнее, вероятно, является правильным ответом.

Комментарии:

1. Привет, @Sajid. Спасибо за ваш ответ. Хорошо.. Я действительно не могу объявить его как окончательный, компилятор этого не допускает. Что касается второго решения, которое вы предложили… как я могу это сделать? Извините… Я новичок, и это действительно ново для меня! =)

2. О, неважно. Я совершенно неправильно понял проблему. Это не проблема видимости. Вы никогда не инициализируете tts до onActivityResult. Вы должны либо создать объект tts в onCreate(), либо, если вы не можете (что может быть в данном случае), затем проверить, что tts равен нулю, и показать тост или что-то в этом роде, пока данные tts не будут инициализированы. Не видя всех взаимодействий, это лучшее, что я могу сказать.