Activity Recognition API
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 updateActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);// Get the most probable activity from the list of activities in the updateDetectedActivity mostProbableActivity = result.getMostProbableActivity();// Get the type of activityint 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. */@Overrideprotected 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"; }}
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 resultActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);ArrayList<DetectedActivity> activityList = new ArrayList<DetectedActivity>(result.getProbableActivities());//Get the most probable activitygetMostProbableActivity(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 listfor(DetectedActivity detectedActivity : detectedActivityList){ if(detectedActivity.getType() != DetectedActivity.ON_FOOT) { if(result == null) { result = detectedActivity; } else { if(result.getConfidence() < detectedActivity.getConfidence()) { result = detectedActivity; } } }}return result;
}
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.