Служба Google Now в моем приложении

Я заблокирован сервисом и Google TTS. Ну, я хочу, чтобы сервис запускался в bg, и когда я говорю «окей, Google» или что бы я ни выбрал, начинается распознавание текста. Я создал сервис, но теперь... Что мне делать? Я застрял. Это сервис:

public class GnowService extends Service
{
    protected static AudioManager mAudioManager; 
    protected SpeechRecognizer mSpeechRecognizer;
    protected Intent mSpeechRecognizerIntent;
    protected final Messenger mServerMessenger = new Messenger(new IncomingHandler(this));

    protected boolean mIsListening;
    protected volatile boolean mIsCountDownOn;
    private static boolean mIsStreamSolo;

    static final int MSG_RECOGNIZER_START_LISTENING = 1;
    static final int MSG_RECOGNIZER_CANCEL = 2;

    @Override
    public void onCreate()
    {
        super.onCreate();
        mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 
        mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(this);
        mSpeechRecognizer.setRecognitionListener(new SpeechRecognitionListener());
        mSpeechRecognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
        mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
                                         RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
        mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE,
                                         this.getPackageName());
    }

    protected static class IncomingHandler extends Handler
    {
        private WeakReference<GnowService> mtarget;

        IncomingHandler(GnowService target)
        {
            mtarget = new WeakReference<GnowService>(target);
        }


        @Override
        public void handleMessage(Message msg)
        {
            final GnowService target = mtarget.get();

            switch (msg.what)
            {
                case MSG_RECOGNIZER_START_LISTENING:

                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
                    {
                        // turn off beep sound  
                        if (!mIsStreamSolo)
                        {
                            mAudioManager.setStreamSolo(AudioManager.STREAM_VOICE_CALL, true);
                            mIsStreamSolo = true;
                        }
                    }
                     if (!target.mIsListening)
                     {
                         target.mSpeechRecognizer.startListening(target.mSpeechRecognizerIntent);
                         target.mIsListening = true;
                        //Log.d(TAG, "message start listening"); //$NON-NLS-1$
                     }
                     break;

                 case MSG_RECOGNIZER_CANCEL:
                    if (mIsStreamSolo)
                   {
                        mAudioManager.setStreamSolo(AudioManager.STREAM_VOICE_CALL, false);
                        mIsStreamSolo = false;
                   }
                      target.mSpeechRecognizer.cancel();
                      target.mIsListening = false;
                      //Log.d(TAG, "message canceled recognizer"); //$NON-NLS-1$
                      break;
             }
       } 
    } 

    // Count down timer for Jelly Bean work around
    protected CountDownTimer mNoSpeechCountDown = new CountDownTimer(5000, 5000)
    {

        @Override
        public void onTick(long millisUntilFinished)
        {
            // TODO Auto-generated method stub

        }

        @Override
        public void onFinish()
        {
            mIsCountDownOn = false;
            Message message = Message.obtain(null, MSG_RECOGNIZER_CANCEL);
            try
            {
                mServerMessenger.send(message);
                message = Message.obtain(null, MSG_RECOGNIZER_START_LISTENING);
                mServerMessenger.send(message);
            }
            catch (RemoteException e)
            {

            }
        }
    };

    @Override
    public void onDestroy()
    {
        super.onDestroy();

        if (mIsCountDownOn)
        {
            mNoSpeechCountDown.cancel();
        }
        if (mSpeechRecognizer != null)
        {
            mSpeechRecognizer.destroy();
        }
    }

    protected class SpeechRecognitionListener implements RecognitionListener
    {

        @Override
        public void onBeginningOfSpeech()
        {
            // speech input will be processed, so there is no need for count down anymore
            if (mIsCountDownOn)
            {
                mIsCountDownOn = false;
                mNoSpeechCountDown.cancel();
            }               
            //Log.d(TAG, "onBeginingOfSpeech"); //$NON-NLS-1$
        }

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

        }

        @Override
        public void onEndOfSpeech()
        {
            //Log.d(TAG, "onEndOfSpeech"); //$NON-NLS-1$
         }

        @Override
        public void onError(int error)
        {
            if (mIsCountDownOn)
            {
                mIsCountDownOn = false;
                mNoSpeechCountDown.cancel();
            }
             mIsListening = false;
             Message message = Message.obtain(null, MSG_RECOGNIZER_START_LISTENING);
             try
             {
                    mServerMessenger.send(message);
             }
             catch (RemoteException e)
             {

             }
            //Log.d(TAG, "error = " + error); //$NON-NLS-1$
        }

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

        }

        @Override
        public void onPartialResults(Bundle partialResults)
        {

        }

        @Override
        public void onReadyForSpeech(Bundle params)
        {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
            {
                mIsCountDownOn = true;
                mNoSpeechCountDown.start();

            }
            Log.d("", "onReadyForSpeech"); //$NON-NLS-1$
        }

        @Override
        public void onResults(Bundle results)
        {
            //Log.d(TAG, "onResults"); //$NON-NLS-1$

        }

        @Override
        public void onRmsChanged(float rmsdB)
        {

        }

    }

    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        return null;
    }
}

Должен ли я создать что-то в моем MainActivity? Как я могу «сказать» приложению распознавать, например, слова: «Окей, Google»? чтобы начать намерение? Спасибо РЕДАКТИРОВАТЬ:

Это часть, которую я интегрировал в манифест:

<receiver
            android:name=".mBootCompletedReceiver"
            android:enabled="true"
            android:permission="android.permission.RECEIVE_BOOT_COMPLETED" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />

            </intent-filter>
    </receiver>
        <service android:name=".GnowService"></service>

в моей MainActivity я создал Broadcastreceiver

private BroadcastReceiver mBootCompletedReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Intent serviceIntent = new Intent();
            serviceIntent.setAction("com.dd.speech.GnowService");
            context.startService(serviceIntent);
        }
    };

Прежде всего.. пока правильно? Или я ошибаюсь? Затем, другие пункты, которые я не знаю, понимаю ли я и могу ли я это сделать. У вас есть образец кода для этого?


person Atlas91    schedule 18.03.2014    source источник


Ответы (1)


В моем ответе предлагаю решение, распознаватель всегда слушает. Он просто ничего не делает, пока не будет произнесено ключевое слово. Предположим, что приложение ничего не делает, пока пользователь не скажет «начать окончание игры», и ничего не делает снова, когда пользователь говорит «остановить окончание игры».

  1. Зарегистрируйте Intent.ACTION_BOOT_COMPLETED в манифесте и создайте класс BroadcastReceiver для прослушивания этого события и запуска службы. Ваше приложение должно быть запущено хотя бы один раз, чтобы приемник получил эту трансляцию.
  2. В вашей MainActivity запустите службу в onCreate. Если вы хотите общаться с сервером, то привяжите службу в onStart и отвяжите в onStop.
  3. В сервисе создайте флаг private boolean mShouldProcessResult;
  4. В onResults, если флаг mShouldProcessResult имеет значение false, просто проверьте, содержит ли результат «начало конца игры». Если да, сообщите пользователю, что приложение начнет обрабатывать его/ее произнесенные слова, и установите для флага mShouldProcessResult значение true, иначе ничего не делайте. Если флаг mShouldProcessResult имеет значение true, обрабатывать все, что когда-либо говорил пользователь, это должно включать «остановить окончание игры».

Имейте в виду, что срок службы батареи значительно сократится, в некоторых случаях примерно наполовину.

person Hoan Nguyen    schedule 18.03.2014
comment
Будет ли ваша идея предотвращать попадание произносимых слов в Интернет (на серверы Google) до того, как будет распознано начало и конец игры (например, OK Google работает для Google Now)? Если нет, возможно ли это сделать в любой из существующих версий Android? Спасибо +1. - person sfinja; 13.03.2015
comment
Затем вам нужно использовать Sphinx или автономный распознаватель речи, который доступен только в Jelly Bean. - person Hoan Nguyen; 13.03.2015
comment
Спасибо, Хоан. Разве PocketSphinx не доступен для всех версий Android, начиная с 2.2? Если это так, вы можете иметь в виду какой-то другой автономный распознаватель речи, который доступен только в JellyBean. Верно? Вы имеете в виду какой-то конкретный автономный распознаватель? (т.е. можете ли вы порекомендовать один?) - person sfinja; 13.03.2015
comment
В автономном режиме, доступном в JellyBean, является распознаватель речи Google. Однако вы должны отключить интернет-соединение. Поэтому я думаю, что PocketSphinx — ваш вариант. - person Hoan Nguyen; 14.03.2015