因此,在我的助手应用程序中,当用户说了特定的单词时,我会检测到,然后我会在后台启动应用程序。我在前台服务中使用了一个名为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>
重点是我在应用程序处于前台时启动前台服务,所以我相信它不包含在new limits introduced in Android 11 and above中。但我的进程仍然无法重新控制麦克风,直到应用程序重新启动(再次出现在前台)。我该如何解决这个问题?
发布于 2021-08-31 11:49:40
经过进一步的研究,我找到了解决方案。在Android11和更高版本中,我必须在AndroidManifest.xml
的前台服务声明中添加android:foregroundServiceType="microphone"
<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或任何其他应用程序录制音频时,我的服务停止工作,当我使用完麦克风时,我的服务将恢复成功的检测过程。
https://stackoverflow.com/questions/68989856
复制相似问题