【问题标题】:Android TextToSpeech app null pointer exceptionAndroid TextToSpeech 应用程序空指针异常
【发布时间】:2012-03-29 16:41:59
【问题描述】:

我在 android 开发者控制台中收到一个空指针异常报告。我需要一些关于这里可能是什么问题的建议,堆栈跟踪是这样的

java.lang.NullPointerException
at com.myfreeapp.workers.Speaker.onInit(Speaker.java:57)
at android.speech.tts.TextToSpeech$1.onServiceConnected(TextToSpeech.java:451)
at android.app.ActivityThread$PackageInfo$ServiceDispatcher.doConnected(ActivityThread.java:1247)
at android.app.ActivityThread$PackageInfo$ServiceDispatcher$RunConnection.run(ActivityThread.java:1264)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4668)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:878)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:636)
at dalvik.system.NativeStart.main(Native Method)

我的应用中的相关代码sn-p是

public Speaker(final Context context, final Settings settings) 
{   
    this.settings = settings;
    params = new HashMap<String, String>();      
    params.put(TextToSpeech.Engine.KEY_PARAM_STREAM, String.valueOf(AudioManager.STREAM_ALARM));
    params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "myfreeapps");

    tts= new TextToSpeech(context, this);   
    Utils.log(TAG, "Created TextToSpeech..");
}

@Override
public void onInit(final int status) 
{
    Utils.log(TAG, "TTS onInit..");

//below is line 57 mentioned in the stack trace
    tts.setOnUtteranceCompletedListener(new SpeechFinishedListener());
    tts.setLanguage(Locale.getDefault());
    tts.setSpeechRate(settings.getSpeed());
    tts.setPitch(settings.getPitch());      
    ready = true;

}

请首先我需要清楚究竟什么是空.. 第 57 行指向变量 tts 的堆栈跟踪是否为 null..?

还是TextToSpeech方法setOnUtteranceCompletedListener内部发生空指针异常?

扬声器实例是在粘性服务的主线程上创建的,当我调试我的代码时,来自 TextToSpeech 的回调也返回到同一线程上。..

我不明白变量 tts 怎么可能是 null ???

顺便说一下,这个问题对我来说是无法重现的。我在开发者控制台上多次报告了这个堆栈跟踪。

请指教,

【问题讨论】:

  • 这是您在构造函数中初始化 TextToSpeech 对象而不是在 onInit 中初始化的原因吗?
  • 好吧,onInit 是作为创建 TextToSpeech(context, this); 的结果而被调用的。 TextToSpeech 构造函数的第二个参数是 OnInitListener 的实现,它具有 onInit 方法。语音类正在实现 OnInitListener 接口。

标签: android text-to-speech


【解决方案1】:

您的代码应该可以工作,但我会试试这个,看看它是否能解决问题:

在您的代码顶部放置:

Handler handler = new Handler()

然后让你的其他代码有这个:

handler.post(new Runnable()
    {
        @Override
        public void run()
        {
            tts.setOnUtteranceCompletedListener(new SpeechFinishedListener());
            tts.setLanguage(Locale.getDefault());
            tts.setSpeechRate(settings.getSpeed());
            tts.setPitch(settings.getPitch());                    
        }
    });

【讨论】:

  • 谢谢,我试试看,也想了解一下这篇文章。是否类似于在稍后调用的 UI 线程上发布?像invokeLater of swing ??
【解决方案2】:

我解决了这个问题,这是它的工作原理

有一个案例是我在非 ui 线程上创建 Speaker 对象。 onInit() 的回调将出现在 UI 线程/主线程上..

现在即使运行它可能并不总是崩溃,但我意识到它不安全,并且有可能出现空指针异常..

所以我更新的代码看起来像这样

public Speaker(final Context context, final Settings settings) 
{   
    this.settings = settings;
    params = new HashMap<String, String>();      
    params.put(TextToSpeech.Engine.KEY_PARAM_STREAM, String.valueOf(AudioManager.STREAM_ALARM));
    params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "myfreeapps");

    synchronize(synchobject)
    {
       tts= new TextToSpeech(context, this);   
    }
    Utils.log(TAG, "Created TextToSpeech..");
}

@Override
public void onInit(final int status) 
{
    Utils.log(TAG, "TTS onInit..");

    synchronize(synchobject)
    {

    tts.setOnUtteranceCompletedListener(new SpeechFinishedListener());
    tts.setLanguage(Locale.getDefault());
    tts.setSpeechRate(settings.getSpeed());
    tts.setPitch(settings.getPitch());      
    ready = true;
    }

}

这似乎解决了我的问题,感谢每一位帮助我的人,..

【讨论】:

    【解决方案3】:

    可能是设备上没有安装 TextToSpeech 引擎。

    【讨论】:

    • 我调查了TextToSpeech 的代码第三行的tack trace,。在 android.speech.tts.TextToSpeech$1.onServiceConnected(TextToSpeech.java:451) 。使用成功代码调用 onInit
    【解决方案4】:

    我是否正确假设 Speaker 是从您的主要活动之外调用的类?

    似乎在构造函数之前调用了 onInit 方法。我看到你已经用日志标签检查了这个;你的结果是什么?

    【讨论】:

    • Speaker 实例是在 Service 的 onStartCommand(..) 中创建的。我只能从 android 开发者控制台获得堆栈跟踪。我认为不可能在构造函数之前调用 onInit() ??
    • 我的印象是 onInit 永远不应该在构造函数之前被调用。在进行故障排除时,仔细检查实施永远不会有什么坏处。
    猜你喜欢
    • 2013-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多