ActivityRecognitionClient из библиотеки Google Play Services — «распознавание действий пользователя»

Предисловие


В одно из обновлений библиотеки Google Play Services прокрался новый компонент, который может быть очень полезен при реализации некоторого типа приложений. Имя этому компоненту — ActivityRecognitionClient.

ActivityRecognitionClient позволяет приложению получать данные о действиях пользователя. Например, приложение может определять текущее действие пользователя, к примеру ходьбу, езду в автомобиле, чтение книги, и даже езду на велосипеде.
Многие уже успели догадаться, что механизм работает за счёт сенсоров устройства. Однако не смотря на использование множества датчиков, энергопотребление компонента очень низкое, что позволяет использовать его без ограничений.

Надеюсь понятно объяснил, но для наглядности предлагаю просмотреть 4-х минутный ролик представленный компанией Google:



Реализация


Давайте приступим к реализации и набросаем пример использования, но для начала не забудьте подключить к вашему проекту библиотеку Google Play Services.

Добавим в main.xml TextView для отображения текущего действия и его точность:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:paddingBottom="20dp"
                android:paddingLeft="20dp"
                android:paddingRight="20dp"
                android:paddingTop="20dp">

    <TextView
            android:id="@+id/tvActivity"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentRight="true"
            android:text=""/>

</RelativeLayout>


Приступаем к написанию кода нашей MyActivity.java, которая должна реализовать интерфейсы GooglePlayServicesClient.ConnectionCallbacks и GooglePlayServicesClient.OnConnectionFailedListener.

public class MyActivity extends Activity implements GooglePlayServicesClient.ConnectionCallbacks,GooglePlayServicesClient.OnConnectionFailedListener


Объявляем объекты:

    private ActivityRecognitionClient activityRecognitionClient;
    private PendingIntent pIntent;
    private BroadcastReceiver receiver;
    private TextView tvActivity;


В методе onCreate инициализируем объявленные ранее объекты и проверяем наличие Google Play Services на устройстве:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        tvActivity = (TextView) findViewById(R.id.tvActivity);

        int resp = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
        if(resp == ConnectionResult.SUCCESS){
            activityRecognitionClient = new ActivityRecognitionClient(this, this, this);
            activityRecognitionClient.connect();
        }
        else {
            Toast.makeText(this, "Please install Google Play Service.", Toast.LENGTH_SHORT).show();
        }

        receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String v =  "Activity :" + intent.getStringExtra("Activity") + " " + "Confidence : " + intent.getExtras().getInt("Confidence") + "\n";
                v += tvActivity.getText();
                tvActivity.setText(v);
            }
        };

        IntentFilter filter = new IntentFilter();
        filter.addAction("com.alexche.recognitionservice.ACTIVITY_RECOGNITION_DATA");
        registerReceiver(receiver, filter);
    }


В методе onConnected связываем наш activityRecognitionClient с ActivityRecognitionService, код реализации которого будет представлен ниже:

    @Override
    public void onConnected(Bundle arg0) {
        Intent intent = new Intent(this, ActivityRecognitionService.class);
        pIntent = PendingIntent.getService(this, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
        activityRecognitionClient.requestActivityUpdates(1000, pIntent);
    }


И наконец переходим к реализации ActivityRecognitionService.java, наследующего класс IntentService:

public class ActivityRecognitionService extends IntentService


Переопределяем метод onHandleIntent:
    @Override
    protected void onHandleIntent(Intent intent) {
        if(ActivityRecognitionResult.hasResult(intent)){
            ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
            Log.i(TAG, getType(result.getMostProbableActivity().getType()) + "t" + result.getMostProbableActivity().getConfidence());
            Intent i = new Intent("com.alexche.recognitionservice.ACTIVITY_RECOGNITION_DATA");
            i.putExtra("Activity", getType(result.getMostProbableActivity().getType()) );
            i.putExtra("Confidence", result.getMostProbableActivity().getConfidence());
            sendBroadcast(i);
        }
    }


Дописываем метод getType, который возвращает нам текущее состояние:

private String getType(int type){
        if(type == DetectedActivity.UNKNOWN)
            return "Unknown";
        else if(type == DetectedActivity.IN_VEHICLE)
            return "In Vehicle";
        else if(type == DetectedActivity.ON_BICYCLE)
            return "On Bicycle";
        else if(type == DetectedActivity.ON_FOOT)
            return "On Foot";
        else if(type == DetectedActivity.STILL)
            return "Still";
        else if(type == DetectedActivity.TILTING)
            return "Tilting";
        else
            return "";
    }


Не забываем добавить разрешение в AndroidManifest.xml:

<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION"/>


Демонстрация


image
Скриншоты
image

image

image


Заключение


В принципе ActivityRecognitionClient мне показался очень забавной и полезной штукой, однако тестирование на нескольких устройствах показало, что «действие/состояние» не всегда определяется адекватно.

Надеюсь, ничего не забыл.

Если будут вопросы — спрашивайте.

Полные исходники смотрите на GitHub.
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 6

  • НЛО прилетело и опубликовало эту надпись здесь
      0
      Видео конечно забавное :)
      К слову, гугл карты сейчас умеют сами подставлять тип навигации? Ну например едешь на велосипеде, остановился и проложил маршрут. он должен автоматом выбираться для велосипедиста (там вроде как сейчас последний тип выбран)
      Вообще к слову надо именно отслеживать внутри приложения только? Я вот просто думаю — ведь по сути тот же гугл нау и так отслеживает, т.е. при установке нового приложения можно было бы просто присоединиться к логам полученным гуглнау и узнать, что например последние 2 часа человек шел пешком и он в парке, и на основании этого можно например сделать приложение которое будет предлагать интересные места, пешком поближе, на велосипеде чуть подальше, если приложение видит что использутся еще транспорт быстрый то можно еще дальше.
        0
        К слову, гугл карты сейчас умеют сами подставлять тип навигации?

        На сколько я знаю — такого пока не практикуют.

        Вообще к слову надо именно отслеживать внутри приложения только?

        Тут всё зависит от цели которую Вы преследуете. Но по мне так проще реализовать данный клиент в своём приложении, чем постоянно считывать логи с Google Now, который очень часто отключён у многих пользователей.
        +1
        За пост спасибо, но я бы все-таки порекомендовал использовать GoogleApiClient для общения с GooglePlayServices, а не создавать ActivityRecognitionClient напрямую. Негоже учить использованию deprecated APIs :)
        Также, если мне не изменяет память, в манифесте не помешает зарегистрировать «ActivityRecognitionService» иначе работать не будет ;)
        0
        Приложение к сожалению уже не собрать по вашему гайду.

        ActivityRecognitionClient переименовали в ActivityRecognition, его конструктор сделали private и убрали методы connect(), requestActivityUpdates().

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое