在android TTS中使用addSpeech(),您可以将某个文本链接到声音文件。然后,TTS引擎播放文件而不是合成文本的声音(也在Android TTS(Text to Speech)'s addSpeech() and speak() can't play a sound file in the external storage from marshmallow(api 23) above, with Google TTS处有问题)。这在使用TTS版本3.9.14(和3.10.10)的Android 6.0中不起作用。 到目前为止,我没有看到ant post的答案,为什么这在Android 6.0中不起作用。所以我想我会提供更多有关这个问题的数据,可以帮助有人找出问题所在。 (我已将此添加到上面链接中的问题,但主持人删除了它说这不是答案。他们没有建议添加更多这样的数据,除了说另一个问题。因此这个问题。实际上这是关于尚未回答的同一问题的其他数据)。所以这里。
在清单中,我使用TTS(后者又使用Media Player)为应用程序提供了读取和写入权限,以播放所提供的语音文件。
android:targetSdkVersion="22"
...
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
请注意,这适用于Android 5.0,但在Android 6.0上失败(除非将res / raw中的文件用作语音文件)。此外,当它失败时,似乎在logcat中给出略有不同的错误,具体取决于语音文件是在内部存储还是外部存储。
当res / raw文件夹中的语音文件时,TTS使用资源ID(addSpeech(word,pkgName,resId))正常播放所需的语音文件
当语音文件位于外部存储器上时(/ storage / sdcard0 / pkgName / soundFiles / ..使用TTS播放会给出EACCES失败日志(对于amr和mp3文件)。
09-08 16:57:17.514 1549-7830/? D/MediaPlayer: create failed:
java.io.FileNotFoundException: /storage/emulated/0/pkgName/soundFiles/voice1.amr: open failed: EACCES (Permission denied)
at libcore.io.IoBridge.open(IoBridge.java:487)
at java.io.FileInputStream.(FileInputStream.java:76)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1115)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1066)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1003)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:983)
at android.media.MediaPlayer.create(MediaPlayer.java:890
at android.speech.tts.AudioPlaybackQueueItem.run(AudioPlaybackQueueItem.java:58)
at android.speech.tts.AudioPlaybackHandler$MessageLoop.run(AudioPlaybackHandler.java:134)
at java.lang.Thread.run(Thread.java:818)
Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
at libcore.io.Posix.open(Native Method)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
at libcore.io.IoBridge.open(IoBridge.java:473)
at java.io.FileInputStream.(FileInputStream.java:76)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1115)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1066)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1003)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:983)
at android.media.MediaPlayer.create(MediaPlayer.java:890)
at android.speech.tts.AudioPlaybackQueueItem.run(AudioPlaybackQueueItem.java:58)
at android.speech.tts.AudioPlaybackHandler$MessageLoop.run(AudioPlaybackHandler.java:134)
at java.lang.Thread.run(Thread.java:818
当语音文件位于内部存储器上时(/ data /.../pkgName/soundFiles/ ..使用TTS播放单词会出现以下错误日志(对于amr和mp3文件)。
09-08 17:24:23.103 1549-32732/? D/MediaPlayer: create failed:
java.io.IOException: setDataSource failed.
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1120)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1066)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1003)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:983)
at android.media.MediaPlayer.create(MediaPlayer.java:890)
at android.speech.tts.AudioPlaybackQueueItem.run(AudioPlaybackQueueItem.java:58)
at android.speech.tts.AudioPlaybackHandler$MessageLoop.run(AudioPlaybackHandler.java:134)
at java.lang.Thread.run(Thread.java:818)
作为一项实验,在使用TTS的同一个类中创建了一个MediaPlayer对象,并播放了与TTS失败的相同声音文件。没有任何问题他们打得很好。所以看起来只有TTS中MediaPlayer的实例化才有文件权限问题。
感谢任何帮助。
编辑:请注意,已授予运行时权限,因此这不是问题。问题仅限于Google Text to Speech引擎。其他引擎工作正常。
答案 0 :(得分:0)
感谢您的所有实验。我同意您的意见,即TTS中的媒体播放器无法读取内部/外部存储中的音频文件。
那时,我使用MODE_WORLD_READABLE将目标设备设置为22或类似的值以避免出现此问题。 既然不可能将目标设置得如此之低,那么我能想到的最好的选择就是自己创建一个功能为“ addSpeech()”的函数。 使用MediaPlayer播放音频文件而不是播放特定文本并不难。但是,棘手的部分是有关在需要时如何处理'utteranceId'的问题。
其中一个选项是将“ playSilentUtterance(final long durationInMs,final int queueMode,final String utteranceId)”放置在MediaPlayer的onCompleteListener中,以便它可以触发所需的utteranceId。您可以在durationInMs中放置一个非常短的时间,例如100millisec。
我希望这对遇到问题的所有人有所帮助,并希望Google解决该问题。
答案 1 :(得分:-1)
我认为它失败是因为你必须在棒棒糖5.1操作系统上面的Android手机中添加运行时权限(就像你需要在用户使用该功能时询问权限),
https://developer.android.com/training/permissions/requesting.html
检查此链接以便最好地了解此问题。 如果需要知道如何完成,只需查看下面的代码即可。
https://www.androidhive.info/2016/11/android-working-marshmallow-m-runtime-permissions/
这是代码:
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
// MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}