10

I am creating the voice recognition service like "Ok Google" with custom command. For this I have used the VoiceInteractionService and I refered the code from here. Also, I am getting the STATE_HARDWARE_UNAVAILABLE error in onAvailabilityChanged.

public class VoiceCommandService extends VoiceInteractionService {
private static final String TAG = "AlwaysOnHotwordDetector";
Locale locale = new Locale("en-US");
protected SpeechRecognizer mSpeechRecognizer;
protected Intent mSpeechRecognizerIntent;

public final Callback mHotwordCallback = new Callback() {
    @Override
    public void onAvailabilityChanged(int status) {
        Log.i(TAG, "onAvailabilityChanged(" + status + ")");
        hotwordAvailabilityChangeHelper(status);
    }

    @Override
    public void onDetected(EventPayload eventPayload) {
        Log.i(TAG, "onDetected");
    }

    @Override
    public void onError() {
        Log.i(TAG, "onError");
    }

    @Override
    public void onRecognitionPaused() {
        Log.i(TAG, "onRecognitionPaused");
    }

    @Override
    public void onRecognitionResumed() {
        Log.i(TAG, "onRecognitionResumed");
    }
};

private AlwaysOnHotwordDetector mHotwordDetector;

@Override
public void onCreate(){
    Log.d(TAG, "Entered on create");
    super.onCreate();
}

@Override
public void onReady() {
    super.onReady();
    Log.i(TAG, "Creating " + this);
    mHotwordDetector = createAlwaysOnHotwordDetector(
            "Hello", Locale.forLanguageTag("en-US"), mHotwordCallback);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Bundle args = new Bundle();
    args.putParcelable("intent", new Intent(this, MainActivity.class));
    showSession(args, 0);
    stopSelf(startId);
    return START_NOT_STICKY;
}

private void hotwordAvailabilityChangeHelper(int availability) {
    Log.i(TAG, "Hotword availability = " + availability);
    switch (availability) {
        case AlwaysOnHotwordDetector.STATE_HARDWARE_UNAVAILABLE:
            Log.i(TAG, "STATE_HARDWARE_UNAVAILABLE");
            break;
        case AlwaysOnHotwordDetector.STATE_KEYPHRASE_UNSUPPORTED:
            Log.i(TAG, "STATE_KEYPHRASE_UNSUPPORTED");
            break;
        case AlwaysOnHotwordDetector.STATE_KEYPHRASE_UNENROLLED:
            Log.i(TAG, "STATE_KEYPHRASE_UNENROLLED");
            Intent enroll = mHotwordDetector.createEnrollIntent();
            Log.i(TAG, "Need to enroll with " + enroll);
            break;
        case AlwaysOnHotwordDetector.STATE_KEYPHRASE_ENROLLED:
            Log.i(TAG, "STATE_KEYPHRASE_ENROLLED - starting recognition");
            if (mHotwordDetector.startRecognition(0)) {
                Log.i(TAG, "startRecognition succeeded");
            } else {
                Log.i(TAG, "startRecognition failed");
            }
            break;
    }
}}
Nisar
  • 828
  • 1
  • 10
  • 28
  • What mobile are you using – blackHawk Apr 12 '17 at 14:09
  • Using Moto X play – Nisar Apr 12 '17 at 14:10
  • 1
    I am new to android. Is this correct way? – Nisar Apr 12 '17 at 14:13
  • Ever get this working? – JoeTomks Nov 23 '18 at 11:30
  • did you ever find an answer to this question ? – Someone Somewhere May 28 '19 at 23:26
  • 1
    STATE_HARDWARE_UNAVAILABLE comes when 1.) no dspModuleProperties are available for SoundTrigger service - usually missing sound triggers models too. 2.) Voice enrollment metadata is missing (system permission needed) – rudifus Jan 28 '20 at 11:27
  • Aside from that class, which ones more do you have? All the others that are on the link? Could you post how you have them? (If you still remember and are reading.) I'm trying now a second time to do this, but I'm having some issues with old classes on that link, even though it's from Google. – Edw590 Oct 02 '20 at 16:59
  • @rudifus Would you know why it would complain about no DSP modules? Because the Google app works, so why doesn't mine? (or the OP's, or whoever's) I'm confused. Are you able to turn on a light around ahah? Also, do you know what is the DSP module they talk about? Not that it matters much, but I got curious. The main question is the other one, because I don't get it. I don't get why this doesn't work at all if the Google app does. Weird. – Edw590 May 27 '22 at 00:35
  • @DADi590 DSP modules are proprietary SoundTrigger AI speech/voice binary models to detect hotword sounds. Usually from Qualcomm (chipset) or Google. When doing custom VoiceInteractionService - some steps need to be done and checked -> custom keywords enrollment linked to DSP models, and/or SoundTrigger HAL update with audio device configurations of bus/channels (AudioFlinger). It is a low level platform thingy - nothing resolvable only via upper VoiceInteractorService. – rudifus Nov 30 '22 at 20:38

1 Answers1

0

VoiceInteractionService need android.permission.BIND_VOICE_INTERACTION in AndroidManifests

SJK
  • 1
  • 1
  • Yes, I already used this permission `android:permission="android.permission.BIND_VOICE_INTERACTION"` in `AndroidManifest`. – Nisar May 23 '17 at 07:47
  • I don't know why but android is a bit strange. You can install the app with this permission as a normal app, but in real android didn't gave your app this permission. So you also have to install the App as System App – BierDav Jan 14 '21 at 06:50
  • @BierDav Not really. This permission is to ensure only a package (app) with that permission can invoke the service. So not any app can bind to that service --> only the system – Edw590 Jan 04 '22 at 02:05
  • @DADi590 I didn't understand your point? – BierDav Jan 04 '22 at 12:14
  • @BierDav I mean you don't need to hold the permission for that to work. That's just an indicator that means that whoever wants to take control of the service must be holding that permission. So if I want to start that service, I must be a system app with the permission. Anyone else (even system apps) without that permission won't be able to control the service. You don't have to hold the permission. Someone else has to. It doesn't need to be a system permission though. You could want that the service is started by apps with INTERNET permission only or something. Hopefully it's better now? – Edw590 Jan 05 '22 at 00:46
  • So you say that the permission is not for my app to be able to use the service. It's for the app/service that starts my app to give me the permission to access the service? – BierDav Jan 06 '22 at 21:53
  • @BierDav Sorry for the "delay"... Only noticed this now! (Because I'm after answers again, even though I advanced a bit on it, but not enough) Still not that ahah, but almost there. It's a way to ensure that only authorized apps can start your app (in this case, only an app that holds the `BIND_VOICE_INTERACTION ` permission - your app or a component of it, like an activity, receiver or service). It doesn't grant you the permission nor you have to hold it. And it's the system that checks it. If the app attempting to start your app holds the permission, it can start it, else it won't be able to – Edw590 May 26 '22 at 23:59
  • @DADi590 also when configuring platform a default system role holder for assistant is to be in place - so that your custom VoiceInteractionService gets selectable via Settings by user - or is by default selected there. – rudifus Nov 30 '22 at 20:41