テキスト読み上げアプリ
Githubでテキスト読み上げアプリの.apkファイルなどをパブリック ドメインで公開しております。
マイクロソフトのBing検索エンジンで「github android-tts」などで検索してみてください。
残念ながらグーグル検索エンジンでは検索できません。
テキストを読み上げるアプリです。
AQUOS sense3、Pixel 7aで動作を確認できました。
AmazonのFireOSのFireHDタブレットでは動作しません。
※下記のXMLファイルやKotlinのプログラムなどのコードをコピペする場合は、2文字の全角空白を4文字の半角空白に置換してください。
また、Android StudioにJavaやKotlinなどのプログラムのコードをコピペして、「import android.R」が自動で追加されてしまったら、削除してください。
「android.R」は、「R.layout.activity_main」や「R.id.◯◯◯」の「R」とは違います。
そのため、「import android.R」が有ると、コンパイル エラーが発生してしまいます。
Android StudioにJavaやKotlinなどのプログラムのコードをコピペすると、変数の名前が半角バッククォート記号(`)で囲まれる事が有ります。
Kotlinでは変数の名前を半角バッククォート記号(`)で囲むと予約語(inやnullなど)や半角空白記号( )などを変数の名前にできるそうです。
可能であれば、半角バッククォート記号(`)で囲まれた変数の名前は、半角バッククォート記号(`)で囲まずに済む名前に変更したほうが良いのでは、と個人的に思っております。
・次のアンドロイドのTTS(テキスト トゥ スピーチ)の設定をAndroidManifest.xmlに追加します。
アンドロイドのTTS(テキスト トゥ スピーチ)の設定
――――――――――――――――――――
<queries>
<intent>
<action android:name="android.intent.action.TTS_SERVICE" />
</intent>
</queries>
――――――――――――――――――――
/home/◯◯◯/AndroidStudioProjects/Tts/app/src/main/AndroidManifest.xml
――――――――――――――――――――
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
>
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.Tts"
tools:targetApi="31"
>
<activity
android:name=".MainActivity"
android:exported="true"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<queries>
<intent>
<action android:name="android.intent.action.TTS_SERVICE" />
</intent>
</queries>
</manifest>
――――――――――――――――――――
◯◯◯はLinux Mintのユーザー名です。
Ttsは著者が付けたAndroid Studioのプロジェクトの名前です。
/home/◯◯◯/AndroidStudioProjects/Tts/app/src/main/res/values/strings.xml
――――――――――――――――――――
<resources>
<string name="app_name">Tts</string>
<string name="speak">Speak</string>
<string name="cancel">Cancel</string>
<string name="text_to_speech_is_busy">TextToSpeech is busy now.</string>
</resources>
――――――――――――――――――――
◯◯◯はLinux Mintのユーザー名です。
Ttsは著者が付けたAndroid Studioのプロジェクトの名前です。
/home/◯◯◯/AndroidStudioProjects/Tts/app/src/main/res/values-ja/strings.xml
――――――――――――――――――――
<resources>
<string name="app_name">Tts</string>
<string name="speak">読み上げ</string>
<string name="cancel">キャンセル</string>
<string name="text_to_speech_is_busy">読み上げ機能が混雑しています。</string>
</resources>
――――――――――――――――――――
◯◯◯はLinux Mintのユーザー名です。
Ttsは著者が付けたAndroid Studioのプロジェクトの名前です。
/home/◯◯◯/AndroidStudioProjects/Tts/app/src/main/res/layout/activity_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="match_parent"
android:layout_height="match_parent"
>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<Button
android:id="@+id/speak"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/speak"
android:layout_gravity="center"
/>
<Button
android:id="@+id/cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cancel"
android:layout_gravity="center"
/>
<EditText
android:id="@+id/editText"
android:inputType="textMultiLine"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<requestFocus/>
</EditText>
</LinearLayout>
</ScrollView>
</LinearLayout>
――――――――――――――――――――
◯◯◯はLinux Mintのユーザー名です。
Ttsは著者が付けたAndroid Studioのプロジェクトの名前です。
/home/◯◯◯/AndroidStudioProjects/Tts/app/src/main/java/eliphas1810/tts/MainActivity.kt
――――――――――――――――――――
package eliphas1810.tts
import android.os.Bundle
import android.speech.tts.TextToSpeech
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AppCompatActivity
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.TimeUnit
class MainActivity : AppCompatActivity(), TextToSpeech.OnInitListener {
var textToSpeech: TextToSpeech? = null
var editText: EditText? = null
var speakButton: Button? = null
var cancelButton: Button? = null
var isStopping: Boolean = false
var isStarting: Boolean = false
var isCompleted: Boolean = true
var lineList: List<String> = mutableListOf<String>()
var lineIndex = 0
var maxLineIndex = 0
var scheduledExecutorService: ScheduledExecutorService? = null
//メモリー上に作成される時にのみ呼ばれます。
override fun onCreate(savedInstanceState: Bundle?) {
try {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//戻るボタン、戻るジェスチャーを無効化
onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {}
})
textToSpeech = TextToSpeech(this, this)
editText = findViewById(R.id.editText)
speakButton = findViewById(R.id.speak)
cancelButton = findViewById(R.id.cancel)
speakButton?.isClickable = true
cancelButton?.isClickable = false
speakButton?.setOnClickListener { view ->
try {
if(textToSpeech?.isSpeaking ?: true) {
Toast.makeText(applicationContext, getString(R.string.text_to_speech_is_busy), Toast.LENGTH_LONG).show()
return@setOnClickListener
}
if (isStarting) {
return@setOnClickListener
}
speakButton?.isClickable = false
cancelButton?.isClickable = true
isStarting = true
isStopping = false
var text = editText?.text.toString() ?: ""
if (text.length == 0) {
isStarting = false
isStopping = false
speakButton?.isClickable = true
cancelButton?.isClickable = false
return@setOnClickListener
}
text = text.replace("\r\n", "\n")
text = text.replace("\r", "\n")
lineList = text.split("\n")
lineIndex = 0
maxLineIndex = lineList.size - 1
scheduledExecutorService = Executors.newSingleThreadScheduledExecutor()
scheduledExecutorService?.scheduleAtFixedRate(
{
try {
if (isCompleted) {
if (maxLineIndex < lineIndex || isStopping) {
isStarting = false
isStopping = false
speakButton?.isClickable = true
cancelButton?.isClickable = false
lineIndex = 0
scheduledExecutorService?.shutdown()
return@scheduleAtFixedRate
}
var line = lineList[lineIndex]
isCompleted = false
if (1 <= line.length) {
textToSpeech?.speak(line, TextToSpeech.QUEUE_FLUSH, null, "line" + (lineIndex + 1))
}
lineIndex += 1
isCompleted = true
}
} catch (exception: Exception) {
Toast.makeText(applicationContext, exception.toString(), Toast.LENGTH_LONG).show()
throw exception
}
},
1, //1回目までの時間間隔の時間数
1, //1回目以降の時間間隔の時間数
TimeUnit.SECONDS //時間の単位。秒。
)
} catch (exception: Exception) {
Toast.makeText(applicationContext, exception.toString(), Toast.LENGTH_LONG).show()
throw exception
}
}
cancelButton?.setOnClickListener { view ->
try {
if (isStarting == false) {
return@setOnClickListener
}
speakButton?.isClickable = false
cancelButton?.isClickable = false
isStopping = true
} catch (exception: Exception) {
Toast.makeText(applicationContext, exception.toString(), Toast.LENGTH_LONG).show()
throw exception
}
}
} catch (exception: Exception) {
Toast.makeText(applicationContext, exception.toString(), Toast.LENGTH_LONG).show()
throw exception
}
}
override fun onInit(status: Int) {
if (status == TextToSpeech.SUCCESS) {
//textToSpeech?.setSpeechRate(1.0f) //読み上げ速度
}
}
//メモリーから破棄される時にのみ呼ばれます。
override fun onDestroy() {
try {
textToSpeech?.shutdown()
textToSpeech = null
scheduledExecutorService?.shutdownNow()
scheduledExecutorService = null
} catch (exception: Exception) {
Toast.makeText(applicationContext, exception.toString(), Toast.LENGTH_LONG).show()
throw exception
} finally {
super.onDestroy()
}
}
}
――――――――――――――――――――
◯◯◯はLinux Mintのユーザー名です。
Ttsは著者が付けたAndroid Studioのプロジェクトの名前です。
eliphas1810/ttsは著者が付けたJavaやKotlinのプログラムのパッケージのディレクトリの相対パスです。
eliphas1810.ttsは著者が付けたJavaやKotlinのプログラムのパッケージの名前です。
アンドロイド スマホのアプリを作ろう! エリファス1810 @Eliphas1810
★で称える
この小説が面白かったら★をつけてください。おすすめレビューも書けます。
カクヨムを、もっと楽しもう
カクヨムにユーザー登録すると、この小説を他の読者へ★やレビューでおすすめできます。気になる小説や作者の更新チェックに便利なフォロー機能もお試しください。
新規ユーザー登録(無料)簡単に登録できます
この小説のタグ
同じコレクションの次の小説
ビューワー設定
文字サイズ
背景色
フォント
組み方向
機能をオンにすると、画面の下部をタップする度に自動的にスクロールして読み進められます。
応援すると応援コメントも書けます