Android-百度语音合成工具类封装内存泄漏防护与简化调用
目录
Android 百度语音合成工具类封装:内存泄漏防护与简化调用
适配高版本 Android 系统
使用 Application Context 避免内存泄漏
默认回调支持,调用更简洁
线程安全与资源释放优化
完整代码:BaiduTTSManager.java:
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import androidx.annotation.NonNull;
import com.baidu.tts.client.SpeechError;
import com.baidu.tts.client.SpeechSynthesizer;
import com.baidu.tts.client.SpeechSynthesizerListener;
import com.baidu.tts.client.TtsMode;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 百度语音合成工具类
* - 适配高版本 Android 系统
* - 使用 Application Context 避免内存泄漏
* - 提供默认回调,简化调用逻辑
* - 线程安全与资源释放优化
*/
public class BaiduTTSManager {
private static final String TAG = "BaiduTTSManager";
private static BaiduTTSManager instance;
private SpeechSynthesizer speechSynthesizer;
private Context appContext; // 使用 Application Context
private Handler mainHandler = new Handler(Looper.getMainLooper());
private ExecutorService executorService = Executors.newSingleThreadExecutor();
private TTSState currentState = TTSState.UNINITIALIZED;
private BaiduTTSManager(Context context) {
// 使用 Application Context,避免内存泄漏
this.appContext = context.getApplicationContext();
}
/**
* 获取单例实例
*/
public static synchronized BaiduTTSManager getInstance(Context context) {
if (instance == null) {
instance = new BaiduTTSManager(context);
}
return instance;
}
/**
* 初始化 TTS(简化调用,无需回调)
*/
public void init(String appId, String apiKey, String secretKey) {
init(appId, apiKey, secretKey, new DefaultTTSInitListener());
}
/**
* 初始化 TTS(带回调)
*/
public void init(String appId, String apiKey, String secretKey, @NonNull TTSInitListener listener) {
if (currentState == TTSState.INITIALIZING || currentState == TTSState.INITIALIZED) {
Log.w(TAG, "TTS is already initializing or initialized");
return;
}
currentState = TTSState.INITIALIZING;
executorService.execute(() -> {
try {
speechSynthesizer = SpeechSynthesizer.getInstance();
speechSynthesizer.setContext(appContext); // 使用 Application Context
speechSynthesizer.setAppId(appId);
speechSynthesizer.setApiKey(apiKey, secretKey);
speechSynthesizer.initTts(TtsMode.ONLINE);
currentState = TTSState.INITIALIZED;
mainHandler.post(() -> listener.onInitSuccess());
} catch (Exception e) {
currentState = TTSState.UNINITIALIZED;
Log.e(TAG, "TTS initialization failed: " + e.getMessage());
mainHandler.post(() -> listener.onInitFailed(e.getMessage()));
}
});
}
/**
* 播报文本(简化调用,无需回调)
*/
public void speak(String text) {
speak(text, new DefaultTTSSpeakListener());
}
/**
* 播报文本(带回调)
*/
public void speak(String text, @NonNull TTSSpeakListener listener) {
if (currentState != TTSState.INITIALIZED) {
Log.e(TAG, "TTS is not initialized!");
mainHandler.post(() -> listener.onSpeakFailed("TTS 未初始化"));
return;
}
if (speechSynthesizer == null) {
Log.e(TAG, "SpeechSynthesizer is null!");
mainHandler.post(() -> listener.onSpeakFailed("TTS 初始化失败"));
return;
}
try {
speechSynthesizer.speak(text);
setSpeechSynthesizerListener(listener);
mainHandler.post(() -> listener.onSpeakStart());
} catch (Exception e) {
Log.e(TAG, "Speak failed: " + e.getMessage());
mainHandler.post(() -> listener.onSpeakFailed(e.getMessage()));
}
}
/**
* 设置 TTS 监听器
*/
private void setSpeechSynthesizerListener(@NonNull TTSSpeakListener listener) {
if (speechSynthesizer != null) {
speechSynthesizer.setSpeechSynthesizerListener(new SpeechSynthesizerListener() {
@Override
public void onSynthesizeStart(String s) {
// 合成开始
}
@Override
public void onSynthesizeDataArrived(String s, byte[] bytes, int i) {
// 合成数据回调
}
@Override
public void onSynthesizeFinish(String s) {
// 合成完成
}
@Override
public void onSpeechStart(String s) {
// 播报开始
mainHandler.post(() -> listener.onSpeakStart());
}
@Override
public void onSpeechProgressChanged(String s, int i) {
// 播报进度
}
@Override
public void onSpeechFinish(String s) {
// 播报完成
mainHandler.post(() -> listener.onSpeakFinish());
}
@Override
public void onError(String s, SpeechError speechError) {
// 播报错误
mainHandler.post(() -> listener.onSpeakFailed(speechError.description));
}
});
}
}
/**
* 释放资源
*/
public void release() {
if (speechSynthesizer != null) {
speechSynthesizer.release();
speechSynthesizer = null;
}
currentState = TTSState.UNINITIALIZED;
executorService.shutdown();
}
/**
* TTS 状态枚举
*/
private enum TTSState {
UNINITIALIZED, // 未初始化
INITIALIZING, // 初始化中
INITIALIZED, // 初始化完成
}
/**
* TTS 初始化回调接口
*/
public interface TTSInitListener {
void onInitSuccess();
void onInitFailed(String errorMessage);
}
/**
* TTS 播报回调接口
*/
public interface TTSSpeakListener {
void onSpeakStart();
void onSpeakFinish();
void onSpeakFailed(String errorMessage);
}
/**
* 默认初始化回调(空实现)
*/
private static class DefaultTTSInitListener implements TTSInitListener {
@Override
public void onInitSuccess() {
Log.d(TAG, "TTS 初始化成功");
}
@Override
public void onInitFailed(String errorMessage) {
Log.e(TAG, "TTS 初始化失败: " + errorMessage);
}
}
/**
* 默认播报回调(空实现)
*/
private static class DefaultTTSSpeakListener implements TTSSpeakListener {
@Override
public void onSpeakStart() {
Log.d(TAG, "开始播报");
}
@Override
public void onSpeakFinish() {
Log.d(TAG, "播报完成");
}
@Override
public void onSpeakFailed(String errorMessage) {
Log.e(TAG, "播报失败: " + errorMessage);
}
}
}
使用示例
1. 初始化 TTS
BaiduTTSManager ttsManager = BaiduTTSManager.getInstance(this);
ttsManager.init("你的App ID", "你的API Key", "你的Secret Key");
2. 播报文本
ttsManager.speak("你好,百度语音合成");
3. 带回调的播报
ttsManager.speak("你好,百度语音合成", new BaiduTTSManager.TTSSpeakListener() {
@Override
public void onSpeakStart() {
Log.d(TAG, "开始播报");
}
@Override
public void onSpeakFinish() {
Log.d(TAG, "播报完成");
}
@Override
public void onSpeakFailed(String errorMessage) {
Log.e(TAG, "播报失败: " + errorMessage);
}
});
4. 释放资源
@Override
protected void onDestroy() {
super.onDestroy();
if (ttsManager != null) {
ttsManager.release();
}
}
5.在 Application 中带回调使用
import android.app.Application;
import android.util.Log;
public class MyApplication extends Application {
private static final String TAG = "MyApplication";
private BaiduTTSManager ttsManager;
@Override
public void onCreate() {
super.onCreate();
// 初始化 TTS
ttsManager = BaiduTTSManager.getInstance(this);
ttsManager.init("你的App ID", "你的API Key", "你的Secret Key", new BaiduTTSManager.TTSInitListener() {
@Override
public void onInitSuccess() {
Log.d(TAG, "TTS 初始化成功");
}
@Override
public void onInitFailed(String errorMessage) {
Log.e(TAG, "TTS 初始化失败: " + errorMessage);
}
});
// 播报文本
ttsManager.speak("欢迎使用百度语音合成", new BaiduTTSManager.TTSSpeakListener() {
@Override
public void onSpeakStart() {
Log.d(TAG, "开始播报");
}
@Override
public void onSpeakFinish() {
Log.d(TAG, "播报完成");
}
@Override
public void onSpeakFailed(String errorMessage) {
Log.e(TAG, "播报失败: " + errorMessage);
}
});
}
@Override
public void onTerminate() {
super.onTerminate();
// 释放资源
if (ttsManager != null) {
ttsManager.release();
}
}
}
5.在 Application 中不带回调使用
public class MyApplication extends Application {
private BaiduTTSManager ttsManager;
@Override
public void onCreate() {
super.onCreate();
ttsManager = BaiduTTSManager.getInstance(this);
ttsManager.init("你的App ID", "你的API Key", "你的Secret Key");
}
public BaiduTTSManager getTTSManager() {
return ttsManager;
}
}
优点
高兼容性:
适配 Android 6.0 及以上版本,动态权限处理和存储适配。
内存泄漏防护:
使用 Application Context,避免持有 Activity 引用。
简化调用:
提供默认回调实现,调用方无需强制实现回调接口。
线程安全:
使用线程池管理异步任务,确保线程安全。
资源释放:
在 release 方法中清理所有资源,避免内存泄漏。
总结
该工具类封装了百度语音合成的核心功能,适用于 Android 平台,具有高兼容性、内存泄漏防护和简化调用等优点。通过清晰的接口设计和优化,开发者可以轻松集成语音播报功能,同时避免常见的内存泄漏问题。