/** * Global Sensor Networks (GSN) Source Code * Copyright (c) 2006-2014, Ecole Polytechnique Federale de Lausanne (EPFL) * <p/> * This file is part of GSN. * <p/> * GSN is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * <p/> * GSN is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * <p/> * You should have received a copy of the GNU General Public License * along with GSN. If not, see <http://www.gnu.org/licenses/>. * <p/> * File: gsn-tiny/src/tinygsn/model/wrappers/AndroidActivityRecognitionWrapper.java * * @author Marc Schaer */ package tinygsn.model.wrappers; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.util.Log; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks; import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener; import com.google.android.gms.location.ActivityRecognition; import com.google.android.gms.location.ActivityRecognitionResult; import com.google.android.gms.location.DetectedActivity; import java.io.Serializable; import java.util.ArrayList; import tinygsn.beans.DataField; import tinygsn.beans.DataTypes; import tinygsn.beans.StaticData; import tinygsn.beans.StreamElement; import tinygsn.beans.WrapperConfig; import tinygsn.services.WrapperService; public class AndroidActivityRecognitionWrapper extends AbstractWrapper implements ConnectionCallbacks, OnConnectionFailedListener { private static final String[] FIELD_NAMES = new String[]{"type", "confidence"}; private static final Byte[] FIELD_TYPES = new Byte[]{DataTypes.DOUBLE, DataTypes.DOUBLE}; private static final String[] FIELD_DESCRIPTION = new String[]{"Type", "Confidence"}; private static final String[] FIELD_TYPES_STRING = new String[]{"double", "double"}; private static final String TAG = "ActivityRecognitionWrap"; private Context context = StaticData.globalContext; private GoogleApiClient mGoogleApiClient = null; private AbstractWrapper w = null; public AndroidActivityRecognitionWrapper() { } public AndroidActivityRecognitionWrapper(WrapperConfig wc) { super(wc); } private void connectGoogleAPI() { mGoogleApiClient = new GoogleApiClient.Builder(context) .addApi(ActivityRecognition.API) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .build(); mGoogleApiClient.connect(); Log.d(TAG, "Connected to google API"); } private void disconnectGoogleAPI() { mGoogleApiClient.disconnect(); mGoogleApiClient = null; Log.d(TAG, "Disconnected from google API"); } @Override public DataField[] getOutputStructure() { ArrayList<DataField> output = new ArrayList<DataField>(); for (int i = 0; i < FIELD_NAMES.length; i++) output.add(new DataField(FIELD_NAMES[i], FIELD_TYPES_STRING[i], FIELD_DESCRIPTION[i])); return output.toArray(new DataField[]{}); } @Override public String[] getFieldList() { return FIELD_NAMES; } @Override public Byte[] getFieldType() { return FIELD_TYPES; } @Override public void runOnce() { if (!isRunning()) { disconnectGoogleAPI(); } else { if (mGoogleApiClient == null) { connectGoogleAPI(); } updateWrapperInfo(); if (ActivityRecognitionResult.hasResult(ActivityRecognitionService.getIntent())) { // Get the update ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(ActivityRecognitionService.getIntent()); DetectedActivity mostProbableActivity = result.getMostProbableActivity(); // Get the confidence % (probability) double confidence = mostProbableActivity.getConfidence(); // Get the type double activityType = mostProbableActivity.getType(); /* types: * DetectedActivity.IN_VEHICLE * DetectedActivity.ON_BICYCLE * DetectedActivity.ON_FOOT * DetectedActivity.STILL * DetectedActivity.UNKNOWN * DetectedActivity.TILTING */ StreamElement streamElement = new StreamElement(FIELD_NAMES, FIELD_TYPES, new Serializable[]{activityType, confidence}); postStreamElement(streamElement); } else { Log.d(TAG, "No results for AndroidActivityRecognition"); } } } @Override public void onConnected(Bundle bundle) { PendingIntent mActivityReconPendingIntent = PendingIntent .getService(context, 0, ActivityRecognitionService.getIntent(), PendingIntent.FLAG_UPDATE_CURRENT); Log.d(TAG, "connected to ActivityRecognition"); ActivityRecognition.ActivityRecognitionApi.requestActivityUpdates(mGoogleApiClient, 0, mActivityReconPendingIntent); } @Override public void onConnectionSuspended(int cause) { Log.d(TAG, "Suspended to ActivityRecognition"); } @Override public void onConnectionFailed(ConnectionResult result) { Log.d(TAG, "Not connected to ActivityRecognition"); } public static class ActivityRecognitionService extends WrapperService { private static Intent mIntent = null; public ActivityRecognitionService() { super("activityRecognitionService"); } @Override protected void onHandleIntent(Intent intent) { mIntent = intent; super.onHandleIntent(intent); try { w = StaticData.getWrapperByName(config.getWrapperName()); if (!w.isRunning()) { w.runOnce(); } } catch (Exception e1) { } } private static Intent getIntent() { return ActivityRecognitionService.mIntent; } public static String getType(double 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 ""; } } @Override public Class<? extends WrapperService> getSERVICE() { return ActivityRecognitionService.class; } }