一个非常简洁的问题:我如何用简单的测试证明,该设置:
android.os.Process.setThreadPriority(int);
Run Code Online (Sandbox Code Playgroud)
实际上有效?
我发布这个问题的原因主要是通用的,因为我找不到一个可以复制的简单测试.
进一步阅读:
这对我和我的应用程序来说非常重要,因为它捕获音频,这必须是优先考虑的事情.音频数据也被写入文件以及分析其属性,这不太重要 - 因此我不要求这些任务"真正同时".
在我的音频线程中,我设置:
Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO);
Run Code Online (Sandbox Code Playgroud)
我可以通过检查之前和之后简单地测试上面的'应用':
Process.getThreadPriority(Process.myTid());
Run Code Online (Sandbox Code Playgroud)
但是,我对测试的需求是由于文档,其中指出:
最重要的音频线程的标准优先级.应用程序通常无法更改为此优先级.
尽管日志输出显示优先级已更改为-19,但我在文档中的措辞引起的担忧是,系统在执行时可能不允许正常应用程序的值为-19,并且可能保留为仅限系统应用?
如果上述情况属实,我想知道如何简单地证明这个优先级值会发生什么 - 它是否默认为允许的最大值,还是可以完全忽略?
关于实际测试本身,我已经尝试了循环和暂停,但没有成功,我不相信我所做的尝试的结果.我也知道这种行为是依赖于操作系统的,所以也许我无法复制一个独立的Java测试,但我没有找到任何支持的例子?
希望有人能提供帮助.提前致谢.
编辑 - 除了最初的答案,我很欣赏这种行为可能不是我想要或期望的.我想要对此进行实际的物理测试,而不是对可能性的解释.
测试将由多个线程组成,这些线程以不同的优先级运行,并且它们完成的顺序打印到日志中,没有比这更复杂的了.我的尝试似乎过于复杂,因此我在这里寻求帮助.
我有一个情况我觉得我要推倒重来还是走房前屋后,处理事情,已经有一个"设计"了 - 所以我做之前,我希望我能得到第二个意见,请.
我有一个远程服务.由于应用程序本身的不寻常特性/功能,它是永久性的前台服务.
我正在编写一个库,以便第三方应用程序可以绑定到服务并使用我公开的API.正如我在处理线程我和大部分的回调将是一个异步的性质,我使用的是AIDL方式,与被"瓜分了"提供必要的参数,以服务自定义类.到目前为止,一切都很完美.
我的服务代码的构造与RemoteService API示例非常相似,所以我将参考,因为发布我的特定代码不会改变问题.
作为与示例中,每个请求的接口I保存到RemoteCallbackList,这似乎是一个方便的解决方案的一些其它基础.
但是,我的服务不会向使用以下代码段的"等待接收者"提供相同的信息:
int i = callbacks.beginBroadcast();
while (i > 0) {
i--;
try {
callbacks.getBroadcastItem(i).somethingHappened();
} catch (RemoteException e) {
// The RemoteCallbackList will take care of removing
// the dead object for us.
}
}
callbacks.finishBroadcast();
Run Code Online (Sandbox Code Playgroud)
相反,请求有许多不同的类型,因此我需要跟踪我要将结果发送回的确切接口对象.每个单独的请求可能涉及进一步的异步Web请求和/或处理,并且不得不将回调对象交给其中的每一个(通过构造函数或只是方法参数),我觉得我将要做一些非常乏味的事情.啰嗦地解决了一个问题,我或许可以简单地实现另一种方式?
如果我可以保证第一个请求将是第一个结果,并且因此在删除对它们的引用之前简单地使用RemoteCallbackList中的顺序,那么任务将变得容易,但由于处理时间的变化,情况并非如此.不同的请求类型.
编辑 - 看起来RemoteCallbackList由ArrayMap支持,所以我认为还没有订购?
我没有找到任何记录的方法来缩小RemoteCallbackList中的回调所在的位置,尽管即使我可以,我当然还需要某种持久性标识符才能知道我在寻找什么....难倒.
感谢您阅读本文,欢迎任何想法.
编辑 - 出于伪示例的目的.想象一下,API请求是关于书籍的.
// requests
bookExists(String title)
bookContent(String title)
// response
bookExists(boolean exists)
bookContent(ArrayList<String> words, int pageTotal)
Run Code Online (Sandbox Code Playgroud)
正如您从上面所看到的,在所有条件相同的情况下,对较小书籍的远程请求或书籍的存在,可能会在请求更长的书籍之前完成并准备好回复,即使之后请求了.这是我需要跟踪'请求者'的地方,也是我追求的设计.
多年来(从字面上看),我的应用程序遭遇了性能不佳的文本到语音引擎的困境,特别是调用时的初始化时间:
tts = new TextToSpeech(context, myOnInitListener);
Run Code Online (Sandbox Code Playgroud)
以上可能导致UI滞后,如果您在SO上搜索"文本到语音初始化缓慢",您会发现很多帖子.嵌入式高品质IVONA声音曾经是最糟糕的罪魁祸首,但Google TTS引擎现已获此殊荣.
他们最近的APK更新导致初始化时出现严重滞后 - 无需测试此代码,您可以转到Android文本到语音设置并尝试在可用引擎之间切换,同时按"收听样本",显示延迟很好".
为了尝试解决这个问题,我实施了以下内容:
private volatile TextToSpeech tts;
AsyncTask.execute(new Runnable() {
@Override
public void run() {
tts = new TextToSpeech(context, volatileOnInitListener);
}
});
Run Code Online (Sandbox Code Playgroud)
这完全解决了初始化的滞后问题,但我担心这可能会产生副作用,我没有考虑过?任何人都可以想到吗?
我也很困惑,因为我相信TextToSpeech构造函数是异步的,因此将此构造函数移动到工作线程应该没有区别?如果这种实现是前进的方向,那么Google为什么不在TextToSpeechSettings中实现它呢?
希望有人能澄清以上内容.提前致谢.
编辑 - 当我说"构造函数是异步的"时,我真的指的是它启动的引擎初始化过程,以及最终调用onInit
我为Android创建了一个支持多种语言的文本到语音引擎,其中一种语言是印地语.
在Android文本到语音设置中,当用户选择默认语言环境时,Android会执行多项检查,包括发送意图ACTION_GET_SAMPLE_TEXT
这是我支持的语言环境列表:
private static final String[] SUPPORTED_LANGUAGES = { "eng-GBR", "eng-USA", "fra-FRA", "spa-ESP", "deu-DEU", "ita-ITA",
"kor-KOR", "nld-NLD", "dan-DNK", "fin-FIN", "jpn-JPN", "nor-NOR", "pol-POL", "por-PRT", "por-BRA", "rus-RUS",
"swe-SWE", "zho-CHN", "zho-HKG", "zho-TWN", "ara-SAU", "hi-IN", "ces-CZE", "ell-GRC", "hun-HUN", "ron-ROU",
"slk-SVK", "tha-THA", "tur-TUR", "cym-GBR", "isl-ISL", "in-IDN" };
Run Code Online (Sandbox Code Playgroud)
对于"hi-IN"以外的每个区域设置,Android都会发送此意图,我会回复示例文本并显示"收听示例"按钮.
我已成功从调用onIsLanguageAvailable返回LANG_COUNTRY_AVAILABLE,但按钮仍然显示为灰色,并指出该语言不受支持.
我尝试了很多不同的语言环境ISO组合:
hin-IN,hi-IND,ind-HI等等,但Android不发送Intent,尽管它在Locale列表中被正确标记为印地语(印度语)或印地语.
logcat中没有错误表明失败的变体匹配.
我发布我的代码没什么意义,因为Android根本没有发送此Locale的Intent,所以它无法访问我的代码....
任何想法如何正确处理此区域设置变体?
编辑:我刚刚意识到它也发生在印尼语(in-IDN)
赏金奖励 - 奖金将奖励给从填充Telephony.Sms.Inbox.PERSON值到相关Contact仅使用ContractsContact表格的答案.
我正在申请中以标准方式阅读短信:
final String[] projection = {Telephony.Sms.Inbox.BODY,
Telephony.Sms.Inbox.ADDRESS,
Telephony.Sms.Inbox.READ,
Telephony.Sms.Inbox.DATE,
Telephony.Sms.Inbox.PERSON};
final Cursor cursor = ctx.getContentResolver().query(Telephony.Sms.Inbox.CONTENT_URI,
projection, null, null, Telephony.Sms.Inbox.DEFAULT_SORT_ORDER);
Run Code Online (Sandbox Code Playgroud)
填充时,从索引返回Telephony.Sms.Inbox.PERSON的id与弃用的id相关,Contacts.People._ID可用于通过以下方式查询更多联系人信息:
final String[] projection = {Contacts.People.DISPLAY_NAME};
final String[] selectionArgs = {contactId};
final Cursor cursor = ctx.getContentResolver().query(Contacts.People.CONTENT_URI,
projection, Contacts.People._ID + " = ?", selectionArgs, null);
Run Code Online (Sandbox Code Playgroud)
为什么相对较新的Telephony API使用弃用表而不是ContactsContract?
Telephony.Sms.Inbox.PERSON文档说明:
类型:INTEGER(对内容中的项目的引用://联系人/人)
我试过(但并不奇怪吗?)在任何ContactsContractid字段中找到id的映射都没有成功,所以我不得不使用弃用的API来解决我需要快速执行的查询.
这样的查询包括搜索特定联系人的消息,我只有这个名字.联系人可能有多个号码,这些号码的格式可能不正确,无法匹配Telephony.Sms.Inbox.ADDRESS条目......
从数字到联系人时,使用和ContactsContract.PhoneLookup的解决方法不是世界末日,但我仍然觉得我必须在这里遗漏一些东西 …
概观
我将字符串发送到文本到语音服务器,该服务器最多可接受300个字符.由于网络延迟,返回的每个语音段之间可能会有延迟,因此我希望尽可能在最"自然暂停"时打破语音.
每个服务器的请求花了我的钱,所以最好我会送的最长的字符串可能,直到达到最大允许的字符.
这是我目前的实施:
private static final boolean DEBUG = true;
private static final int MAX_UTTERANCE_LENGTH = 298;
private static final int MIN_UTTERANCE_LENGTH = 200;
private static final String FULL_STOP_SPACE = ". ";
private static final String QUESTION_MARK_SPACE = "? ";
private static final String EXCLAMATION_MARK_SPACE = "! ";
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
private static final String COMMA_SPACE = ", ";
private static final String JUST_A_SPACE = " ";
public static ArrayList<String> splitUtteranceNaturalBreaks(String utterance) {
final long …Run Code Online (Sandbox Code Playgroud) 在android TTS中使用addSpeech(),您可以将某个文本链接到声音文件.然后,TTS引擎播放文件而不是合成文本的声音(在Android TTS(文本到语音)的addSpeech()中也有问题)并且speak()无法在棉花糖的外部存储器中播放声音文件(api 23)上面,谷歌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" />
Run Code Online (Sandbox Code Playgroud)
请注意,这适用于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 …Run Code Online (Sandbox Code Playgroud)android text-to-speech media-player google-text-to-speech android-6.0-marshmallow
我有兴趣编写一个能够识别多个发言者的语音识别应用程序.例如,如果比尔,乔和简正在谈论,那么应用程序不仅可以将声音识别为文本,还可以通过发言者对结果进行分类(比如0,1和2 ......因为显然/希望谷歌没有办法将声音链接到人).
我正在寻找可能会这样做的语音识别API,而Google Cloud Speech则是排名第一的API.我查看了API文档,看看这些功能是否可用,还没有找到.
我的问题是:这个功能是否存在?
注意:Google的支持页面说他们的工程师有时会在SO上回答这些问题,所以似乎有人可能会回答问题的"遗嘱"部分.
我已经设法通过GRPC使用流媒体模式的服务帐户为我的Android应用程序运行Google Cloud Speech.但是,根据我所读到的内容,出于安全原因,我不应该在其中部署具有这些凭据的Android应用程序(当前存储为资源中的JSON文件).正确的做法是创建API密钥,如下所述:https://cloud.google.com/speech/docs/common/auth
这允许我限制对我的特定Android应用的访问.但是,我一直无法找到如何使用GRPC的API密钥.我正在GoogleCredentials从JSON文件创建一个实例,这很好.如何从API密钥获取凭证对象?
当用户将网络合成语音设置为默认值时,我的应用程序会缓存常见的请求以防止未来的网络延迟。
我如何做到这一点,是体现在我的代码在这里。简而言之,它将引擎名称和话语与请求匹配,如果它们匹配,我会流式传输缓存的音频而不是使用 TTS 引擎。
如果用户随后在 Android 文本到语音设置中更改了他们的音调和语速,则缓存的音频当然将不再反映这一点,并且需要被忽略并“重新缓存”,或者相应地处理音频。
我的问题:如何获得系统默认设置,用于音调和语速。
要设置音调和速率,TextToSpeech API中提供了公开的方法:
/**
* Sets the speech rate.
*
* This has no effect on any pre-recorded speech.
*
* @param speechRate Speech rate. {@code 1.0} is the normal speech rate,
* lower values slow down the speech ({@code 0.5} is half the normal speech rate),
* greater values accelerate it ({@code 2.0} is twice the normal speech rate).
*
* @return {@link #ERROR} or {@link …Run Code Online (Sandbox Code Playgroud)