首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >应用后台热词检测无法重启,安卓?

应用后台热词检测无法重启,安卓?
EN

Stack Overflow用户
提问于 2021-08-30 20:16:37
回答 1查看 66关注 0票数 0

因此,在我的助手应用程序中,当用户说了特定的单词时,我会检测到,然后我会在后台启动应用程序。我在前台服务中使用了一个名为PocketSphinx的库来检测热词,它工作得相当好。下面是我要启动的前台服务:

代码语言:javascript
复制
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和更高版本中是如此,除非用户再次启动我的应用程序。以下是我的前台服务尝试恢复热词检测但失败时的错误日志:

代码语言:javascript
复制
>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中。但我的进程仍然无法重新控制麦克风,直到应用程序重新启动(再次出现在前台)。我该如何解决这个问题?

EN

回答 1

Stack Overflow用户

发布于 2021-08-31 11:49:40

经过进一步的研究,我找到了解决方案。在Android11和更高版本中,我必须在AndroidManifest.xml的前台服务声明中添加android:foregroundServiceType="microphone"

代码语言:javascript
复制
<service android:name=".HotKeyWordDetectionService" android:foregroundServiceType="microphone"/>

也感谢我在onStartCommand()中的服务

代码语言:javascript
复制
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
    startForeground(1, createNotification(), ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE);
else
    startForeground(1, createNotification());

现在,当我使用WhatsApp或任何其他应用程序录制音频时,我的服务停止工作,当我使用完麦克风时,我的服务将恢复成功的检测过程。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68989856

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档