如何注册自定义语音识别服务?

12

我创建了一个简单的语音识别服务:为此,我创建了android.speech.RecognitionService的子类,并创建了一个活动来启动和停止该服务。

我的自定义语音识别服务简单地使用了默认的语音识别器,因为我的目标只是了解RecognitionServiceRecognitionService.Callback类的工作原理。

public class SimpleVoiceService extends RecognitionService {

    private SpeechRecognizer m_EngineSR;

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("SimpleVoiceService", "Service started");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i("SimpleVoiceService", "Service stopped");
    }

    @Override
    protected void onCancel(Callback listener) {
        m_EngineSR.cancel();
    }

    @Override
    protected void onStartListening(Intent recognizerIntent, Callback listener) {
        m_EngineSR.setRecognitionListener(new VoiceResultsListener(listener));
        m_EngineSR.startListening(recognizerIntent);
    }

    @Override
    protected void onStopListening(Callback listener) {
        m_EngineSR.stopListening();
    }


    /**
     * 
     */
    private class VoiceResultsListener implements RecognitionListener {

        private Callback m_UserSpecifiedListener;

        /**
         * 
         * @param userSpecifiedListener
         */
        public VoiceResultsListener(Callback userSpecifiedListener) {
            m_UserSpecifiedListener = userSpecifiedListener;
        }

        @Override
        public void onBeginningOfSpeech() {
            try {
                m_UserSpecifiedListener.beginningOfSpeech();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onBufferReceived(byte[] buffer) {
            try {
                m_UserSpecifiedListener.bufferReceived(buffer);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onEndOfSpeech() {
            try {
                m_UserSpecifiedListener.endOfSpeech();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onError(int error) {
            try {
                m_UserSpecifiedListener.error(error);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

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

        @Override
        public void onPartialResults(Bundle partialResults) {
            try {
                m_UserSpecifiedListener.partialResults(partialResults);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onReadyForSpeech(Bundle params) {
            try {
                m_UserSpecifiedListener.readyForSpeech(params);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onResults(Bundle results) {
            try {
                m_UserSpecifiedListener.results(results);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onRmsChanged(float rmsdB) {
            try {
                m_UserSpecifiedListener.rmsChanged(rmsdB);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

}

我使用以下活动来启动和停止服务。

public class VoiceServiceStarterActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Button startButton = new Button(this);
        startButton.setText("Start the service");
        startButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) { startVoiceService(); }
        });
        Button stopButton = new Button(this);
        stopButton.setText("Stop the service");
        stopButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) { stopVoiceService(); }
        });
        LinearLayout layout = new LinearLayout(this);
        layout.setOrientation(LinearLayout.VERTICAL);
        layout.addView(startButton);
        layout.addView(stopButton);
        setContentView(layout);
    }

    private void startVoiceService() {
        startService(new Intent(this, SimpleVoiceService.class));
    }

    private void stopVoiceService() {
        stopService(new Intent(this, SimpleVoiceService.class));
    }
}

最后我在AndroidManifest.xml中声明了我的服务(请参见Android SDK文件夹中的VoiceRecognition示例)。

<service android:name="SimpleVoiceService"
         android:label="@string/service_name" >

    <intent-filter>
        <action android:name="android.speech.RecognitionService" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</service>

然后我在安卓设备上安装了这个应用程序并启动它: - 当我启动服务时,它会正常启动; - 当我停止它时,它会正常停止。

但是,如果我在另一个活动中启动以下代码,则activities List仅包含一个元素,即默认的语音识别器。

PackageManager pm = getPackageManager();
List<ResolveInfo> activities = pm.queryIntentActivities(
            new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0);

为什么我的语音识别器没有出现在系统中?


1
这能让我们覆盖“Google Now”默认的RecognitionService吗?我的意思是,我能为Google Now挂钩自己扩展的识别服务吗? - Sid Sarasvati
1
当您启动SimpleVoiceSearch服务时,您的onStartListening是否开始工作?@enzom83 - Gaurav Arora
2个回答

8

如果你希望queryIntentActivities(new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0)能够识别你的活动(VoiceServiceStarterActivity),那么你需要在你的应用程序清单中声明这个活动处理RecognizerIntent.ACTION_RECOGNIZE_SPEECH。声明方式如下:

<activity android:name="VoiceServiceStarterActivity">
  <intent-filter>
    <action android:name="android.speech.action.RECOGNIZE_SPEECH" />
    <category android:name="android.intent.category.DEFAULT" />
  </intent-filter>
  ...
</activity>

如果想要更具体的代码,请查看项目Kõnele源代码),它本质上是Android提供语音识别接口的开源实现,即涵盖了以下内容:

  • ACTION_RECOGNIZE_SPEECH
  • ACTION_WEB_SEARCH
  • RecognitionService

并使用开源语音识别服务器。


1
我不明白为什么我应该创建一个新的活动。目前,我有一个处理默认语音识别器的活动(VoiceDemoActivity),它通过一个 SpeechRecognizer 对象来处理。为了使用自定义语音识别服务,我必须创建一个新的 SpeechRecognizer 对象,并在 createSpeechRecognizer 方法中指定一个 ComponentName 对象:我认为这个 ComponentName 应该是指自定义语音识别服务,因此我创建了一个新的 RecognitionService 类。我为什么需要实现另一个可以处理 ACTION_RECOGNIZE_SPEECH 意图的活动呢? - enzom83
2
我稍微改进了我的答案,也许使它更清晰了一点。 - Kaarel
@Kaarel,我非常喜欢你在Kõnele中所做的事情(尽管我不懂爱沙尼亚语)。我从Github下载了源代码,以此为例学习如何实现自己的(仅英语),但它无法直接构建,在Google Play上下载的发布应用程序本身也会卡在“转录...”处。我在哪里可以了解有关您的代码结构(3个不同的包)以及为什么要这样实现的更多信息?谢谢! - ripopenid
@ripopenid 谢谢!Kõnele实际上是独立于语言的,但目前主要关注的确实是爱沙尼亚语。Kõnele使用的默认服务器也支持英语,但仅限于基于语法的语音识别(http://kaljurand.github.io/Grammars/)。请在https://code.google.com/p/recognizer-intent/issues/list报告您发现的任何错误(以及缺乏文档),我可以作为错误报告的一部分进行回应。 - Kaarel

0

是的,您需要使用createSpeechRecognizer(Context context, ComponentName serviceComponent)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接