在棉花糖(Android 6)上的TTS中使用声音文件失败,出现权限问题 [英] Use of sound files in TTS on Marshmallow (Android 6) fails with permission issues

查看:196
本文介绍了在棉花糖(Android 6)上的TTS中使用声音文件失败,出现权限问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用android TTS中的addSpeech(),您可以将某些文本链接到声音文件.然后,TTS引擎播放文件而不是合成文本的声音(也在

Using addSpeech() in android TTS, you can link a certain text to a sound file. Then, the TTS engine plays the file instead of synthesizing the sound of the text (also in question at 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 ). This is not working in Android 6.0 with TTS version 3.9.14 (and 3.10.10). So far, I did not see ant post with an answer as to why this is not working in Android 6.0. So I thought I'll provide more data on the issue that could help someone figure out the issue. (I had added this to the question in the link above, but moderators deleted it saying this is not an answer. They did not suggest a way to add more data like this except saying ask another question. Hence this question. In reality this is additional data on the same question that is not answered yet). so here goes.

在清单中,我已经使用TTS(依次使用Media Player)为应用程序提供了读取和写入权限,以播放提供的语音文件.

In the manifest I have provided both read and write permissions to the app using TTS (which in turn uses Media Player) to play the voice files provided.

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中的错误似乎会稍有不同.

Note that this works fine up to Android 5.0, but fails on android 6.0 (except when files in res/raw are used as voice files). Also when it fails it seems to give slightly different error in logcat depending on whether the voice file is on internal or external storage.

  1. 当语音文件位于res/raw文件夹中时,TTS可以使用资源ID(addSpeech(word,pkgName,resId))正确播放所需的语音文件

  1. When the voice file in res/raw folder, TTS works fine playing the required voice file using the resource id (addSpeech (word, pkgName, resId))

当语音文件位于外部存储(/storage/sdcard0/pkgName/soundFiles/..使用TTS播放时,会给出EACCES故障日志(对于amr和mp3文件).

When the voice file is located on external storage (/storage/sdcard0/pkgName/soundFiles/.. playing using TTS gives the EACCES failure log (for both amr and mp3 files).

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实例存在文件权限问题.

    As an experiment, created a MediaPlayer object in the same class where TTS is being used and played the same sound files that are failing with TTS. They played fine without any issue. So it looks like only the instantiation of MediaPlayer within TTS is having file permission issues.

    感谢您的帮助.

    请注意,已授予运行时权限,所以这不是问题.该问题仅限于Google文本到语音引擎.其他引擎正常工作.

    Please note, runtime permissions have been granted, so this is not the issue. The problem is limited to the Google Text to Speech engine. Other engines work correctly.

    推荐答案

    我是发布您下面提到的链接的人. Android TTS(文字转语音))的addSpeech()和talk()无法使用Google TTS在上述棉花糖(api 23)中的外部存储中播放声音文件

    I'm the guy who posted the link below you mentioned. 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中的媒体播放器无法读取内部/外部存储中的音频文件.

    Thank you for all the experiments. I agree with you that the mediaplayer in TTS can't read the audio files in the internal/external storage.

    那时,我使用MODE_WORLD_READABLE将目标设备设置为22或类似的值,以避免出现此问题.现在不可能将目标设置得太低,我想到的最好的选择是自己创建一个功能为"addSpeech()"的函数.使用MediaPlayer播放音频文件而不是播放特定文本并不难.但是,棘手的部分是有关在需要时如何处理'utteranceId'的问题.

    At that time, I set my target device at 22 or something to avoid the issue using MODE_WORLD_READABLE. Now that it's impossible to set the target so low, the best option I can think of is to make a function that works as 'addSpeech()' yourself. It's not that hard to play an audio file instead of a certain text with MediaPlayer. The tricky part, however, is about how to deal with 'utteranceId' in your workaround if you need it.

    其中一个选项是将"playSilentUtterance(final long durationInMs,final int queueMode,final String utteranceId)"放置在MediaPlayer的onCompleteListener中,以便它可以触发所需的utteranceId.您可以在durationInMs中放置一个非常短的时间,例如100millisec.

    One of the options is you place 'playSilentUtterance(final long durationInMs, final int queueMode, final String utteranceId)' in your MediaPlayer onCompleteListener so that it can trigger the utteranceId you want. You can put a very short time like 100millisec in durationInMs.

    我希望这对遇到问题的所有人有所帮助,并希望Google能解决此问题.

    I hope this helps anyone who is stuck with the issue, and hopefully Google resolves this issue.

    这篇关于在棉花糖(Android 6)上的TTS中使用声音文件失败,出现权限问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆