Google Glass: есть ли способ запустить распознавание речи из службы пользовательского интерфейса?

У меня есть стеклянное приложение, использующее LiveCards. Таким образом, у меня нет явно запущенных действий, а просто фоновая служба, которая взаимодействует с LiveCard для получения информации. В какой-то момент я хотел бы вызвать голосовой ввод. Проблема в том, что примеры кода говорят вам использовать startActivityForResult, это не то, что я могу сделать из службы. Итак, есть ли другой способ поднять это, или я не могу сделать это в моей текущей конфигурации?


person kolosy    schedule 15.01.2014    source источник
comment
Обычно принятые шаблоны проектирования Android требуют, чтобы любое взаимодействие с пользователем вовлекало пользователя (извините, если это констатация очевидного). Обычно это означает использование Activity, с которым пользователь может взаимодействовать, или, по крайней мере, использование системы Notification, когда дело доходит до использования Service. Принимая во внимание, что Android-устройство может делать много вещей в данный момент времени, я бы подумал, что одно или другое из них должно быть обязательным для соответствия принятым шаблонам проектирования.   -  person Squonk    schedule 16.01.2014
comment
Я понимаю и согласен. Проблема в том, что GDK вводит этот новый шаблон LiveCard, который частично пассивен, частично активен. В результате возникает небольшая путаница в том, как это сделать правильно.   -  person kolosy    schedule 16.01.2014
comment
Можете ли вы описать, какое взаимодействие вы хотите вызвать для запуска распознавателя речи? Вы хотите запустить распознаватель из отложенного намерения, связанного с действием карты, или что-то еще?   -  person Tony Allevato    schedule 16.01.2014
comment
Я хотел бы использовать распознаватель в качестве подсказки. Передайте приглашение через EXTRA_PROMPT, а затем получите уведомление о том, что пользователь сказал в ответ. Ожидающее намерение не сработало бы для меня, потому что это не ответ на выбор живой карты, это то, что происходит в службе, и я хочу, чтобы взаимодействие было свободным от рук.   -  person kolosy    schedule 16.01.2014
comment
почему оценка -1? ... на ответ на любимый вопрос?   -  person kolosy    schedule 25.02.2014


Ответы (1)


У меня тоже была эта проблема, а не с речевым вводом, но мне нужно было запустить действие, чтобы получить информацию для отображения на живой карте «низкочастотного рендеринга» без предварительного вызова пользователем меню. Я думаю, вы могли бы использовать действие, чтобы получить текстовый ввод, а затем отправить его обратно в службу.

Большая часть информации о том, как связать службу, получена с http://developer.android.com/guide/components/bound-services.html

MainService Это служба, которая запускается командой "ок, стекло,..." В макете есть только один TextView с текстом идентификатора.

public class MainService extends Service {

    private static final String LIVE_CARD_TAG = "my_card";

    private final IBinder mBinder = new LocalBinder();

    LiveCard mLiveCard;
    TimelineManager mTimelineManager;
    RemoteViews mViews;

    @Override
    public void onCreate() {
        super.onCreate();
        mTimelineManager = TimelineManager.from(this);
    } 

    public class LocalBinder extends Binder {
        MainService getService() {
            return MainService.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    } 

    public int onStartCommand(Intent intent, int flags, int startId) {
        mLiveCard = mTimelineManager.createLiveCard(LIVE_CARD_TAG);
        mViews = new RemoteViews(this.getPackageName(),R.layout.activity_main);
        mLiveCard.setViews(mViews);
        Intent mIntent = new Intent(this, MenuActivity.class);
        mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        mLiveCard.setAction(PendingIntent.getActivity(this, 0, mIntent, 0));
        mLiveCard.publish(LiveCard.PublishMode.REVEAL);
        new android.os.Handler().postDelayed(
                new Runnable() {
                    public void run() {
                        // run the test activity after the initial text has displayed
                        Intent testIntent = new Intent(getBaseContext(), TestActivity.class);
                        testIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        getApplication().startActivity(testIntent);
                    }
                }, 3000);
        return START_STICKY;
    }

    public void updateText(String textString) {
        mViews.setTextViewText(R.id.text,textString);
        mLiveCard.setViews(mViews);
    }

    @Override
    public void onDestroy() {
        if (mLiveCard != null && mLiveCard.isPublished()) {
            Log.d("debug", "Unpublishing LiveCard");
            mLiveCard.unpublish();
            mLiveCard = null;
        }
        super.onDestroy();
    }

}

TestActivity Это запускается после задержки из MainService и автоматически обновляет текст на активной карточке без ввода пользователем.

public class TestActivity extends Activity {

    MainService mService;
    boolean mBound = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    protected void onStart() {
        super.onStart();
        Intent intent = new Intent(this, MainService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        new android.os.Handler().postDelayed(
                new Runnable() {
                    public void run() {
                        // this crashes if run right away, so give it a little time
                        mService.updateText("Updated from TestActivity");
                        finish();
                    }
                }, 500);
    }

    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            LocalBinder binder = (LocalBinder) service;
            mService = binder.getService();
            mBound = true;
        }
        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };

}

MenuActivity Это действие, которое установлено как ожидаемое намерение для живой карты. Он вызывает меню для выхода или обновления текста при касании сенсорной панели.

public class MenuActivity extends Activity {

    MainService mService;
    boolean mBound = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    protected void onStart() {
        super.onStart();
        Intent intent = new Intent(this, MainService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        openOptionsMenu();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.stop:
                stopService(new Intent(this, MainService.class));
                return true;
            case R.id.update:
                mService.updateText("Updated from MenuActivity");
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public void onOptionsMenuClosed(Menu menu) {
        finish();
    }

    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            LocalBinder binder = (LocalBinder) service;
            mService = binder.getService();
            mBound = true;
        }
        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };
}
person Tom Kincaid    schedule 03.02.2014