Android Open Source - ActivityTracker Background Service






From Project

Back to project page ActivityTracker.

License

The source code is released under:

GNU General Public License

If you think the Android project ActivityTracker listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package biz.bokhorst.activitytracker;
// ww w  .ja  v  a  2s .  c  o m
/*
 Copyright 2014 Marcel Bokhorst
 All Rights Reserved

 This program 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.

 This program 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.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks;
import com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener;
import com.google.android.gms.location.ActivityRecognitionClient;
import com.google.android.gms.location.ActivityRecognitionResult;
import com.google.android.gms.location.DetectedActivity;

import android.annotation.TargetApi;
import android.app.AlarmManager;
import android.app.IntentService;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;

import biz.bokhorst.activitytracker.DatabaseHelper.ActivityData;
import biz.bokhorst.activitytracker.DatabaseHelper.ActivityRecord;

public class BackgroundService extends IntentService {
  private static String TAG = "ATRACKER";

  private static PendingIntent watchdogPendingIntent = null;
  private static ActivityRecognitionClient activityRecognitionClient = null;
  private static PendingIntent locationPendingIntent = null;
  private static boolean stepCounterRegistered = false;

  public static final String ACTION_INIT = "Init";
  public static final String ACTION_WATCHDOG = "Watchdog";
  public static final String ACTION_LOCATION = "Location";
  public static final String ACTION_STEPS = "Steps";

  public BackgroundService() {
    super(TAG);
  }

  @Override
  protected void onHandleIntent(Intent intent) {
    // Handle intent
    try {
      if (ActivityRecognitionResult.hasResult(intent))
        handleActivityRecognition(intent);
      else if (ACTION_INIT.equals(intent.getAction()))
        handleInit(intent);
      else if (ACTION_WATCHDOG.equals(intent.getAction()))
        handleWatchdog(intent);
      else if (ACTION_LOCATION.equals(intent.getAction()))
        handleLocationChanged(intent);
      else if (ACTION_STEPS.equals(intent.getAction()))
        handleStepsChanged(intent);
      else
        Log.w(TAG, "Unknown intent=" + intent);
    } catch (Throwable ex) {
      Log.e(TAG, ex.toString());
    } finally {
      // Start trackers
      ensureWatchdog();
      ensureActivityRecognition();
      ensureLocationUpdates();
      ensureStepCounting();
    }
  }

  // Watchdog setup

  private void ensureWatchdog() {
    if (watchdogPendingIntent == null) {
      // Build pending intent
      Intent watchdogIntent = new Intent(this, BackgroundService.class);
      watchdogIntent.setAction(BackgroundService.ACTION_WATCHDOG);
      watchdogPendingIntent = PendingIntent.getService(this, 0,
          watchdogIntent, PendingIntent.FLAG_UPDATE_CURRENT);

      // Start watchdog
      startWatchdog();
      Log.w(TAG, "Watchdog started");
    }
  }

  private void startWatchdog() {
    // TODO: get settings
    long interval = 10L * 60L * 1000L;

    // Start watchdog timer
    AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
    long watchdogTime = SystemClock.elapsedRealtime() + interval;
    alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, watchdogTime,
        watchdogPendingIntent);
  }

  // Activity recognition setup

  private void ensureActivityRecognition() {
    // Check for Play services
    int result = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
    if (result == ConnectionResult.SUCCESS) {
      // Create activity recognition client
      if (activityRecognitionClient == null) {
        PlayServicesListener listener = new PlayServicesListener();
        activityRecognitionClient = new ActivityRecognitionClient(this,
            listener, listener);
      }

      // Connect to Play services
      if (!activityRecognitionClient.isConnected()
          && !activityRecognitionClient.isConnecting()) {
        Log.w(TAG, "Connecting to activity recognition client");
        activityRecognitionClient.connect();
      }
    } else
      Log.w(TAG, "Play services not available, result=" + result);
  }

  private class PlayServicesListener implements ConnectionCallbacks,
      OnConnectionFailedListener {
    @Override
    public void onConnectionFailed(ConnectionResult result) {
      Log.e(TAG,
          "Connection to Play services failed, result="
              + result.getErrorCode());
    }

    @Override
    public void onConnected(Bundle hint) {
      // TODO: settings
      long interval = 60L * 1000L;

      // Build pending intent
      Intent activityIntent = new Intent(BackgroundService.this,
          BackgroundService.class);
      PendingIntent activityCallbackIntent = PendingIntent.getService(
          BackgroundService.this, 0, activityIntent,
          PendingIntent.FLAG_UPDATE_CURRENT);

      // Request activity updates
      activityRecognitionClient.requestActivityUpdates(interval,
          activityCallbackIntent);
      Log.w(TAG, "Requested activity updates");
    }

    @Override
    public void onDisconnected() {
      Log.w(TAG, "Disconnected from Play services");
    }
  }

  // Location updates setup

  private void ensureLocationUpdates() {
    if (locationPendingIntent == null) {
      // TODO: settings
      int locationAccuracy = Criteria.POWER_LOW;
      long minTime = 60L * 1000L;
      float minDistance = 50.0F;

      // Build pending intent
      Intent locationIntent = new Intent(this, BackgroundService.class);
      locationIntent.setAction(BackgroundService.ACTION_LOCATION);
      locationPendingIntent = PendingIntent.getService(this, 0,
          locationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

      // Request location updates
      LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
      locationManager.removeUpdates(locationPendingIntent);
      Criteria criteria = new Criteria();
      criteria.setAccuracy(locationAccuracy);
      locationManager.requestLocationUpdates(minTime, minDistance,
          criteria, locationPendingIntent);
      Log.w(TAG, "Requested location updates");
    }
  }

  // Step counter setup

  @TargetApi(Build.VERSION_CODES.KITKAT)
  private void ensureStepCounting() {
    if (getPackageManager().hasSystemFeature(
        PackageManager.FEATURE_SENSOR_STEP_COUNTER)) {
      if (!stepCounterRegistered) {
        // TODO: settings
        int stepDelay = SensorManager.SENSOR_DELAY_NORMAL;

        // Request step counting
        SensorManager sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        Sensor countSensor = sensorManager
            .getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
        sensorManager.registerListener(new SensorListener(),
            countSensor, stepDelay);
        stepCounterRegistered = true;
        Log.w(TAG, "Step counter listener registered");
      }
    } else
      Log.w(TAG, "No hardware step counter");
  }

  private class SensorListener implements SensorEventListener {
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
      // Ignored
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
      if (event.sensor.getType() == Sensor.TYPE_STEP_COUNTER) {
        int steps = (int) event.values[0];
        Log.w(TAG, "Steps changed, steps=" + steps);
        Intent intentSteps = new Intent(BackgroundService.this,
            BackgroundService.class);
        intentSteps.setAction(ACTION_STEPS);
        intentSteps.putExtra(ACTION_STEPS, steps);
        startService(intentSteps);
      }
    }
  }

  // Logic

  private void handleInit(Intent intent) {
    Log.w(TAG, "Init");
  }

  private void handleWatchdog(Intent intent) {
    Log.w(TAG, "Watchdog");

    // Start watchdog
    startWatchdog();
  }

  private void handleActivityRecognition(Intent intent) {
    DatabaseHelper dh = new DatabaseHelper(this);

    // Register activity
    ActivityRecognitionResult result = ActivityRecognitionResult
        .extractResult(intent);
    DetectedActivity mostProbableActivity = result
        .getMostProbableActivity();
    Log.w(TAG, "Activity type=" + mostProbableActivity.getType()
        + " confidence=" + mostProbableActivity.getConfidence());

    boolean newActivity = false;
    if (mostProbableActivity.getType() != DetectedActivity.TILTING)
      newActivity = dh.registerActivityRecord(new ActivityRecord(result
          .getTime(), mostProbableActivity.getType()));
    for (DetectedActivity activity : result.getProbableActivities())
      dh.registerActivityData(new ActivityData(result.getTime(), activity
          .getType(), activity.getConfidence()));

    // Get last know location
    if (newActivity) {
      LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
      Location location = locationManager
          .getLastKnownLocation(LocationManager.PASSIVE_PROVIDER);
      dh.registerActivityData(new ActivityData(
          ActivityData.TYPE_TRACKPOINT, location));
    }
  }

  private void handleLocationChanged(Intent intent) {
    // Get location
    Location location = (Location) intent.getExtras().get(
        LocationManager.KEY_LOCATION_CHANGED);

    // Register location
    Log.w(TAG, "Location=" + location);
    new DatabaseHelper(this).registerActivityData(new ActivityData(
        ActivityData.TYPE_TRACKPOINT, location));
  }

  private void handleStepsChanged(Intent intent) {
    // TODO: setting
    int minStepDelta = 10;

    // TODO: shared preference
    SharedPreferences prefs = getSharedPreferences("activity",
        Context.MODE_MULTI_PROCESS);

    // Get steps
    int steps = intent.getIntExtra(ACTION_STEPS, -1);
    int last = prefs.getInt("Steps", 0);
    int delta = steps - last;
    Log.w(TAG, "Steps=" + steps + " Delta=" + delta + " Register="
        + (delta >= minStepDelta));

    // Register steps
    if (delta >= minStepDelta) {
      new DatabaseHelper(this).registerActivityData(new ActivityData(
          delta));

      SharedPreferences.Editor editor = prefs.edit();
      editor.putInt("Steps", steps);
      editor.commit();
    }
  }
}




Java Source Code List

biz.bokhorst.activitytracker.ActivityMain.java
biz.bokhorst.activitytracker.BackgroundService.java
biz.bokhorst.activitytracker.BootReceiver.java
biz.bokhorst.activitytracker.DatabaseHelper.java
biz.bokhorst.activitytracker.GPXFileWriter.java
org.xmlrpc.android.Base64Coder.java
org.xmlrpc.android.IXMLRPCSerializer.java
org.xmlrpc.android.MethodCall.java
org.xmlrpc.android.Tag.java
org.xmlrpc.android.XMLRPCClient.java
org.xmlrpc.android.XMLRPCCommon.java
org.xmlrpc.android.XMLRPCException.java
org.xmlrpc.android.XMLRPCFault.java
org.xmlrpc.android.XMLRPCSerializable.java
org.xmlrpc.android.XMLRPCSerializer.java
org.xmlrpc.android.XMLRPCServer.java