Android活动在服务准备好之前访问服务的静态引用

时间:2013-08-06 13:28:35

标签: java android android-service text-to-speech

我正在尝试从活动中触发文本到语音服务,并且基于某些事件的活动会导致将相应的字符串发送到说出来的服务。

这是我的TTSService:

public class TTSService extends Service implements TextToSpeech.OnInitListener{

    private String str;
    private TextToSpeech mTts;
    private static final String TAG="TTSService";
    public static TTSService sInstance;



    @Override

    public IBinder onBind(Intent arg0) {

        return null;
    }


    @Override
    public void onCreate() {

        mTts = new TextToSpeech(this,
                this  // OnInitListener
        );
        mTts.setSpeechRate(0.5f);
        Log.v(TAG, "oncreate_service");
        str ="turn left please ";
        super.onCreate();
        sInstance=this;
    }


    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        if (mTts != null) {
            mTts.stop();
            mTts.shutdown();
        }
        super.onDestroy();
    }


    @Override
    public void onInit(int status) {
        Log.v(TAG, "oninit");
        if (status == TextToSpeech.SUCCESS) {
            int result = mTts.setLanguage(Locale.US);
            if (result == TextToSpeech.LANG_MISSING_DATA ||
                    result == TextToSpeech.LANG_NOT_SUPPORTED) {
                Log.v(TAG, "Language is not available.");
            } else {

                sayHello(str);

            }
        } else {
            Log.v(TAG, "Could not initialize TextToSpeech.");
        }
    }
    public void sayHello(String str) {
        mTts.speak(str,
                TextToSpeech.QUEUE_FLUSH,
                null);
    }
}

以下是我的活动创建服务的代码:

public void onCreate(Bundle savedInstanceState) {
         //rest of code.....
        Intent serviceIntent = new Intent();
        serviceIntent.setAction("com.packagename.texttospeech.TTSService");
        startService(serviceIntent);
}

这是活动的onSensorChanged事件处理程序:

 @Override
    public void onSensorChanged(SensorEvent event) {
        float distance = event.values[0];
        while(TTSService.sInstance==null){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }
        }
        TTSService.sInstance.sayHello(Float.valueOf(distance).toString());

    }

现在当我运行上面的活动时,它会挂起并且不响应。

在删除上面的while循环时,我得到以下错误跟踪:

ERROR/AndroidRuntime(7469): FATAL EXCEPTION: main
        java.lang.NullPointerException
        at com.packagename.texttospeech.SensorTestActivity.onSensorChanged(SensorTestActivity.java:51)
        at android.hardware.SensorManager$ListenerDelegate$1.handleMessage(SensorManager.java:456)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:123)
        at android.app.ActivityThread.main(ActivityThread.java:4633)
        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:858)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
        at dalvik.system.NativeStart.main(Native Method)

很明显,问题在于行(SensorTestActivity.java:51):

TTSService.sInstance.sayHello(Float.valueOf(distance).toString());

此处sInstance为空,表明TTSService的onCreate()尚未完成。那么我应该如何让我的活动等到TTSService准备好使用?

1 个答案:

答案 0 :(得分:2)

  

那么我应该如何让我的活动等到TTSService准备好被使用?

你没有。最有可能的是,你完全摆脱了服务,因为它似乎没有必要。让活动直接使用TextToSpeech

如果您有明确的理由说明您的应用需要将其用于服务中:

第1步:删除public static TTSService sInstancesayHello()方法。

第2步:摆脱现有的startService()电话。

步骤3:用TTSService.sInstance.sayHello(Float.valueOf(distance).toString());呼叫替换startService(),向服务发送命令,将要说的消息添加为String额外的。

步骤#4:在您的服务的onStartCommand()中,如果TTS初始化完成,请致电speak()说出请求的字符串(从额外提取)。如果TTS初始化尚未完成,请将字符串附加到ArrayList<String>

步骤5:在onInit()中,将NullPointerException - 生成sayHello()来电替换为ArrayList<String>内容的循环至speak()

这样,您的活动并不关心TTS引擎是否准备就绪。它只是将请求发送到服务,服务将其排队直到TTS准备就绪,此时它将被播放。