Not so! (the claim that Android does not run simultaneous processes).
Android does indeed run multiple processes simultaneously, and I'll
prove it to you. But first, an explanation for the confusion. In
Android, a *well-behaved* application will suspend user interaction
when the onPause() callback is invoked. This appears to the user that
the application has been put to sleep. And yes indeed, an application
in this state could be killed if resources get tight. If your
application is speaking text, and the user gets a phone call, of
course you want the audio to stop while the user is talking on the
phone. But your application doesn't stop running just because some
other app has been given center stage. If you don't believe me, try
out this little demo:
/res/layout/main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="
http://schemas.android.com/apk/res/
android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button android:id="@+id/startStopBtn"
android:text="Start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:enabled="false"
android:onClick="startStop" />
</LinearLayout>
and now your Java code:
import java.util.HashMap;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.speech.tts.TextToSpeech.OnUtteranceCompletedListener;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity implements OnInitListener,
OnUtteranceCompletedListener {
private int counter = 1;
private Button startStopBtn = null;
private static final int REQ_TTS_STATUS_CHECK = 0;
private static final String TAG = "TTS Demo Background";
private TextToSpeech mTts;
private HashMap<String, String> params = new HashMap<String,
String>();
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startStopBtn = (Button)findViewById(R.id.startStopBtn);
// Check to be sure that TTS exists and is okay to use
Intent checkIntent = new Intent();
checkIntent.setAction
(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
startActivityForResult(checkIntent, REQ_TTS_STATUS_CHECK);
}
public void startStop(View view) {
if(mTts.isSpeaking()) {
startStopBtn.setText("Start");
mTts.stop();
}
else {
mTts.setOnUtteranceCompletedListener(this);
startStopBtn.setText("Stop");
sayNext();
}
};
private void sayNext() {
params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,
"value");
mTts.speak(String.valueOf(counter++), TextToSpeech.QUEUE_ADD,
params);
params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,
"silence");
mTts.playSilence(2000, TextToSpeech.QUEUE_ADD, params);
}
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
if (requestCode == REQ_TTS_STATUS_CHECK) {
switch (resultCode) {
case TextToSpeech.Engine.CHECK_VOICE_DATA_PASS:
// TTS is up and running
mTts = new TextToSpeech(this, this);
Log.v(TAG, "Pico is installed okay");
break;
case TextToSpeech.Engine.CHECK_VOICE_DATA_BAD_DATA:
case TextToSpeech.Engine.CHECK_VOICE_DATA_MISSING_DATA:
case TextToSpeech.Engine.CHECK_VOICE_DATA_MISSING_VOLUME:
// missing data, install it
Log.v(TAG, "Need language stuff: " + resultCode);
Intent installIntent = new Intent();
installIntent.setAction(
TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installIntent);
break;
case TextToSpeech.Engine.CHECK_VOICE_DATA_FAIL:
default:
Log.e(TAG, "Got a failure. TTS apparently not
available");
}
}
else {
// Got something else
}
}
@Override
public void onInit(int status) {
// Now that the TTS engine is ready, we enable the button
if( status == TextToSpeech.SUCCESS) {
startStopBtn.setEnabled(true);
}
}
@Override
public void onPause()
{
super.onPause();
Log.v(TAG,"In onPause()");
}
@Override
public void onDestroy()
{
super.onDestroy();
// if we're going away, clean up
if( mTts != null) {
mTts.stop();
mTts.shutdown();
}
}
@Override
public void onUtteranceCompleted(String uttId) {
Log.v(TAG,"Got utterance: " + uttId);
if("silence".compareTo(uttId) == 0)
sayNext();
}
}
Run it and click the Start button. Now hit the Home button and start
up some other application. You should continue to hear numbers being
counted to you even though you're now using another application.
Pretty soon I think you'll realize why applications "go to sleep" when
they lose focus. If you change the duration argument of playSilence to
a smaller number than 2000 (100 did it for me), you will find that
Android decides to kill the application a little while after it has
been backgrounded.
- dave
> The vOICe for Androidhttp://
www.seeingwithsound.com/android.htm