android - 应用程序在后台时,热词检测无法重新启动,Android?
问题描述
因此,在我的助手应用程序中,我检测到用户何时说出特定单词,然后在后台启动我的应用程序。我在前台服务中使用了一个名为PocketSphinx的库来检测热词,它工作得相当好。这是我正在启动的前台服务:
public class HotKeyWordDetectionService extends Service
implements RecognitionListener {
private static final String KWS_SEARCH = "wakeup";
/* Keyword we are looking for to activate menu */
private static final String KEYPHRASE = "hello buddy";
private SpeechRecognizer recognizer;
private ExecutorService service;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
startForeground(1, createNotification());
service = Executors.newFixedThreadPool(3);
// Recognizer initialization is a time-consuming and it involves IO,
// so we execute it in a separate thread.
init();
return START_NOT_STICKY;
}
public void init() {
service.submit(() -> {
try {
Assets assets = new Assets(HotKeyWordDetectionService5.this);
File assetDir = assets.syncAssets();
setupRecognizer(assetDir);
Log.i("sphinx_test", "setup success: ");
handler.sendEmptyMessage(0);
} catch (IOException e) {
Log.i("sphinx_test", "setup failed: "+"Failed to init recognizer " + e.getMessage());
e.printStackTrace();
}
});
}
private Handler handler = new Handler(message -> {
switchSearch(KWS_SEARCH);
return false;
});
@Override
public void onResult(Hypothesis hypothesis) {
if (hypothesis != null) {
String text = hypothesis.getHypstr();
if (text.equals(KEYPHRASE))
launchMyApp();
}
}
private void switchSearch(String searchName) {
recognizer.stop();
recognizer.startListening(KWS_SEARCH);
}
private void setupRecognizer(File assetsDir) throws IOException {
// The recognizer can be configured to perform multiple searches
// of different kind and switch between them
recognizer = SpeechRecognizerSetup.defaultSetup()
.setAcousticModel(new File(assetsDir, "en-us-ptm"))
.setDictionary(new File(assetsDir, "cmudict-en-us.dict"))
.setRawLogDir(assetsDir)
.getRecognizer();
recognizer.addListener(this);
// Create keyword-activation search.
recognizer.addKeyphraseSearch(KWS_SEARCH, KEYPHRASE);
// Create grammar-based search for selection between demos
File menuGrammar = new File(assetsDir, "menu.gram");
recognizer.addGrammarSearch(MENU_SEARCH, menuGrammar);
// Create grammar-based search for digit recognition
File digitsGrammar = new File(assetsDir, "digits.gram");
recognizer.addGrammarSearch(DIGITS_SEARCH, digitsGrammar);
// Create language model search
File languageModel = new File(assetsDir, "weather.dmp");
recognizer.addNgramSearch(FORECAST_SEARCH, languageModel);
// Phonetic search
File phoneticModel = new File(assetsDir, "en-phone.dmp");
recognizer.addAllphoneSearch(PHONE_SEARCH, phoneticModel);
}
}
当用户使用另一个应用程序(如 WhatsApp)录制音频时,问题就出现了。这会导致我的应用失去对麦克风的控制。用户在其他应用程序中使用完麦克风后,我的应用程序将无法重新控制麦克风,至少在 Android 11 及更高版本中,除非用户再次启动我的应用程序。这是我的前台服务尝试恢复热词检测但失败时的错误日志:
>com.parts.assitant E/IAudioFlinger: createRecord returned error -1
>com.parts.assitant E/AudioRecord: createRecord_l(5263): AudioFlinger could not create record track, status: -1
>com.parts.assitant W/AudioRecord: restoreRecord_l(5263): failed status -1, retries 2
>com.parts.assitant I/BpBinder: onLastStrongRef automatically unlinking death recipients: <uncached descriptor>
重点是我在应用程序处于前台时启动前台服务,所以我相信它不包含在 Android 11 及更高版本中引入的新限制中。但是在重新启动应用程序(再次在前台)之前,我的进程仍然无法重新控制麦克风。我该如何解决这个问题?
解决方案
经过更多研究,我找到了解决方案。在 Android 11 及更高版本中,我必须在android:foregroundServiceType="microphone"
我的前台服务声明中添加AndroidManifest.xml
:
<service android:name=".HotKeyWordDetectionService" android:foregroundServiceType="microphone"/>
还有我的服务onStartCommand()
:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
startForeground(1, createNotification(), ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE);
else
startForeground(1, createNotification());
现在,当我使用 WhatsApp 或任何其他应用程序录制音频时,我的服务会停止工作,当我使用完麦克风后,我的服务会恢复成功的检测过程。
推荐阅读
- c# - 将新模型动态添加到查看器中
- python - 在硒中选择谷歌单框标签时遇到问题
- javascript - 推送数组Javascript时数组包含同一数组的多个实例
- python - 如何比较python中的两个日期列
- reactjs - 如何正确更新全局状态?
- nginx - 内容安全策略阻止 nginx 下 Blazor Wasm 项目中的“评估”
- oauth-2.0 - 使用社交登录(例如 Google 和 Facebook 登录)保护 micronaut rest api
- postman - Postman 模拟服务器与 JSON 模拟服务器
- azure - 了解 Azure 应用服务计划的出站数据传输
- json - 如何在 Anypoint Studio 中使用连接器停止 Mulesoft 流