Perfecte — et dono una guia pas a pas (en català) per crear una app Android (no Compose) anomenada tts_cat que fa servir TextToSpeech. La UI serà basada en XML i tindrà:
- Un contenidor (usaré 
ConstraintLayout) amb un camp de text (EditText) amb text precarregat en català. - 2 botons: Parlar i Parar.
 - Lògica a 
MainActivity.ktper inicialitzar TTS, parlar el text i aturar la parla. - Maneig de la vida del TTS (alliberament a 
onDestroy) i comprovació si falta la veu catalana (i acció per instal·lar dades de TTS). 
Segueix aquests passos i copia/enganxa els fitxers.
1) Crear el projecte a Android Studio
File > New > New Project.- Escull Empty Activity (no Compose).
 - Nom: 
tts_cat - Language: Kotlin
 - Minimum SDK: API 21+ (recomanat)
 - Finalitza i deixa que Android Studio generi el projecte.
 
2) build.gradle (Module: app)
Assegura’t que tens dependències bàsiques (Android Studio normalment ja les posa). Exemple rellevant:
android {
    compileSdk 34
    defaultConfig {
        applicationId "com.example.tts_cat"
        minSdk 21
        targetSdk 34
        versionCode 1
        versionName "1.0"
    }
    // no cal activar Compose
}
dependencies {
    implementation "androidx.core:core-ktx:1.10.1"
    implementation "androidx.appcompat:appcompat:1.6.1"
    implementation "com.google.android.material:material:1.9.0"
}
(Si Android Studio usa versions diferents, deixa les que proposa; el més important: no fer servir dependències de Compose.)
3) Layout XML: res/layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/rootLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:padding="16dp">
    <!-- Contenidor (equivalent "div") -->
    <LinearLayout
        android:id="@+id/container"
        android:orientation="vertical"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:padding="12dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:background="?attr/selectableItemBackground">
        
        <!-- EditText amb text precarregat en català -->
        <EditText
            android:id="@+id/etText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Introdueix text..."
            android:inputType="textMultiLine"
            android:minLines="3"
            android:gravity="top|start"
            android:text="Hola! Aquest és un missatge de prova en català." />
        <!-- Botons en fila -->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_marginTop="12dp">
            <Button
                android:id="@+id/btnSpeak"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="Parlar" />
            <Button
                android:id="@+id/btnStop"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginStart="8dp"
                android:layout_weight="1"
                android:text="Parar" />
        </LinearLayout>
    </LinearLayout>
    <!-- Opcional: text d'estat a la part de baix -->
    <TextView
        android:id="@+id/tvStatus"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Estat: inactiu"
        android:layout_marginTop="16dp"
        app:layout_constraintTop_toBottomOf="@+id/container"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Nota: he posat un
LinearLayoutdinsConstraintLayoutper crear el “contenidor” que demanaves (equivalent d’un<div>). L’EditTextarriba amb text precarregat.
4) MainActivity.kt (Kotlin) — lògica completa TTS
Copia aquest fitxer (modifica el package per adaptar-lo a applicationId si cal):
package com.example.tts_cat
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.speech.tts.TextToSpeech
import android.speech.tts.TextToSpeech.Engine
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import java.util.Locale
class MainActivity : AppCompatActivity(), TextToSpeech.OnInitListener {
    private var tts: TextToSpeech? = null
    private lateinit var etText: EditText
    private lateinit var btnSpeak: Button
    private lateinit var btnStop: Button
    private lateinit var tvStatus: TextView
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // bind views
        etText = findViewById(R.id.etText)
        btnSpeak = findViewById(R.id.btnSpeak)
        btnStop = findViewById(R.id.btnStop)
        tvStatus = findViewById(R.id.tvStatus)
        // Inicialitza TextToSpeech
        tts = TextToSpeech(this, this)
        btnSpeak.setOnClickListener {
            val text = etText.text.toString().ifBlank { "Hola! Aquest és un missatge de prova en català." }
            speakText(text)
        }
        btnStop.setOnClickListener {
            stopSpeaking()
        }
    }
    override fun onInit(status: Int) {
        if (status == TextToSpeech.SUCCESS) {
            // Intentem establir català (Catalonia, Espanya)
            val localeCa = Locale("ca", "ES")
            val result = tts?.setLanguage(localeCa)
            if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) {
                // La veu catalana no està disponible
                tvStatus.text = "Estat: Català no disponible, s'utilitza idioma per defecte."
                Toast.makeText(this, "Veu catalana no disponible. Pots instal·lar dades TTS.", Toast.LENGTH_LONG).show()
                // Prova d'obrir instal·lador de dades TTS (pot permetre descarregar veus)
                try {
                    val installIntent = Intent(Engine.ACTION_INSTALL_TTS_DATA)
                    startActivity(installIntent)
                } catch (e: Exception) {
                    // Si no és suportat, només fem servir l'idioma per defecte
                    tts?.language = Locale.getDefault()
                }
            } else {
                // Tot OK: català disponible
                tvStatus.text = "Estat: TTS inicialitzat (català)."
                // Opcional: parla automàticament en obrir l'app
                speakText("Hola Android! Benvingut a l'aplicació.")
            }
        } else {
            tvStatus.text = "Estat: Error al inicialitzar TTS."
            Toast.makeText(this, "No s'ha pogut inicialitzar TextToSpeech.", Toast.LENGTH_SHORT).show()
        }
    }
    private fun speakText(text: String) {
        if (tts == null) return
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            // id d'utt
            tts?.speak(text, TextToSpeech.QUEUE_FLUSH, null, "UTTERANCE_ID")
        } else {
            @Suppress("DEPRECATION")
            tts?.speak(text, TextToSpeech.QUEUE_FLUSH, null)
        }
        tvStatus.text = "Estat: parlant..."
    }
    private fun stopSpeaking() {
        tts?.stop()
        tvStatus.text = "Estat: aturat"
    }
    override fun onDestroy() {
        tts?.stop()
        tts?.shutdown()
        super.onDestroy()
    }
}
Explicació ràpida del codi
- La 
MainActivityimplementaTextToSpeech.OnInitListener. tts = TextToSpeech(this, this)inicialitza el motor.onInitcomprova si el català (Locale("ca","ES")) està suportat. Si no hi és, intenta obrir l’instal·lador de dades TTS (Engine.ACTION_INSTALL_TTS_DATA).speakText(...)cridatts.speak(...). Per API >= 21 s’usa el paràmetreutteranceId.stopSpeaking()atura la parla.- A 
onDestroytanquem i alliberem recursos. 
5) Strings (opcional)
Pots posar els textos a res/values/strings.xml si vols:
<resources>
    <string name="app_name">tts_cat</string>
    <string name="hello_default">Hola! Aquest és un missatge de prova en català.</string>
    <string name="btn_speak">Parlar</string>
    <string name="btn_stop">Parar</string>
</resources>
I a l’XML utilitzar @string/….
6) Provar l’app
- Executa l’aplicació en un dispositiu físic (recomanat) o un emulador amb suport TTS.
 - Si no s’escolta català, Android normalment et deixarà descarregar paquets de veu a Configuració → Accessibilitat / Entrada i Idioma → Sortida de text a veu (pot variar segons fabricant). També el codi obrirà el flux d’instal·lació de dades TTS.
 - El botó Parlar llegirà el text del 
EditText. El botó Parar aturarà la parla. 
7) Millores opcionals (per si vols ampliar)
- Afegir un spinner per triar idioma (ca, es, en) dins la mateixa Activity.
 - Guardar l’últim text escrit amb 
SharedPreferences. - Afegir controls de velocitat (
setSpeechRate) i to (setPitch) per l’usuari. - Gestionar esdeveniments d’
UtteranceProgressListenerper actualitzar UI quan acaba la parla. 
Exemple ràpid per ajustar velocitat:
tts?.setSpeechRate(1.0f) // 1.0 és normal, 0.5 més lent, 2.0 més ràpid tts?.setPitch(1.0f) // 1.0 normal
Si vols, ara:
- Et faig el codi amb selector d’idiomes dins la mateixa 
MainActivity.kt; o - Et dono un fitxer 
activity_main.xmlamb una mica més d’estil; o - T’explico com instal·lar la veu catalana des del dispositiu pas a pas.
 
Quina d’aquestes prefereixes que fem ara? (si vols, faig directament el selector d’idiomes dins la mateixa Activity)