“null object reference error” 当尝试使用 TTS 时。

huangapple go评论82阅读模式
英文:

"null object reference error" when trying to use TTS

问题

我正在尝试使用文本转语音功能但是遇到了以下错误

> 2020-07-26 22:58:51.876 15964-15964/ch.yourclick.kitt
> E/AndroidRuntime: FATAL EXCEPTION: main
>     Process: ch.yourclick.kitt, PID: 15964
>     java.lang.NullPointerException: 尝试调用虚拟方法 'int android.speech.tts.TextToSpeech.speak(java.lang.String, int, java.util.HashMap)' 但空对象引用
>         at ch.yourclick.kitt.MainActivity.speak(MainActivity.java:61)
>         at ch.yourclick.kitt.fragments.GeneralFragment$1.onClick(GeneralFragment.java:59)

**MainActivity.java**
```java
package ch.yourclick.kitt;

import android.os.Bundle;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.tabs.TabLayout;
import androidx.viewpager.widget.ViewPager;
import androidx.appcompat.app.AppCompatActivity;
import android.speech.tts.TextToSpeech;
import android.util.Log;
import android.view.View;
import java.util.Locale;
import ch.yourclick.kitt.ui.main.SectionsPagerAdapter;

public class MainActivity extends AppCompatActivity {
    public TextToSpeech tts;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());
        ViewPager viewPager = findViewById(R.id.view_pager);
        viewPager.setAdapter(sectionsPagerAdapter);
        TabLayout tabs = findViewById(R.id.tabs);
        tabs.setupWithViewPager(viewPager);
        FloatingActionButton fab = findViewById(R.id.fab);

        // 文本转语音
        tts = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
            @Override
            public void onInit(int status) {
                if (status == TextToSpeech.SUCCESS) { // <— 我从未进入这个 if 语句
                    int result = tts.setLanguage(Locale.getDefault());
                    // 不支持该语言
                    if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) {
                        Log.e("TTS", "不支持的语言");
                    }
                }
                else {
                    Log.e("TTS", "" + status); // 返回 -1
                    Log.e("TTS", "" + TextToSpeech.SUCCESS); // 返回 0
                }
            }
        });

        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "用自己的操作替换它", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
    }

    /**
     * 朗读
     */
    public void speak() {
        String text = "你好";
        tts.speak(text, TextToSpeech.QUEUE_ADD, null);
    }

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

}
英文:

I am trying to use Text-To-Speech but get the following error:

> 2020-07-26 22:58:51.876 15964-15964/ch.yourclick.kitt
> E/AndroidRuntime: FATAL EXCEPTION: main
> Process: ch.yourclick.kitt, PID: 15964
> java.lang.NullPointerException: Attempt to invoke virtual method 'int android.speech.tts.TextToSpeech.speak(java.lang.String, int,
> java.util.HashMap)' on a null object reference
> at ch.yourclick.kitt.MainActivity.speak(MainActivity.java:61)
> at ch.yourclick.kitt.fragments.GeneralFragment$1.onClick(GeneralFragment.java:59)

MainActivity.java

package ch.yourclick.kitt;

import android.os.Bundle;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.tabs.TabLayout;
import androidx.viewpager.widget.ViewPager;
import androidx.appcompat.app.AppCompatActivity;
import android.speech.tts.TextToSpeech;
import android.util.Log;
import android.view.View;
import java.util.Locale;
import ch.yourclick.kitt.ui.main.SectionsPagerAdapter;

public class MainActivity extends AppCompatActivity {
    public TextToSpeech tts;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());
        ViewPager viewPager = findViewById(R.id.view_pager);
        viewPager.setAdapter(sectionsPagerAdapter);
        TabLayout tabs = findViewById(R.id.tabs);
        tabs.setupWithViewPager(viewPager);
        FloatingActionButton fab = findViewById(R.id.fab);

        // Text to speech
        tts = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
            @Override
            public void onInit(int status) {
                if (status == TextToSpeech.SUCCESS) { // &lt;-- I never get into that if statement
                    int result = tts.setLanguage(Locale.getDefault());
                    // Language is not supported
                    if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) {
                        Log.e(&quot;TTS&quot;, &quot;Language not supported&quot;);
                    }
                }
                else {
                    Log.e(&quot;TTS&quot;, &quot;&quot; + status); // Returns -1
                    Log.e(&quot;TTS&quot;, &quot;&quot; + TextToSpeech.SUCCESS); // Returns 0
                }
            }
        });

        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, &quot;Replace with your own action&quot;, Snackbar.LENGTH_LONG)
                        .setAction(&quot;Action&quot;, null).show();
            }
        });
    }

    /**
     * Speak
     */
    public void speak() {
        String text = &quot;Hello&quot;;
        tts.speak(text, TextToSpeech.QUEUE_ADD, null);
    }

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

}

GeneralFragment.java

package ch.yourclick.kitt.fragments;

import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

import ch.yourclick.kitt.MainActivity;
import ch.yourclick.kitt.R;

/**
 * A simple {@link Fragment} subclass.
 * Use the {@link GeneralFragment#newInstance} factory method to
 * create an instance of this fragment.
 */
public class GeneralFragment extends Fragment {

    public GeneralFragment() {
        // Required empty public constructor
    }

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @return A new instance of fragment General.
     */
    // TODO: Rename and change types and number of parameters
    public static GeneralFragment newInstance() {
        GeneralFragment fragment = new GeneralFragment();
        Bundle args = new Bundle();
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_general, container, false);
        Button hello = view.findViewById(R.id.hello);
        
        hello.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                MainActivity mainActivity = new MainActivity();
                mainActivity.speak();
            }
        });
        return view;
    }


}

It seems like tts returns null but why?

答案1

得分: 2

考虑一下你的帖子中的以下两个代码片段:

// 在 MainActivity.java 的 onCreate(...) 中找到的代码
tts = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
    // 这里有一堆代码
});

// 在 GeneralFragment.java 的 OnClickListener 中找到的代码
MainActivity mainActivity = new MainActivity();
mainActivity.speak();

很可能会因为在调用 mainActivity.speak()tts 为 null 而收到 NullPointerException

虽然你的意图是好的,但之所以不能按计划工作的原因是,实际上你正在创建一个新的 MainActivity 实例,这个实例尚未经过适当的生命周期步骤,意味着 onCreate(...) 从未被调用,因此 tts 从未被分配...在该特定活动实例中。值得注意的是,你的片段正在其中运行的“真实”活动实例应该已经正确设置。

那么,使其工作的最快方法是什么呢?嗯,我建议获取当前活动,如果可能的话将其转换为 MainActivity,然后尝试在该实例上调用 speak()

hello.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        final Activity activity = getActivity();
        if (activity instanceof MainActivity) {
            ((MainActivity) activity).speak();
        }
    }
});
英文:

Consider the following two snippets from your post:

// Code found in onCreate(...) in MainActivity.java
tts = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
// A bunch of code here
}

and

// Code found in an OnClickListener in GeneralFragment.java
MainActivity mainActivity = new MainActivity();
mainActivity.speak();

You're probably getting a NullPointerException due to the fact that tts is null when you call through to mainActivity.speak().

While your intentions were good, the reason for this not working as planned is that you're actually creating a new instance of MainActivity that hasn't gone through the appropriate lifecycle steps, meaning that onCreate(...) was never called and thus tts was never assigned... in that specific activity instance. Worth mentioning is that the "real" activity instance your fragment is running in however should have it set-up correctly.

So, what's the fastest way to get it working? Well, I'd say get the current activity, cast it to MainActivity if possible and try to call speak() on that instance instead:

hello.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
final Activity activity = getActivity();
if (activity instanceof MainActivity) {
((MainActivity) activity).speak();
}
}
});

huangapple
  • 本文由 发表于 2020年7月27日 05:32:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/63105917.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定