com.updetector.google.activityrecognition.ActivityRecognitionIntentService.java Source code

Java tutorial

Introduction

Here is the source code for com.updetector.google.activityrecognition.ActivityRecognitionIntentService.java

Source

/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.updetector.google.activityrecognition;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.R.integer;
import android.app.IntentService;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.location.Location;
import android.provider.Settings;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;

import com.updetector.Constants;
import com.updetector.MainActivity;
import com.updetector.R;
import com.updetector.R.drawable;
import com.updetector.R.string;
import com.updetector.managers.DetectionNotificationManager;
import com.updetector.managers.LocationManagerWrapper;
import com.updetector.managers.LogManager;
import com.google.android.gms.location.ActivityRecognitionResult;
import com.google.android.gms.location.DetectedActivity;

/**
 * Service that receives ActivityRecognition updates. It receives updates
 * in the background, even if the main Activity is not visible.
 */
public class ActivityRecognitionIntentService extends IntentService {
    // TAG for the class;
    private static final String LOG_TAG = ActivityRecognitionIntentService.class.getSimpleName();

    // Delimits the timestamp from the log info
    private static final String LOG_DELIMITER = " ";

    // A date formatter
    private SimpleDateFormat mDateFormat;

    // Store the app's shared preferences repository
    private SharedPreferences mPrefs;

    // An instance of the notificaiton manager
    private DetectionNotificationManager mNotificationManagerWrapper;

    // The location manager object
    private LocationManagerWrapper mLocationManagerWrapper;

    public ActivityRecognitionIntentService() {
        // Set the label for the service's background thread
        super("ActivityRecognitionIntentService");
    }

    /**
     * Called when a new activity detection update is available.
     */
    @Override
    protected void onHandleIntent(Intent intent) {

        // 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(Constants.APP_NAME, getString(R.string.date_format_error));
        }

        // Format the timestamp according to the pattern, then localize the pattern
        mDateFormat.applyPattern("yyyy-MM-dd HH:mm:ss:SSS");
        mDateFormat.applyLocalizedPattern(mDateFormat.toLocalizedPattern());

        mNotificationManagerWrapper = DetectionNotificationManager.getInstance(this);
        mLocationManagerWrapper = LocationManagerWrapper.getInstance(this);

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

            // 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 confidence percentage for the most probable activity
            int confidenceOfMostProbableActivity = mostProbableActivity.getConfidence();

            int confidenceOfOnFoot = result.getActivityConfidence(DetectedActivity.ON_FOOT);
            int confidenceOfInVehicle = result.getActivityConfidence(DetectedActivity.IN_VEHICLE);

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

            Location curLocation = null;

            /*if (
               // If the current type is "moving"
               isMoving(activityType)
               &&
               // The activity has changed from the previous activity
               activityChanged(activityType)
               // The confidence level for the current activity is > 50%
               && (confidence >= 50)) {
                
            // Notify the user
            mNotificationManagerWrapper.sendTextNotification("Please enable the GPS.");
            }
            if(isFromOnFoottoInVehicle(mostProbableActivity)){
               //request a location fix
               curLocation=mLocationManagerWrapper.getLatestLocation();
            }
            if(isFromInVehicletoOnFoot(mostProbableActivity)){
               //request a location fix
               curLocation= mLocationManagerWrapper.getLatestLocation();
            }
                
             // Save the current state 
             Editor editor = mPrefs.edit();
             editor.putInt(Constants.KEY_PREVIOUS_ACTIVITY_TYPE, activityType);
             editor.commit();
                 
             // Log the update
             logActivityRecognitionResult(result, curLocation);*/

            sendActivityUpdateToMainActivity(mostProbableActivityType, getNameFromType(mostProbableActivityType),
                    confidenceOfMostProbableActivity, confidenceOfOnFoot, confidenceOfInVehicle);
        }
    }

    private void sendActivityUpdateToMainActivity(int mostProbableActivityTypeInt, String mobilityState,
            int confidenceOfMostProbableActivity, int confidenceOfOnFoot, int confidenceOfInVehicle) {
        Log.e(LOG_TAG, "Send out the google activity update back to main activity\n " + "most likely activity:  "
                + mobilityState + "   confidence: " + confidenceOfMostProbableActivity);
        Intent ackIntent = new Intent(Constants.GOOGLE_ACTIVITY_RECOGNITION_UPDATE);
        ackIntent.putExtra(Constants.GOOGLE_ACT_UPDATE_MOST_LIKELY_ACTIVITY_TYPE, mobilityState);
        ackIntent.putExtra(Constants.GOOGLE_ACT_UPDATE_MOST_LIKELY_ACTIVITY_TYPE_INT, mostProbableActivityTypeInt);
        ackIntent.putExtra(Constants.GOOGLE_ACT_UPDATE_MOST_LIKELY_ACTIVITY_CONFIDENCE,
                (float) confidenceOfMostProbableActivity);
        ackIntent.putExtra(Constants.GOOGLE_ACT_UPDATE_ON_FOOT_ACTIVITY_CONFIDENCE, (float) confidenceOfOnFoot);
        ackIntent.putExtra(Constants.GOOGLE_ACT_UPDATE_IN_VEHICLE_ACTIVITY_CONFIDENCE,
                (float) confidenceOfInVehicle);

        LocalBroadcastManager.getInstance(this).sendBroadcast(ackIntent);
    }

    /**
     * Tests to see if the activity has changed
     *
     * @param currentType The current activity type
     * @return true if the user's current activity is different from the previous most probable
     * activity; otherwise, false.
     */
    private boolean activityChanged(int currentType) {
        if (!mPrefs.contains(Constants.KEY_PREVIOUS_ACTIVITY_TYPE))
            return false;

        // Get the previous type, otherwise return the "unknown" type
        int previousType = mPrefs.getInt(Constants.KEY_PREVIOUS_ACTIVITY_TYPE, DetectedActivity.UNKNOWN);

        // If the previous type isn't the same as the current type, the activity has changed
        if (previousType != currentType) {
            return true;

            // Otherwise, it hasn't.
        } else {
            return false;
        }
    }

    private boolean isFromOnFoottoInVehicle(DetectedActivity newDetectedActivity) {
        // Get the previous type, otherwise return the "unknown" type
        int previousType = mPrefs.getInt(Constants.KEY_PREVIOUS_ACTIVITY_TYPE, DetectedActivity.UNKNOWN);

        // If the previous type isn't the same as the current type, the activity has changed
        if (previousType == DetectedActivity.ON_FOOT
                && newDetectedActivity.getType() == DetectedActivity.IN_VEHICLE) {
            return true;
        }

        return false;
    }

    private boolean isFromInVehicletoOnFoot(DetectedActivity newDetectedActivity) {

        int curType = newDetectedActivity.getType();

        Editor editor = mPrefs.edit();
        //in_vehicle to on_foot
        if (curType == DetectedActivity.ON_FOOT && mPrefs.getInt(Constants.KEY_PREVIOUS_ACTIVITY_TYPE,
                DetectedActivity.UNKNOWN) == DetectedActivity.IN_VEHICLE) {
            editor.putInt(Constants.KEY_PREVIOUS_CONSECUTIVE_ON_FOOT_COUNT, 1);
        } else {
            //two consecutive on_foot
            if (mPrefs.contains(Constants.KEY_PREVIOUS_CONSECUTIVE_ON_FOOT_COUNT)
                    && curType == DetectedActivity.ON_FOOT && mPrefs.getInt(Constants.KEY_PREVIOUS_ACTIVITY_TYPE,
                            DetectedActivity.UNKNOWN) == DetectedActivity.ON_FOOT) {

                int cnt = mPrefs.getInt(Constants.KEY_PREVIOUS_CONSECUTIVE_ON_FOOT_COUNT, 1);
                editor.putInt(Constants.KEY_PREVIOUS_CONSECUTIVE_ON_FOOT_COUNT, cnt + 1);
                //found 3 consecutive on_foot activities
                if (cnt + 1 == 3)
                    return true;
            }
        }
        editor.commit();

        return false;
    }

    /**
     * Get a content Intent for the notification
     *
     * @return A PendingIntent that starts the device's Location Settings panel.
     */
    private PendingIntent getContentIntent() {

        // Set the Intent action to open Location Settings
        Intent gpsIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);

        // Create a PendingIntent to start an Activity
        return PendingIntent.getActivity(getApplicationContext(), 0, gpsIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    }

    /**
     * Determine if an activity means that the user is moving.
     *
     * @param type The type of activity the user is doing (see DetectedActivity constants)
     * @return true if the user seems to be moving from one location to another, otherwise false
     */
    private boolean isMoving(int type) {
        switch (type) {
        // These types mean that the user is probably not moving
        case DetectedActivity.STILL:
        case DetectedActivity.TILTING:
        case DetectedActivity.UNKNOWN:
            return false;
        default:
            return true;
        }
    }

    /**
     * Write the activity recognition update to the log file
        
     * @param result The result extracted from the incoming Intent
     */
    private void logActivityRecognitionResult(ActivityRecognitionResult result, Location curLocation) {
        // Get all the probably activities from the updated result

        DetectedActivity mostLikelyActivity = result.getMostProbableActivity();
        /*for (DetectedActivity detectedActivity : result.getProbableActivities()) {
            
        // Get the activity type, confidence level, and human-readable name
        int confidence = detectedActivity.getConfidence();
        if(confidence>maxConfidence){
           confidence=maxConfidence;
           mostLikelyActivity=detectedActivity;
        }
        }*/
        // Make a timestamp
        String timeStamp = mDateFormat.format(new Date());

        String activityName = getNameFromType(mostLikelyActivity.getType());

        // Get the current log file or create a new one, then log the activity
        String msg = timeStamp + LOG_DELIMITER
                + getString(R.string.log_message, activityName, mostLikelyActivity.getConfidence());
        if (curLocation != null)
            msg += LOG_DELIMITER + curLocation.toString();

        LogManager.getInstance(getApplicationContext()).log(msg, Constants.LOG_FILE_TYPE[1]);
        Log.d(LOG_TAG, msg);
    }

    /**
     * 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 "on_bicycle";
        case DetectedActivity.ON_FOOT:
            return "on_foot";
        case DetectedActivity.STILL:
            return "still";
        case DetectedActivity.UNKNOWN:
            return "unknown";
        case DetectedActivity.TILTING:
            return "tilting";
        }
        return "unknown";
    }
}