Autore Topic: Speech recognition su pressione bottone auricolare bluetooth  (Letto 726 volte)

Offline bianchins

  • Nuovo arrivato
  • *
  • Post: 1
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S3 Neo
  • Sistema operativo:
    Max OSX / Windows 7
Speech recognition su pressione bottone auricolare bluetooth
« il: 11 Dicembre 2015, 15:02:44 CET »
0
Ciao a tutti,
scrivo per la prima volta su questo forum. Vi spiego il mio problema: ho creato un sistema open source che, per farvela breve, funziona tramite API Rest. Mediante queste api riceve dei comandi in formato testuale e agisce di conseguenza (ad esempio, accende una luce, controlla il meteo ecc.). Il sistema è il seguente (https://github.com/bianchins/JarvisPHP)


Ora il problema: sto tentando di creare una applicazione Android che, tramite auricolare bluetooth e lo Speech recognition dell'Android SDK, trasformi la voce in testo ed invii la stringa via http al webserver del sistema.
Quindi, per intenderci: premo il bottone sull'auricolare bluetooth, la app viene lanciata automaticamente con il servizio di riconoscimento vocale, il risultato viene inviato via http.

Ciò che ho fatto fino ad ora si limita a:
- creare una activity che, appena lanciata, mostra l'intent di speech recognition;
- sul result della intent, gestisco la stringa riconosciuta e la invio via http.

Codice (Java): [Seleziona]
// codice di onCreate sulla MainActivity
        s = new SpeechRecognitionHelper();
        s.run(MainActivity.this);

Codice (Java): [Seleziona]
//SpeechRecognitionHelper.java
package net.stefanobianchini.jarvis;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.speech.RecognizerIntent;
import android.widget.Toast;

import java.util.List;

/**
 * Created by stefano on 26/01/15.
 */

public class SpeechRecognitionHelper {
    /**
     * Running the recognition process. Checks availability of recognition Activity,
     * If Activity is absent, send user to Google Play to install Google Voice Search.
     * If Activity is available, send Intent for running.
     *
     * @param callingActivity = Activity, that initializing recognition process
     */

    public static void run(Activity callingActivity) {
        // check if there is recognition Activity
        if (isSpeechRecognitionActivityPresented(callingActivity)) {
            // if yes – running recognition
            startRecognitionActivity(callingActivity);
        } else {
            // if no, then showing notification to install Voice Search
            Toast.makeText(callingActivity, "In order to activate speech recognition you must install \"Google Voice Search\"", Toast.LENGTH_LONG).show();
            // start installing process
            installGoogleVoiceSearch(callingActivity);
        }
    }

    /**
     * Checks availability of speech recognizing Activity
     *
     * @param callerActivity – Activity that called the checking
     * @return true – if Activity there available, false – if Activity is absent
     */

    private static boolean isSpeechRecognitionActivityPresented(Activity callerActivity) {
        try {
            // getting an instance of package manager
            PackageManager pm = callerActivity.getPackageManager();
            // a list of activities, which can process speech recognition Intent
            List activities = pm.queryIntentActivities(new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0);

            if (activities.size() != 0) {    // if list not empty
                return true;                // then we can recognize the speech
            }
        } catch (Exception e) {

        }

        return false; // we have no activities to recognize the speech
    }

    /**
     * Send an Intent with request on speech
     * @param callerActivity  - Activity, that initiated a request
     */

    private static void startRecognitionActivity(Activity callerActivity) {

        // creating an Intent with “RecognizerIntent.ACTION_RECOGNIZE_SPEECH” action
        Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);

        // giving additional parameters:
        intent.putExtra(RecognizerIntent.EXTRA_PROMPT, "Pronto a servirti");    // user hint
        intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent. LANGUAGE_MODEL_FREE_FORM);    // setting recognition model, optimized for short phrases – search queries
        intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);    // quantity of results we want to receive
        //choosing only 1st -  the most relevant

        // start Activity ant waiting the result
        callerActivity.startActivityForResult(intent, 1212);
    }

    /**
     * Asking the permission for installing Google Voice Search.
     * If permission granted – sent user to Google Play
     * @param ownerActivity – Activity, that initialized installing
     */

    private static void installGoogleVoiceSearch(final Activity ownerActivity) {

        // creating a dialog asking user if he want
        // to install the Voice Search
        Dialog dialog = new AlertDialog.Builder(ownerActivity)
                .setMessage("For recognition it’s necessary to install \"Google Voice Search\"")    // dialog message
                .setTitle("Install Voice Search from Google Play?")    // dialog header
                .setPositiveButton("Install", new DialogInterface.OnClickListener() {    // confirm button

                    // Install Button click handler
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        try {
                            // creating an Intent for opening applications page in Google Play
                            // Voice Search package name: com.google.android.voicesearch
                            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.google.android.voicesearch"));
                            // setting flags to avoid going in application history (Activity call stack)
                            intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
                            // sending an Intent
                            ownerActivity.startActivity(intent);
                        } catch (Exception ex) {
                            // if something going wrong
                            // doing nothing
                        }
                    }})

                .setNegativeButton("Cancel", null)    // cancel button
                .create();

        dialog.show();    // showing dialog
    }
}

A questo punto mi sono scontrato con la gestione del bottone. Inizialmente ho tentato di gestire la pressione del bottone "MEDIA" dell'auricolare con il filo (si, so che dovrò usare una libreria diversa per il bottone del bluetooth), tramite il seguente codice
Codice (Java): [Seleziona]
((AudioManager)getSystemService(AUDIO_SERVICE)).registerMediaButtonEventReceiver(new ComponentName(
                this,
                MediaButtonIntentReceiver.class));
Codice (Java): [Seleziona]
public static class MediaButtonIntentReceiver extends BroadcastReceiver {

        public MediaButtonIntentReceiver() {
            super();
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            String intentAction = intent.getAction();
            if (!Intent.ACTION_MEDIA_BUTTON.equals(intentAction)) {
                return;
            }
            KeyEvent event = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
            if (event == null) {
                return;
            }
            int action = event.getAction();
            System.out.println("ok");
            Toast.makeText(context, "Pressione bottone", Toast.LENGTH_LONG).show();
            abortBroadcast();
        }

    }
Il codice funziona (il toast viene visualizzato) ma se cerco di far partire l'intent dello speechrecognition... non me lo fa compilare.
Ovvero: non riesco ad utilizzare l'intent dello speech recognition perché il MediaButtonIntentReceiver deve essere dichiarato statico; l'intent di riconoscimento vocale necessita di una activity per intercettare il risultato, quindi il receiver deve interagire con qualcosa che statico non è.

E adesso la domanda: come posso risolvere il mio problema nel migliore dei modi? Qualcuno ha esperienza in tal senso? E' possibile creare un servizio in background che, alla pressione del bottone bluetooth, faccia il riconoscimento vocale ed invii il risultato come stringa ad un web server?

Grazie a tutti anticipatamente per l'aiuto e la pazienza.

P.s. ovviamente anche questa parte dell'applicazione (app Android) sarà pubblicata su Github open source.

Edit: non sapevo se postarlo nella sezione servizi o in quella gestione media... spero di non aver sbagliato.
« Ultima modifica: 11 Dicembre 2015, 15:09:40 CET da bianchins »