Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách sử dụng Android TextToSpeech từ Singleton

TextToSpeech Singleton Pattern

TextToSpeech (TTS) engine tốn tài nguyên khởi tạo. Sử dụng Singleton đảm bảo chỉ tạo một instance TTS trong suốt vòng đời ứng dụng, tránh lag khi phát âm thanh liên tục.

Bước 1: Tạo dự án

Android Studio → File → New Project.

Bước 2: Giao diện (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical"
    android:padding="16dp">

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Nhập nội dung cần đọc"
        android:inputType="textMultiLine"
        android:minHeight="100dp" />

    <Button
        android:id="@+id/show"
        android:text="Phát âm thanh từ Singleton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp" />

</LinearLayout>

Bước 3: MainActivity.java

package com.example.ttssingleton;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends AppCompatActivity {
    Button btnSpeak;
    EditText editText;
    TtsSingleton ttsSingleton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btnSpeak = findViewById(R.id.show);
        editText = findViewById(R.id.editText);
        ttsSingleton = TtsSingleton.getInstance();
        ttsSingleton.init(getApplicationContext());

        btnSpeak.setOnClickListener(v -> {
            String text = editText.getText().toString().trim();
            if (!text.isEmpty()) {
                ttsSingleton.speak(text);
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ttsSingleton.shutdown(); // Quan trọng: giải phóng TTS engine
    }
}

Bước 4: TtsSingleton.java

package com.example.ttssingleton;

import android.content.Context;
import android.speech.tts.TextToSpeech;
import android.widget.Toast;
import java.util.Locale;

public class TtsSingleton {
    private TextToSpeech tts;
    private Context appContext;
    private boolean isInitialized = false;
    private static final TtsSingleton ourInstance = new TtsSingleton();

    public static synchronized TtsSingleton getInstance() {
        return ourInstance;
    }

    private TtsSingleton() { }

    public void init(Context context) {
        if (appContext == null) {
            this.appContext = context.getApplicationContext();
            tts = new TextToSpeech(appContext, status -> {
                if (status == TextToSpeech.SUCCESS) {
                    int result = tts.setLanguage(Locale.US);
                    if (result == TextToSpeech.LANG_MISSING_DATA || 
                        result == TextToSpeech.LANG_NOT_SUPPORTED) {
                        // Ngôn ngữ không hỗ trợ
                    } else {
                        isInitialized = true;
                    }
                }
            });
        }
    }

    public void speak(String text) {
        if (tts != null && isInitialized) {
            tts.speak(text, TextToSpeech.QUEUE_FLUSH, null, "utteranceId");
        }
    }

    public void shutdown() {
        if (tts != null) {
            tts.stop();
            tts.shutdown();
            tts = null;
            isInitialized = false;
        }
    }

    public boolean isReady() {
        return isInitialized;
    }
}

Chạy ứng dụng

Nhập văn bản → nhấn nút → nghe giọng đọc. Thử xoay màn hình, văn bản vẫn được đọc đúng vì Singleton giữ instance TTS.

⚠️ Các vấn đề cần lưu ý

  • Phải gọi shutdown() trong onDestroy() để tránh memory leak TTS engine.
  • Khởi tạo bất đồng bộ: TTS cần thời gian init, nên kiểm tra isInitialized trước khi speak.
  • Ngôn ngữ: Kiểm tra setLanguage() trả về SUCCESS trước khi dùng.
  • API 21+: Nên dùng speak(text, QUEUE_FLUSH, null, utteranceId) thay vì phiên bản cũ.

Cải tiến: Hỗ trợ callback khi nói xong

public void speak(String text, UtteranceProgressListener listener) {
    if (tts != null && isInitialized) {
        tts.setOnUtteranceProgressListener(listener);
        Bundle params = new Bundle();
        params.putString(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "myId");
        tts.speak(text, TextToSpeech.QUEUE_FLUSH, params, "myId");
    }
}