porcupineManager.stop() and .destroy() does not work

Viewed 144

I have been trying to implement a way that the application detect wake word like "Hey google" or "Jarvis". I did some research and found out porcupine helps towards solving the wake word problem but now the problem is I can't seem to trigger startRecognition() to listen again for the user input and then carry forward with it. I still tried to trigger startRecognition() but then it was asking me to do speechRecognizer.Destroy() which I tried doing with the porcupine onDestroy method but then it just stopped working. Sorry if I confused anyone, I will attach my code I will really appreciate everyone's help as I have been trying to solve this problem for a while now.

Another question is what does the following line of code do?

PendingIntent contentIntent = PendingIntent.getActivity(
                                    this,
                                    0,
                                    new Intent(this, MainActivity.class), // this line ?
                                    0);

The code currently :(

public class PorcupineService extends Service {

private static final int REQUEST_RECORD_AUDIO_PERMISSION_CODE = 1;
private SpeechRecognizer speechRecognizer;
TextToSpeech textToSpeech;
String userResponse;
Float speechRate = 2f;

private static final String CHANNEL_ID = "PorcupineServiceChannel";
private PorcupineManager porcupineManager;

private int numUtterances;

private void createNotificationChannel() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel notificationChannel = new NotificationChannel(
                CHANNEL_ID,
                "Porcupine",
                NotificationManager.IMPORTANCE_HIGH);

        NotificationManager manager = getSystemService(NotificationManager.class);
        manager.createNotificationChannel(notificationChannel);
    }
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    createNotificationChannel();

    PendingIntent pendingIntent = PendingIntent.getActivity(
            this,
            0,
            new Intent(this, MainActivity.class),
            0);

    numUtterances = 0;

    Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("Wake word")
            .setContentText("Service running")
            .setSmallIcon(R.drawable.ic_launcher_foreground)
            .setContentIntent(pendingIntent)
            .build();

    startForeground(1234, notification);

    try {
        porcupineManager = new PorcupineManager.Builder()
                .setKeyword(Porcupine.BuiltInKeyword.JARVIS)
                .setSensitivity(0.7f).build(
                        getApplicationContext(),
                        (keywordIndex) -> {
                            Log.i("YOU SAID IT!", "yesss");

                            textSpeechInitialize();
                            startRecognition();
                            listening();

                            numUtterances++;

                            PendingIntent contentIntent = PendingIntent.getActivity(
                                    this,
                                    0,
                                    new Intent(this, MainActivity.class),
                                    0);

                            final String contentText = numUtterances == 1 ? " time!" : " times!";
                            Notification n = new NotificationCompat.Builder(this, CHANNEL_ID)
                                    .setContentTitle("Wake word")
                                    .setContentText("Detected " + numUtterances + contentText)
                                    .setSmallIcon(R.drawable.ic_launcher_background)
                                    .setContentIntent(contentIntent)
                                    .build();

                            NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                            assert notificationManager != null;
                            notificationManager.notify(1234, n);
                        });
        porcupineManager.start();
    } catch (PorcupineException e) {
        Log.e("PORCUPINE", e.toString());
    }

    return super.onStartCommand(intent, flags, startId);
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public void onDestroy() {
    try {
        porcupineManager.stop();
        porcupineManager.delete();
        speechRecognizer.destroy();
    } catch (PorcupineException e) {
        Log.e("PORCUPINE", e.toString());
    }

    super.onDestroy();
}

public void listening(){
    speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this);
    speechRecognizer.setRecognitionListener(new RecognitionListener() {

        @Override
        public void onReadyForSpeech(Bundle params) {
        }

        @Override
        public void onBeginningOfSpeech() {}

        @Override
        public void onRmsChanged(float rmsdB) {}

        @Override
        public void onBufferReceived(byte[] buffer) {}

        @Override
        public void onEndOfSpeech() {}

        @Override
        public void onError(int error) {
            String errorMessage = getErrorText(error);
            Log.i(">>> INFO", "Failed " + errorMessage);
        }

        @Override
        public void onResults(Bundle results) {
            ArrayList<String> matches = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
            userResponse = matches.get(0);
            userResponse = userResponse.toLowerCase();
            toSpeak(userResponse);
        }

        @Override
        public void onPartialResults(Bundle partialResults) {}

        @Override
        public void onEvent(int eventType, Bundle params) {}

    });
}

public void textSpeechInitialize(){
    textToSpeech = new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
        @Override
        public void onInit(int status) {
            if (status == TextToSpeech.SUCCESS){
                textToSpeech.setLanguage(Locale.getDefault());
                textToSpeech.setSpeechRate(speechRate);
                String greet = greetings();
                toSpeak(greet);
                startRecognition();
            } else {
                Toast.makeText(getApplicationContext(), "Feature not supported", Toast.LENGTH_SHORT).show();
            }
        }
    });
}

public String getErrorText(int errorCode) {
    String message;
    switch (errorCode) {
        ...
    }
    return message;
}

public static String greetings(){
    String s = "";
    Calendar c = Calendar.getInstance();
    int time = c.get(Calendar.HOUR_OF_DAY);

    if (time >= 0 && time < 12){
        s = "Good Morning sir! how can I help you today?";
    } else if (time >= 12 && time < 16){
        s = "Good Afternoon sir";
    } else if (time >= 16 && time < 22){
        s = "Good Evening sir";
    }
    else if (time >= 22 && time < 24){
        s = "Hello sir, you need to take some rest... its getting late!";
    }
    return s;
}

private void startRecognition() {
    Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
    intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, getPackageName());
    intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
    intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, "en");
    speechRecognizer.startListening(intent);
}

private void toSpeak(String toSpeak){

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        Log.i(">>>Voice Info", String.valueOf(textToSpeech.getVoice()));
    }
    try {
        textToSpeech.speak(toSpeak, TextToSpeech.QUEUE_FLUSH, null);
    } catch (Exception e){
        e.printStackTrace();
    }
}
}
1 Answers
  1. Since startRecognition() is not getting triggered, check permission to record audio in MainActivity. Your app's AndroidManifest.xml should have the following line:

<uses-permission android:name="android.permission.RECORD_AUDIO"/>

or, you might have to explicitly ask for user permission. You can refer to this article on Medium:

https://medium.com/picovoice/no-way-google-build-your-own-wake-word-service-on-android-339a0189ff4c

  1. Intents are objects of android.content.Intent type. It's basically a passive data structure holding an abstract description of an action to be performed(like starting activities or services). Here, it starts MainActivity class, which gets triggered immediately after the user logs in to mobile SDK apps.

    new Intent(this, MainActivity.class)

For more details, you can check out the following docs:

Related