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

Ну... Я пытаюсь создать приложение с помощью TTS Engine.

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

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

Ну... теперь я снова застрял.

К каждой новой кнопке, которую я создаю, я прикрепляю 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 является статическим классом.

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


person Carlos Pereira    schedule 30.10.2011    source источник


Ответы (2)


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

Правильный подход — настроить очередь фраз для произнесения (например, ArrayList<String>) и после инициализации TTS (т. е. в ветке УСПЕХ onInit) начать говорить.

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

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

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

person Seva Alekseyev    schedule 30.10.2011
comment
Привет @Сева Алексеев! Спасибо за ответ.... Ну... это как раз моя проблема! Как сделать так, чтобы onActivityResult и onInit вызывались раньше? У меня есть метод onCreate, в котором я создаю свои кнопки и добавляю onClickListener к каждой из них с правильным словом для произнесения. Однако методы onActivityResult и onInit находятся ВНЕ onCreate. NullPointerException происходит как раз тогда, когда я пытаюсь использовать tts. Как вы можете видеть в исходнике, я вызываю Toast, и он отлично работает. Может быть, потому что это статический метод. Итак... как я могу сделать то же самое с tts? - person Carlos Pereira; 31.10.2011

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

person Sajid    schedule 30.10.2011
comment
Привет @Саджид. Спасибо за ваш ответ. Ну... я действительно не могу объявить его окончательным, компилятор не позволяет. Что касается второго решения, которое вы предложили... как я могу это сделать? Извините... Я новичок, и это действительно ново для меня! знак равно - person Carlos Pereira; 30.10.2011
comment
О, неважно. Я совершенно неправильно понял проблему. Это не проблема видимости. Вы никогда не инициализируете tts до onActivityResult. Вы должны либо создать объект tts в onCreate(), либо, если вы не можете (что может быть в данном случае), тогда проверьте, является ли tts нулевым, и покажите Toast или что-то еще, пока данные tts не будут инициализированы. Не видя всех взаимодействий, это лучшее, что я могу сказать. - person Sajid; 30.10.2011