TextToSpeech.setEngineByPackageName() triggers NullPointerException

∥☆過路亽.° 提交于 2019-12-11 02:48:53

问题


My activity's onInit() contains a call to TextToSpeech.setEngineByPackageName():

  tts = new TextToSpeech(this, this);
  tts.setEngineByPackageName("com.ivona.tts.voicebeta.eng.usa.kendra");

It works on an Android 2.2.2 device, but on an Android 2.3.4 device it produced a NullPointerException, with the following stack trace:

 E/TextToSpeech.java - setEngineByPackageName(3423): NullPointerException
 W/System.err(3423): java.lang.NullPointerException
 W/System.err(3423):    at android.os.Parcel.readException(Parcel.java:1328)
 W/System.err(3423):    at android.os.Parcel.readException(Parcel.java:1276)
 W/System.err(3423):    at android.speech.tts.ITts$Stub$Proxy.setEngineByPackageName(ITts.java:654)
 W/System.err(3423):    at android.speech.tts.TextToSpeech.setEngineByPackageName(TextToSpeech.java:1356)

Since I am providing a hard-coded string parameter, I know that the parameter isn't what's causing the NullPointerException.

I also know that setEngineByPackageName() is deprecated but that's only since API 14, so this couldn't be the reason.

Any idea what could be causing this NullPointerException?

EDIT: I wouldn't have been concerned with the "why" if this didn't result in an endless bombardment of:

I/TextToSpeech.java(3652): initTts() successfully bound to service

Followed by calls to onInit() (by the system, not by my code).

My hope is that if I underderstand why this is happening, I can stop the bombardment of onInit()s and recover gracefully from the error.


回答1:


Is the TTS engine you are referencing installed on the 2.3.4 device? If it is, it might be a platform bug.

EDIT: Don't remember what results I got when I did this, but calling setEngineByPackageName() when the package doesn't exists is not a good idea. Check if it is installed and don't try to use it if it's not. Something like:

boolean isPackageInstalled(String packageName) {
  PackageManager pm = context.getPackageManager();
  try {
    PackageInfo pi = pm.getPackageInfo(packageName, 0);

    return pi != null;
  } catch (NameNotFoundException e) {
    return false;
  }
}



回答2:


Attempting to investigate this myself, in case an expert on the subject isn't around:

The NullPointerException stack trace is printed by setEngineByPackageName() itself in the catch handler for this try clause:

try {
    result = mITts.setEngineByPackageName(enginePackageName);
    if (result == TextToSpeech.SUCCESS){
        mCachedParams[Engine.PARAM_POSITION_ENGINE + 1] = enginePackageName;
    }
} 

Which suggests that either of the following is null:

  1. mITts
  2. mCachedParams

mCachedParams is unlikely to be the null one because it is initialized in the constructor. So this leaves us with mITts:

If I examine TextToSpeech.initTts() I can easily spot 2 points in which mITts can remain null:

  1. onServiceConnected()
  2. onServiceDisconnected()

But why this is happening only on the 2.3.4 device? This is still a mystery.

Possible clue: The method TextToSpeech.initTts() ends with the following comment:

mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
// TODO handle case where the binding works (should always work) but
//      the plugin fails

Which may explain why I receive a barrage of onInit()s ("initTts() successfully bound to service"): Binding always works, but since the package is not installed, "the plugin fails".

The question now is how to stop this endless loop...



来源:https://stackoverflow.com/questions/9492800/texttospeech-setenginebypackagename-triggers-nullpointerexception

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!