음성 입력

음성 입력을 사용하면 핸즈프리 인터페이스를 구현할 수 있습니다. Glass는 음성 입력을 활용하는 세 가지 방법을 제공합니다.

기본 음성 명령은 Home 카드에서 Glass 웨어를 시작하고, 상황별 음성 명령으로 활동 내에서 작업을 실행할 수 있으며, 시스템의 음성 인식 활동을 통해 사용자로부터 자유 형식의 음성 입력을 받을 수 있습니다.

기본 음성 명령

다음 음성 명령을 사용하여 Home 카드 (시계 카드)에서 Glassware를 실행합니다. 사용자가 기본 음성 명령을 선언하면 Glass가 홈 카드를 탭하여 Glass를 시작하려는 경우 자동으로 터치 메뉴 항목을 대체합니다.

ok glass 음성 기본 메뉴에 음성 명령을 추가하려면 다음 단계를 따르세요.

  1. VoiceTriggers.Command에 정의된 기존 음성 명령 중 하나를 사용하는 res/xml/<my_voice_trigger>.xml에 음성 명령어의 XML 리소스를 만듭니다. 예를 들어 '달리기 시작'을 사용하는 방법은 다음과 같습니다.

    <?xml version="1.0" encoding="utf-8"?>
    <trigger command="START_A_RUN" />
    

    활동 또는 서비스를 시작하기 전에 사용자에게 추가 문구를 말하도록 안내하는 음성 명령을 만들려면 input 요소도 포함합니다. 예를 들어 '업데이트 게시'를 사용하는 경우 이 작업을 실행할 수 있습니다.

    <?xml version="1.0" encoding="utf-8"?>
    <trigger command="POST_AN_UPDATE">
        <input prompt="@string/glass_voice_prompt" />
    </trigger>
    
  2. Android 매니페스트에서 com.google.android.glass.action.VOICE_TRIGGER 작업을 사용하여 인텐트 필터를 등록합니다. 인텐트 필터는 사용자가 음성 명령어를 말하는 것을 감지하면 활동 또는 서비스를 시작합니다.

    <?xml version="1.0" encoding="utf-8"?>
    <application ...>
        <activity | service ...>
            <intent-filter>
                <action android:name=
                        "com.google.android.glass.action.VOICE_TRIGGER" />
            </intent-filter>
            <meta-data android:name="com.google.android.glass.VoiceTrigger"
                android:resource="@xml/my_voice_trigger" />
        </activity | service>
        // ...
    </application>
    
  3. 활동 또는 서비스의 android:icon 속성을 선언합니다. 이렇게 하면 Glass가 ok, glass 터치 메뉴에 Glass 소프트웨어 아이콘을 표시할 수 있습니다.

    <activity |service
        android:icon="@drawable/my_icon" ...>
      ...
    </activity | service>
    
  4. 음성 명령이 음성 메시지를 사용하여 활동을 시작하는 경우 다음 코드를 사용하여 받아쓰기한 텍스트를 가져옵니다 (예: onResume()).

    ArrayList<String> voiceResults = getIntent().getExtras()
            .getStringArrayList(RecognizerIntent.EXTRA_RESULTS);
    

    음성 명령어가 서비스를 시작하면 onStartCommand() 콜백에서 인텐트 추가 항목을 사용할 수 있습니다.

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        ArrayList<String> voiceResults = intent.getExtras()
                .getStringArrayList(RecognizerIntent.EXTRA_RESULTS);
        // ...
    }
    

제약조건 설정

Glass 기능을 시작하기 위해 다음 기능 중 하나 또는 전부가 필요한 경우 res/xml/<my_voice_trigger>.xml 리소스에서 지정합니다. 기능을 사용할 수 없는 경우 Glass가 음성 명령을 사용 중지합니다.

  • camera
  • network
  • microphone

    <trigger command="POST_AN_UPDATE">
        <constraints
            camera="true"
            network="true" />
    </trigger>
    

문맥 음성 명령

상황별 음성 명령을 사용하면 사용자가 활동에서 작업을 실행할 수 있습니다. 표준 Android 메뉴 API를 사용하여 상황별 음성 명령어를 빌드하지만 사용자는 터치 대신 음성 명령어로 메뉴 항목을 호출할 수 있습니다.

특정 활동에 관한 문맥 음성 명령을 사용 설정하려면 다음 단계를 따르세요.

  1. 원하는 활동에서 getWindow().requestFeature(WindowUtils.FEATURE_VOICE_COMMANDS)를 호출하여 상황별 음성 명령어를 사용 설정합니다. 이 기능을 사용 설정하면 이 활동이 포커스를 받을 때마다 화면의 바닥글 영역에 'ok glass' 메뉴가 표시됩니다.

  2. onCreatePanelMenu()를 재정의하고 WindowUtils.FEATURE_VOICE_COMMANDS가 사용 설정된 경우를 처리합니다. 사용 설정하면 메뉴 리소스를 확장하거나 Menu.add() 메서드를 호출하여 음성 메뉴 시스템을 만드는 등 일회성 메뉴 설정을 실행합니다.

  3. 사용자가 말할 때 음성 명령어를 처리하도록 onMenuItemSelected()를 재정의합니다. 사용자가 메뉴 항목 선택을 완료하면 활동에 포커스가 있는 한 'ok, glass' 음성 명령이 화면의 바닥글 섹션에 자동으로 다시 표시되어 새 음성 명령을 받을 수 있습니다.

    다음 코드는 상황별 음성 명령어를 사용 설정하고, 필요에 따라 메뉴 리소스를 확장하며, 음성 명령이 나오면 처리합니다.

    public class ContextualMenuActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle bundle) {
            super.onCreate(bundle);
    
            // Requests a voice menu on this activity. As for any other
            // window feature, be sure to request this before
            // setContentView() is called
            getWindow().requestFeature(WindowUtils.FEATURE_VOICE_COMMANDS);
            setContentView(R.layout.activity_main);
        }
    
        @Override
        public boolean onCreatePanelMenu(int featureId, Menu menu) {
            if (featureId == WindowUtils.FEATURE_VOICE_COMMANDS) {
                getMenuInflater().inflate(R.menu.main, menu);
                return true;
            }
            // Pass through to super to setup touch menu.
            return super.onCreatePanelMenu(featureId, menu);
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
    
        @Override
        public boolean onMenuItemSelected(int featureId, MenuItem item) {
            if (featureId == WindowUtils.FEATURE_VOICE_COMMANDS) {
                switch (item.getItemId()) {
                    case R.id.dogs_menu_item:
                        // handle top-level dogs menu item
                        break;
                    case R.id.cats_menu_item:
                        // handle top-level cats menu item
                        break;
                    case R.id.lab_menu_item:
                        // handle second-level labrador menu item
                        break;
                    case R.id.golden_menu_item:
                        // handle second-level golden menu item
                        break;
                    case R.id.calico_menu_item:
                        // handle second-level calico menu item
                        break;
                    case R.id.cheshire_menu_item:
                        // handle second-level cheshire menu item
                        break;
                    default:
                        return true;
                }
                return true;
            }
            // Good practice to pass through to super if not handled
            return super.onMenuItemSelected(featureId, item);
        }
    }
    

    다음은 이전 활동에서 사용한 메뉴 리소스의 예시입니다. 계층적 음성 메뉴 시스템의 중첩된 메뉴 항목을 만드는 방법을 확인하세요. 다음 예에서 첫 번째 메뉴 항목에 액세스할 수 있는 방법은 OK glass, Show me dogs, Labrador입니다.

    <menu xmlns:android="http://schemas.android.com/apk/res/android">
        <!-- Use the constants defined in the ContextualMenus.Command enum-->
        <item
            android:id="@+id/dogs_menu_item"
            android:title="@string/show_me_dogs">
            <menu>
                <item
                    android:id="@+id/lab_menu_item"
                    android:title="@string/labrador" />
                <item
                    android:id="@+id/golden_menu_item"
                    android:title="@string/golden" />
            </menu>
        </item>
        <item
            android:id="@+id/cats_menu_item"
            android:title="@string/show_me_cats">
            <menu>
                <item
                    android:id="@+id/cheshire_menu_item"
                    android:title="@string/cheshire" />
                <item
                    android:id="@+id/calico_menu_item"
                    android:title="@string/calico" />
            </menu>
        </item>
    </menu>
    
    <menu xmlns:android="http://schemas.android.com/apk/res/android">
        <!-- Use the constants defined in the ContextualMenus.Command enum-->
        <item
            android:id="@+id/play_menu_item"
            android:title="PLAY_MUSIC" />
        <item
            android:id="@+id/pause_menu_item"
            android:title="PAUSE_MUSIC" />
    </menu>
    
  4. (선택사항) WindowUtils.FEATURE_VOICE_COMMANDS의 사용 설정 여부를 확인하여 onPreparePanel()를 재정의합니다. 사용 설정된 경우 일부 기준에 따라 특정 메뉴 항목을 추가 및 삭제하는 등 다른 로직을 통해 메뉴 시스템을 설정할 수 있습니다. 일부 기준에 따라 컨텍스트 음성 메뉴를 사용 설정 (true 반환)하거나 사용 중지(false 반환)할 수도 있습니다. 예를 들면 다음과 같습니다.

        private boolean mVoiceMenuEnabled;
        ...
        @Override
        public boolean onPreparePanel(int featureId, View view, Menu menu) {
            if (featureId == WindowUtils.FEATURE_VOICE_COMMANDS) {
            // toggle this boolean on and off based on some criteria
                return mVoiceMenuEnabled;
            }
            // Good practice to call through to super for other cases
            return super.onPreparePanel(featureId, view, menu);
        }
    

음성 및 터치 메뉴 동시에 지원

상황별 음성 명령은 기존 Android 메뉴 API를 사용하므로 이미 보유하고 있는 많은 코드와 리소스를 터치 메뉴에 재사용하면서 동시에 두 유형의 메뉴를 모두 지원할 수 있습니다.

몇 가지 방법으로 이미 확인 중인 WindowUtils.FEATURE_VOICE_COMMANDS 기능 외에 Window.FEATURE_OPTIONS_PANEL 기능을 확인한 후 로직을 추가하여 탭 같은 일부 사용자 동작에서 터치 메뉴를 열면 됩니다.

예를 들어 이전 활동 예를 변경하여 다음과 같은 터치 메뉴 지원을 추가할 수 있습니다 (변경사항은 주석 처리됨).

// 1. Check for Window.FEATURE_OPTIONS_PANEL
// to inflate the same menu resource for touch menus.
@Override
public boolean onCreatePanelMenu(int featureId, Menu menu) {
    if (featureId == WindowUtils.FEATURE_VOICE_COMMANDS ||
            featureId == Window.FEATURE_OPTIONS_PANEL) {
    ...
}

// 2. Check for Window.FEATURE_OPTIONS_PANEL
// to handle touch menu item selections.
@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
    if (featureId == WindowUtils.FEATURE_VOICE_COMMANDS ||
            featureId == Window.FEATURE_OPTIONS_PANEL) {
    ...
}

이러한 변경을 통해 ok glass를 탭하거나 말하여 메뉴를 표시할 수 있습니다.

개발용으로 목록에 없는 음성 명령 사용하기

Glassware를 배포하려면 VoiceTriggers.Command에서 승인된 기본 음성 명령과 ContextualMenus.Command에서 승인된 상황별 음성 명령어를 사용해야 합니다.

GDK에서 사용할 수 없는 음성 명령을 사용하려면 AndroidManifest.xml 파일에서 Android 권한을 요청하면 됩니다.

<uses-permission
     android:name="com.google.android.glass.permission.DEVELOPMENT" />

비공개 기본 음성 명령 사용

  1. 음성 트리거의 이름을 정의하는 문자열 값을 res/values/strings.xml에 선언합니다. 원하는 경우 Glass 소프트웨어를 시작하기 전에 음성 인식 Glass 소프트웨어 표시를 위한 음성 메시지를 선언합니다.

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string name="glass_voice_trigger">read me a story</string>
        <string name="glass_voice_prompt">what story?</string>
    </resources>
    
  2. res/xml/<my_voice_trigger>.xml에서 음성 트리거의 XML 리소스를 만듭니다. 미등록 음성 명령의 경우 승인된 음성 명령에 사용되는 command 속성 대신 keyword 속성을 사용해야 합니다. keyword 속성은 음성 명령을 정의하는 문자열 리소스에 대한 참조여야 합니다. 활동 또는 서비스를 즉시 시작하는 간단한 음성 트리거의 경우 trigger 요소를 지정하기만 하면 됩니다.

    <?xml version="1.0" encoding="utf-8"?>
    <trigger keyword="@string/glass_voice_trigger" />
    

    활동 또는 서비스를 시작하기 전에 사용자에게 추가 문구를 말하도록 하는 음성 트리거를 만들려면 입력 요소도 포함합니다.

    <?xml version="1.0" encoding="utf-8"?>
    <trigger keyword="@string/glass_voice_trigger">
        <input prompt="@string/glass_voice_prompt" />
    </trigger>
    

미등록 문맥 음성 명령 사용

메뉴 항목을 만들 때 메뉴 항목의 제목에 텍스트를 사용하세요. 예를 들면 다음과 같습니다.

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Use the constants defined in the ContextualMenus.Command enum-->
    <item
        android:id="@+id/pizza_menu_item"
        android:title="@string/find_pizza" />
</menu>

음성 인식 시작


음성 인식 Glass 소프트웨어는 사용자가 말할 때까지 기다린 후 스크립트 작성 텍스트를 반환합니다. 활동을 시작하려면 다음 단계를 따르세요.

  1. ACTION_RECOGNIZE_SPEECH 인텐트로 startActivityForResult()를 호출합니다. 활동을 시작할 때 다음과 같은 추가 인텐트가 지원됩니다.
  2. EXTRA_RESULTS 인텐트 extra에서 변환된 텍스트를 수신하도록 onActivityResult() 콜백을 재정의합니다. 이 콜백은 사용자가 말하기를 완료하면 호출됩니다.

    private static final int SPEECH_REQUEST = 0;
    
    private void displaySpeechRecognizer() {
        Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
        startActivityForResult(intent, SPEECH_REQUEST);
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode,
            Intent data) {
        if (requestCode == SPEECH_REQUEST && resultCode == RESULT_OK) {
            List<String> results = data.getStringArrayListExtra(
                    RecognizerIntent.EXTRA_RESULTS);
            String spokenText = results.get(0);
            // Do something with spokenText.
        }
        super.onActivityResult(requestCode, resultCode, data);
    }