要求是在使用Android文字转语音功能后,在其后播放一个铃声。
for (final Integer orderId : voiceoverIds) {
alertChimePlayer = MediaPlayer.create(getApplicationContext(), R.raw.orderalert);
alertChimePlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
String orderSpeechText = "Number " + orderId;
textToSpeech.speak(orderSpeechText, TextToSpeech.QUEUE_ADD, null, "ORDER_NO_" + orderId);
textToSpeech.playSilentUtterance(2000, TextToSpeech.QUEUE_ADD, "PAUSE_NO_" + orderId);
System.out.println(">>>>>>>>>>>>>>>>>>> orderSpeechText : " + orderSpeechText);
}
});
alertChimePlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
alertChimePlayer.start();
}
});
}
但是这只能工作一次。如何正确处理呢?
答案 0 :(得分:2)
好问题。整夜熬夜。问题在于,在循环中,这些提示音会很快同时全部发送到媒体播放器。 Media Player无法真正正确处理此问题。 这是我的解决方案。我正在使用SoundPool演奏提示音,因为它更适合重复播放短声音。 我还使用计时器线程来触发“铃音+语音合成语音(tts)”序列。 tts onUtteranceProgressListener用于在发出提示音后播放tts。 这是经过测试的代码。您将听到的是: 铃声“数字1”(延迟3秒) 铃声“数字2”(延迟3秒) ...继续直到终止
import android.app.Activity;
import android.content.Context;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.SoundPool;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.speech.tts.UtteranceProgressListener;
import android.util.Log;
import java.util.Locale;
public class MainActivity extends Activity implements TextToSpeech.OnInitListener {
AudioAttributes aa;
SoundPool sp;
private TextToSpeech tts;
int MAX_STREAMS = 5;
int REPEAT = 0;
int DELAY = 3000;
int orderId = 0;
// Clock thread
Thread m_clockThread;
boolean m_bClockThreadStop;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e("TTS", "Starting...");
// Set up the sound pool sound
AudioAttributes aa = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.setUsage(AudioAttributes.USAGE_MEDIA)
.build();
sp = new SoundPool.Builder()
.setMaxStreams(8)
.setAudioAttributes(aa)
.build();
// Start the tts
tts = new TextToSpeech(MainActivity.this,MainActivity.this);
tts.setLanguage(Locale.US);
}
@Override
public void onInit(int status) {
Log.e("TTS", "Enter onInit...");
if (status == TextToSpeech.SUCCESS) {
int result = tts.setLanguage(Locale.US);
if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) {
Log.e("TTS", "This Language is not supported");
} else {
Log.e("TTS", "onInit Success");
// create and run clock thread
createAndRunClockThread(this);
}
} else {
Log.e("TTS", "onInit Fail");
}
}
public void createAndRunClockThread(final Activity act) {
m_bClockThreadStop=false;
m_clockThread = new Thread(new Runnable() {
public void run() {
while(!m_bClockThreadStop) {
try {
act.runOnUiThread(new Runnable() {
public void run() {
playChime();
}
});
Thread.sleep(DELAY);
}
catch(InterruptedException e) {
Log.e("TTS", "ClockThread fail");
}
}
}
});
m_clockThread.start();
}
private void playChime() {
Log.e("TTS", "Entering startChimes...");
sp.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
@Override
public void onLoadComplete(final SoundPool soundPool, final int soundId, int status) {
final int priority = 0;
final int repeat = 0;
final float rate = 1.f; // Frequency Rate can be from .5 to 2.0
// Set volume
AudioManager mgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
float streamVolumeCurrent = mgr.getStreamVolume(AudioManager.STREAM_MUSIC);
float streamVolumeMax = mgr.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
final float volume = streamVolumeCurrent / streamVolumeMax;
// Play a chime followed by the tts
tts.speak("Number " + orderId, TextToSpeech.QUEUE_ADD, null, "ID" + orderId);
tts.setOnUtteranceProgressListener(new UtteranceProgressListener() {
@Override
public void onStart(String utteranceId) {
// Speaking started.
sp.play(soundId, volume, volume, priority, repeat, rate);
}
@Override
public void onDone(String utteranceId) {
// Speaking stopped.
orderId = orderId + 1;
}
@Override
public void onError(String utteranceId) {
// There was an error.
}
});
}
});
sp.load(this, R.raw.beep, 1);
}
}
答案 1 :(得分:0)
感谢@Mark W的回答。但是我正在考虑不涉及明显延迟/睡眠的解决方案。
所以我正在实现此服务类。
public class OrderNoticeService extends Service implements TextToSpeech.OnInitListener {
private List<OrderSpeechAsyncTask> orderSpeechAsyncTasks = new ArrayList<>();
private TextToSpeech textToSpeech;
private Context context;
public void addToOrderNoticeQueue(int orderId) {
String orderSpeechText = String.format(getResources().getString(R.string.order_voice_over_default_text), Integer.toString(orderId));
orderSpeechAsyncTasks.add(new OrderSpeechAsyncTask(getApplicationContext(), R.raw.orderalert, orderSpeechText, textToSpeech, new AsyncTaskCallback() {
@Override
public void onTaskCompleted(Object response) {
}
}));
if (orderSpeechAsyncTasks.size() > 1) {
final OrderSpeechAsyncTask orderSpeechAsyncTask = orderSpeechAsyncTasks.get(orderSpeechAsyncTasks.size() - 1);
OrderSpeechAsyncTask orderSpeechAsyncTaskPrior = orderSpeechAsyncTasks.get(orderSpeechAsyncTasks.size() - 2);
orderSpeechAsyncTaskPrior.setAsyncTaskCallback(new AsyncTaskCallback() {
@Override
public void onTaskCompleted(Object response) {
try {
orderSpeechAsyncTask.execute();
System.out.println("Execution!");
} catch (Exception e) {
}
}
});
}
}
@Override
public void onCreate() {
textToSpeech = new TextToSpeech(this, this);
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
context = this;
return Service.START_STICKY;
}
private static final String TAG = "OrderNoticeService";
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "OrderNoticeService onBind");
return mBinder;
}
@Override
public void onDestroy() {
if (textToSpeech != null) {
textToSpeech.stop();
textToSpeech.shutdown();
}
Log.i(TAG, "OrderNoticeService onDestroy");
}
@Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
OrderNoticeVoiceOverThread orderNoticeVoiceOverThread = new OrderNoticeVoiceOverThread(context, orderSpeechAsyncTasks);
orderNoticeVoiceOverThread.start();
} else {
System.out.println("Text To Speech not supported!");
}
}
private class OrderNoticeVoiceOverThread extends Thread {
private Context context;
private List<OrderSpeechAsyncTask> orderSpeechAsyncTasks;
private boolean anyTaskRunning = false;
public OrderNoticeVoiceOverThread(Context context, List<OrderSpeechAsyncTask> orderSpeechAsyncTasks) {
this.context = context;
this.orderSpeechAsyncTasks = orderSpeechAsyncTasks;
}
public void run() {
while (true) {
for (OrderSpeechAsyncTask orderSpeechAsyncTask : new ArrayList<OrderSpeechAsyncTask>(orderSpeechAsyncTasks)) {
if (orderSpeechAsyncTask != null && orderSpeechAsyncTask.getStatus().equals(AsyncTask.Status.RUNNING)) {
anyTaskRunning = true;
break;
}
}
if (!anyTaskRunning) {
for (OrderSpeechAsyncTask orderSpeechAsyncTask : new ArrayList<OrderSpeechAsyncTask>(orderSpeechAsyncTasks)) {
if (orderSpeechAsyncTask != null && orderSpeechAsyncTask.getStatus().equals(AsyncTask.Status.PENDING)) {
orderSpeechAsyncTask.execute();
anyTaskRunning = false;
break;
}
}
}
}
}
}
private final IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
public OrderNoticeService getService() {
return OrderNoticeService.this;
}
}
}
还有OrderSpeechAsyncTask
。
public class OrderSpeechAsyncTask extends AsyncTask<Void, Void, Void> {
private static final String LOG_TAG = OrderSpeechAsyncTask.class.getSimpleName();
private MediaPlayer mediaPlayer;
private int soundId;
private Context context;
private String orderSpeechText;
private AsyncTaskCallback asyncTaskCallback;
private TextToSpeech textToSpeech;
public OrderSpeechAsyncTask(final Context context, int soundId, String orderSpeechText, TextToSpeech textToSpeech, AsyncTaskCallback asyncTaskCallback) {
this.context = context;
this.soundId = soundId;
this.orderSpeechText = orderSpeechText;
this.textToSpeech = textToSpeech;
this.asyncTaskCallback = asyncTaskCallback;
}
public AsyncTaskCallback getAsyncTaskCallback() {
return asyncTaskCallback;
}
public void setAsyncTaskCallback(AsyncTaskCallback asyncTaskCallback) {
this.asyncTaskCallback = asyncTaskCallback;
}
@Override
protected Void doInBackground(Void... params) {
mediaPlayer = MediaPlayer.create(context, soundId);
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mediaPlayer.release();
textToSpeech.speak(orderSpeechText, TextToSpeech.QUEUE_ADD, null, "ORDER_NO_" + orderSpeechText);
textToSpeech.playSilentUtterance(2000, TextToSpeech.QUEUE_ADD, "PAUSE_NO_" + orderSpeechText);
textToSpeech.setOnUtteranceProgressListener(new UtteranceProgressListener() {
@Override
public void onStart(String utteranceId) {
}
@Override
public void onDone(String utteranceId) {
asyncTaskCallback.onTaskCompleted(null);
}
@Override
public void onError(String utteranceId) {
}
});
}
});
mediaPlayer.start();
return null;
}
}
到目前为止,它可以处理以下内容;
要做;