Activity Recognition API
Asked Answered
M

4

14

Anyone have trouble with the Activity Recognition API in the recent Google Play Services update?

I have it implemented in an app. It was working perfectly fine before the 5.0 update. Now it returns IN_VEHICLE when the user is walking or sitting still. :/

And doesn't return WALKING, RUNNING or ON_FOOT at all.

Were there any changes to the Activity Recognition API I should be aware of?

Let me know if you need any more details.

Marlomarlon answered 18/7, 2014 at 6:28 Comment(1)
The ActivityRecognitionApi is depreciated and Google advises to use the connectionless API ActivityRecognitionClient instead.Doubling
I
13

The WALKING and RUNNING activities come in as secondary activities in a list (ActivityRecognitionResult.getProbableActivities()), and you'll need to parse them out.

// Get the update
ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);

// Get the most probable activity from the list of activities in the update
DetectedActivity mostProbableActivity = result.getMostProbableActivity();

// Get the type of activity
int activityType = mostProbableActivity.getType();

if (activityType == DetectedActivity.ON_FOOT) {
    DetectedActivity betterActivity = walkingOrRunning(result.getProbableActivities());
    if (null != betterActivity)
        mostProbableActivity = betterActivity;
}

private DetectedActivity walkingOrRunning(List<DetectedActivity> probableActivities) {
    DetectedActivity myActivity = null;
    int confidence = 0;
    for (DetectedActivity activity : probableActivities) {
        if (activity.getType() != DetectedActivity.RUNNING && activity.getType() != DetectedActivity.WALKING)
            continue;

        if (activity.getConfidence() > confidence)
            myActivity = activity;
    }

    return myActivity;
}

I tested the above code this evening, both walking and running and it seemed to do fairly well. If you don't explicitly filter on only RUNNING or WALKING, you will likely get erroneous results.

Below is a full method for handling new activity results. I pulled this straight out of the sample app, and have been testing it for a couple of days with good results.

/**
 * Called when a new activity detection update is available.
 */
@Override
protected void onHandleIntent(Intent intent) {
    Log.d(TAG, "onHandleIntent");

    // Get a handle to the repository
    mPrefs = getApplicationContext().getSharedPreferences(
            Constants.SHARED_PREFERENCES, Context.MODE_PRIVATE);

    // Get a date formatter, and catch errors in the returned timestamp
    try {
        mDateFormat = (SimpleDateFormat) DateFormat.getDateTimeInstance();
    } catch (Exception e) {
        Log.e(TAG, getString(R.string.date_format_error));
    }

    // Format the timestamp according to the pattern, then localize the pattern
    mDateFormat.applyPattern(DATE_FORMAT_PATTERN);
    mDateFormat.applyLocalizedPattern(mDateFormat.toLocalizedPattern());

    // If the intent contains an update
    if (ActivityRecognitionResult.hasResult(intent)) {

        // Get the update
        ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);

        // Log the update
        logActivityRecognitionResult(result);

        // Get the most probable activity from the list of activities in the update
        DetectedActivity mostProbableActivity = result.getMostProbableActivity();

        // Get the confidence percentage for the most probable activity
        int confidence = mostProbableActivity.getConfidence();

        // Get the type of activity
        int activityType = mostProbableActivity.getType();
        mostProbableActivity.getVersionCode();

        Log.d(TAG, "acitivty: " + getNameFromType(activityType));

        if (confidence >= 50) {
            String mode = getNameFromType(activityType);

            if (activityType == DetectedActivity.ON_FOOT) {
                DetectedActivity betterActivity = walkingOrRunning(result.getProbableActivities());

                if (null != betterActivity)
                    mode = getNameFromType(betterActivity.getType());
            }

            sendNotification(mode);
        }
    }
}

private DetectedActivity walkingOrRunning(List<DetectedActivity> probableActivities) {
    DetectedActivity myActivity = null;
    int confidence = 0;
    for (DetectedActivity activity : probableActivities) {
        if (activity.getType() != DetectedActivity.RUNNING && activity.getType() != DetectedActivity.WALKING)
            continue;

        if (activity.getConfidence() > confidence)
            myActivity = activity;
    }

    return myActivity;
}

/**
 * Map detected activity types to strings
 *
 * @param activityType The detected activity type
 * @return A user-readable name for the type
 */
private String getNameFromType(int activityType) {
    switch (activityType) {
        case DetectedActivity.IN_VEHICLE:
            return "in_vehicle";
        case DetectedActivity.ON_BICYCLE:
            return RIDE;
        case DetectedActivity.RUNNING:
            return RUN;
        case DetectedActivity.WALKING:
            return "walking";
        case DetectedActivity.ON_FOOT:
            return "on_foot";
        case DetectedActivity.STILL:
            return "still";
        case DetectedActivity.TILTING:
            return "tilting";
        default:
            return "unknown";
    }
}
Included answered 23/7, 2014 at 3:46 Comment(3)
Thanks for replying. I don't need to know if the user is walking or running, I just need to know that the user is on foot. So I will leave it at that. Now all I need to do is work out why the API return IN_VEHICLE when the user is walking or sitting.Marlomarlon
Are you filtering based on confidence, and using the most probable activity? DetectedActivity mostProbableActivity = result.getMostProbableActivity(); and mostProbableActivity.getConfidence() >= 50Included
No, I am just using getMostProbableActivity(). Ill give getConfidence() a try today and let you how it goes.Marlomarlon
C
1

The main change is that ON_FOOT now returns a list of Detected Activities. Use getMostProbableActivities() instead now.

this solution gets walking or running when ON_foot get a list of Detected activities like this:

//Get the list from the result
ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
ArrayList<DetectedActivity> activityList = new ArrayList<DetectedActivity>(result.getProbableActivities());

//Get the most probable activity
getMostProbableActivity(activityList);

Now pass your list to find the most probable activity like this:

private DetectedActivity getMostProbableActivity(List<DetectedActivity> detectedActivityList)
{
DetectedActivity result = null;

//Find the most probably activity in the list
for(DetectedActivity detectedActivity : detectedActivityList)
{
    if(detectedActivity.getType() != DetectedActivity.ON_FOOT)
    {
        if(result == null)
        {
            result = detectedActivity;
        }
        else
        {
            if(result.getConfidence() < detectedActivity.getConfidence())
            {
                result = detectedActivity;
            }
        }
    }
}

return result;

}

Cantal answered 23/7, 2014 at 20:24 Comment(0)
P
1

You could try this simple ‘for loop’ to be sure that your user is driving.

for (DetectedActivity detectedActivity : detectedActivityList)
        {
           {
              if(DetectedActivity == “In_Vehicle” && result.getConfidence()> 75)
                     {
                        // output = User is Driving;
                        // Perform task 
                     }
           }
        }

Remember, for Google Play services to be sure that your user is performing a certain task, the confidence level must be greater than 75, only then you can be certain that the task is performed. Alternatively, you can try some of these free SDKs like Tranql, Neura or ContextHub which can give you better insights about your user’s activities and locations.

Petrapetracca answered 22/12, 2016 at 0:8 Comment(0)
G
0

I have Google play Services 5.0.84 it works fine with my Nexus 5. don't know what you are talking about, so it's probably bug in your code.

my application sampling constantly every minute, and returns (most of the time) the right activity. driving/walking/tilting/on foot.. every thing comes..

also, If you are not using getMostProbableActivity , then you should use it! comment: it might be indeed that in specific devices or some vendor firmwares things will break, but it's not likely.

Gibbsite answered 24/7, 2014 at 5:37 Comment(1)
I am using getMostProbableActivity(). I have not given getConfidence a try yet.Marlomarlon

© 2022 - 2024 — McMap. All rights reserved.