我在应用程序中遇到一个非常奇怪的错误。
我已经添加了TTS,我正在使用构建版本。用户可以从AsyncTask
中onResume()
开始填写的微调器中选择语言。
AsyncTask
看起来像这样:
private class AsyncTTSDownload extends AsyncTask<Void, Integer, String> {
@Override
protected String doInBackground(Void... params) {
try {
languagesTTS = tts.testLang();
} catch (Exception ex) {
if (D)
Log.e(TAG, ex.toString());
}
return null;
}
@Override
protected void onPostExecute(String result) {
ttsUpdate.dismiss();
TTSSpinnerAdapter adapterTTS = new TTSSpinnerAdapter(
MyTTS.this, android.R.layout.simple_spinner_item,
languagesTTS);
int savedLangTTS = ttsLang.getInt("savedTTS", -1);
langTTS.setAdapter(adapterTTS);
if (savedLangTTS == -1)
{
try {
int langObject = languagesTTS.indexOf(tts.getLanguage());
langTTS.setSelection(langObject);
} catch (IndexOutOfBoundsException ie) {
langTTS.setSelection(0);
}
} else {
langTTS.setSelection(savedLangTTS);
}
Locale langChoosen = (Locale) langTTS.getItemAtPosition(langTTS
.getSelectedItemPosition());
tts.setTTSLanguage(langChoosen);
}
@Override
protected void onPreExecute() {
ttsUpdate = ProgressDialog.show(MyTTS.this, "Wait",
"Loading TTS...");
ttsUpdate.setCancelable(false);
}
}
事实上,我不时会支持不同数量的语言。 这是在同一台设备上运行。我只是用TTS打开和关闭Activity。此错误导致IndexOutOfBoundsException
。这是我获取TTS语言的方式:
public List<Locale> testLang() {
Locale[] AvalLoc = Locale.getAvailableLocales();
List<Locale> listaOK = new ArrayList<Locale>();
String tester = "";
for (Locale l : AvalLoc) {
if(tester.contains(l.getLanguage()))
{
continue;
}
int buf = tts.isLanguageAvailable(l);
if (buf == TextToSpeech.LANG_MISSING_DATA
|| buf == TextToSpeech.LANG_NOT_SUPPORTED) {
//TODO maybe
} else {
listaOK.add(l);
tester += l.getLanguage() + ";";
}
}
tts.setLanguage(Locale.ENGLISH);
return listaOK;
}
目前我只发现一个小黑客没有显示此错误,只需保存共享首选项语言数量并将其与收到的数据进行比较,但它根本不能正常工作。每次我得到不同的号码。
对于我来说,似乎有些东西没有完成或在我返回后再次启动这个相同的活动时开始,因为这是tts.isAvaliableLanguage(l)
谁决定是否支持语言,并且不时语言不受支持,重新加载后就是。
修改
由于我的问题出现了新的评论,我需要添加一个关于TTS引擎本身的重要事项。
testLang()
是我的班级TTSClass
内的一种方法,即实施TextToSpeech.OnInitListener
。 tts对象是在MyTTS
活动的onCreate中创建的,此构造函数在TTSClass
中看起来像这样:
public TTSClass(Context context, Locale language) {
contextTTS = context;
languageTTS = language;
tts = new TextToSpeech(contextTTS, this);
}
并致电活动:
tts = new TTSClass(getApplicationContext(), Locale.ENGLISH);
由于TTSClass
实现了TextToSpeech.OnInitListener
,因此还有onInit()
方法,如下所示:
@Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
int result = 0;
result = tts.setLanguage(languageTTS);
if (result == TextToSpeech.LANG_MISSING_DATA
|| result == TextToSpeech.LANG_NOT_SUPPORTED) {
if(D) Log.e(TAG, "This Language is not supported");
}
if(D) Log.d(TAG,"Initialized");
} else {
if(D) Log.e(TAG, "Initilization Failed!");
}
}
所以,这就是我认为连接到这个课程和问题的一切。如果遗漏了任何东西,现在就告诉我。
EDIT2:
鞋鼠评论的建议我已经进行了更多的测试,结果只是惊人的,或非同寻常的,我认为这是更好的词。
所以我所做的就是在代码中的不同位置添加3 Log
,告知我不同阶段的列表大小。
首先添加到onInit()
in status == TextToSpeech.SUCCESS
。这只是testLang().size()
的简单调用。结果是5种语言 - 这是正确的数字,无论是否存在异常,它总是这样。
第二个被添加到那里:
protected String doInBackground(Void... params) {
try {
Log.w(TAG,"before: "+tts.testLang().size());
languagesTTS = tts.testLang();
}
这个开始表现得非常奇怪。它有时甚至经常显示低于5的数字。但这并不是最奇怪的事情。
第三个是在onPostExecute
开始检查语言TTS的大小。不管你信不信,这个数字通常与第二个日志完全不同。但是,它永远不会变小。它可以相等或更大。
有谁知道,会发生什么?
答案 0 :(得分:0)
我找到了解决方案。结果确实是初始化问题。
我不确定文档是否说了什么,但似乎 TTS引擎初始化是异步完成的,所以它可以随时完成。
我的解决方案是更改doInBackground()
方法,如下所示:
@Override
protected String doInBackground(Void... params) {
try {
while(!TTSClass.isInit){}
languagesTTS = tts.testLang();
} catch (Exception ex) {
if (D)
Log.e(TAG, ex.toString());
}
return null;
}
并且在onInit()
方法中我添加了isInit public static boolean variable:
@Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
int result = 0;
result = tts.setLanguage(languageTTS);
if (result == TextToSpeech.LANG_MISSING_DATA
|| result == TextToSpeech.LANG_NOT_SUPPORTED) {
if(D) Log.e(TAG, "This Language is not supported");
}
if(D) Log.d(TAG,"initialized");
isInit = true;
} else {
if(D) Log.e(TAG, "Initilization Failed!");
}
}
希望有人会觉得它有用。