Click here to Skip to main content
15,887,083 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I keep on getting this same error each time I test my game and I don't even know where it is being generated. This is the related code

Java plugin
Java
package com.example.unityandroidplswork;

import android.content.Intent;
import android.app.Activity;
import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;
import android.util.Log;

import java.util.ArrayList;


public class STTPlugin {
    private static final int REQUEST_CODE = 1234;
    private static final String TAG = "SpeechRecognitionPlugin";
    private Activity activity;
    private SpeechRecognizer speechRecognizer;
    private SpeechRecognitionResultListener resultListener;

    public STTPlugin(Activity activity) {

        this.activity = activity;
    }

    public void startSpeechRecognition(SpeechRecognitionResultListener listener, int requestCode) {
        if (SpeechRecognizer.isRecognitionAvailable(activity.getApplicationContext())) {
            resultListener = listener;
            if (speechRecognizer == null) {
                speechRecognizer = SpeechRecognizer.createSpeechRecognizer(activity.getApplicationContext());
            }
            Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
            intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
            intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 10);
            speechRecognizer.startListening(intent);
            activity.startActivityForResult(intent, requestCode);
            Log.d(TAG, "Escuchando...");
        } else {
            Log.d(TAG, "Reconocimiento no disponible.");
        }

    }

    public void stopSpeechRecognition() {
        if (speechRecognizer != null) {
            speechRecognizer.stopListening();
        }
    }

    private String[] processRecognitionResults(ArrayList<String> results) {
        return results.toArray(new String[results.size()]);
    }

    public void handleActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) {
            ArrayList<String> results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
            if (resultListener != null) {
                String[] resultsArray = processRecognitionResults(results);
                resultListener.onResults(resultsArray);
            }
        }
    }

    public interface SpeechRecognitionResultListener {
        void onResults(String[] results);
    }


}


C# script:

C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.UI;
using TMPro;

public class SpeechRecog : MonoBehaviour
{

    private AndroidJavaObject speechRecPlugin;
    public TextMeshProUGUI textofresult;
    private int requestCode = 1234;
    private bool isSpeechRecognitionActive = false;

    // Start is called before the first frame update
    void Start()
    {
        AndroidJavaObject activity = new AndroidJavaClass("com.unity3d.player.UnityPlayer").GetStatic<AndroidJavaObject>("currentActivity");
        speechRecPlugin = new AndroidJavaObject("com.example.unityandroidplswork.STTPlugin", activity);
        if(!Permission.HasUserAuthorizedPermission(Permission.Microphone)) {
            Permission.RequestUserPermission(Permission.Microphone);
        }
    }

    public void StartSpeechRecognition() {
        AndroidJavaObject speechResultListener = new AndroidJavaObject("com.example.unityandroidplswork.STTPlugin$SpeechRecognitionResultListener", this);
        CallOnMainThread(() =>
        {
            speechRecPlugin.Call("startSpeechRecognition", speechResultListener);
        });
    }

    public void StopSpeechRecognition() {
        CallOnMainThread(() =>
        {
            speechRecPlugin.Call("stopSpeechRecognition");
        });
    }

    private void ProcessRecognitionResults(string[] results) {
        string recognizedtext = "";
        foreach(string result in results) {
            Debug.Log("Result: " + result);
            recognizedtext += result + " ";
        }
        CallOnMainThread(() =>
        {
            textofresult.text = recognizedtext;
        });
        //process here for sure
        //ProcessCommands(results)
    }

    private void CallOnMainThread(System.Action action) {
        UnityMainThreadDispatcher.Instance().Enqueue(action);
    }


    private class SpeechRecognitionResultListener : AndroidJavaProxy {

        private SpeechRecog plugin;

        public SpeechRecognitionResultListener(SpeechRecog plugin) : base("com.example.unityandroidplswork.STTPlugin$SpeechRecognitionResultListener") {
            this.plugin = plugin;
        }

        public void onResults(AndroidJavaObject results) {
            string[] resultArray = AndroidJNIHelper.ConvertFromJNIArray<string[]>(results.GetRawObject());
            plugin.ProcessRecognitionResults(resultArray);
        }
    }

    // Update is called once per frame
    void Update()
    {

    }
}




What I have tried:

I tried modifying both the handleActivityResult method and onResults method so the JNIHelper deals with AndroidJavaObject's instead of strings, but I'm not even sure that's the root of the problem
Posted
Updated 20-Jun-23 21:26pm

1 solution

Looking at the C# code you have:
C#
public void StartSpeechRecognition() {
    AndroidJavaObject speechResultListener = new AndroidJavaObject("com.example.unityandroidplswork.STTPlugin$SpeechRecognitionResultListener", this);
    CallOnMainThread(() =>
    {
        speechRecPlugin.Call("startSpeechRecognition", speechResultListener);
    });
}

The call to the constructor of the AndroidJavaObject is being passed the this variable, which is an instance of the enclosing SpeechRecog class. So it is reasonable to assume that that is where the problem lies. Exactly why the constructor is objecting to that parameter can only be answered by studying the documentation for the AndroidJavaObject class.

[edit]
Looking at the documentation at Unity - Scripting API: AndroidJavaObject.AndroidJavaObject[^], it would appear that the constructor is expecting the name of an existing Java class. but you do not appear to have a class with the name com.example.unityandroidplswork.STTPlugin$SpeechRecognitionResultListener. The only reference I can see to that name is a declared interface in your STTPlugin class.

[/edit]
 
Share this answer
 
v3

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900