Android Open Source - GeoLog Background Service






From Project

Back to project page GeoLog.

License

The source code is released under:

Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUC...

If you think the Android project GeoLog 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

/*
 * Copyright (C) 2013 Jorrit "Chainfire" Jongma
 *//w  w w .j  a v a2 s  .  c  o m
 * 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 eu.chainfire.geolog.service;

import java.util.Locale;

import com.google.android.gms.common.ConnectionResult;
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 com.google.android.gms.location.LocationClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;

import eu.chainfire.geolog.Debug;
import eu.chainfire.geolog.R;
import eu.chainfire.geolog.data.Database;
import eu.chainfire.geolog.data.Database.Accuracy;
import eu.chainfire.geolog.data.Database.Activity;
import eu.chainfire.geolog.data.Database.Profile.Type;
import eu.chainfire.geolog.ui.MainActivity;
import eu.chainfire.geolog.ui.SettingsFragment;

import android.annotation.SuppressLint;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.location.Location;
import android.os.BatteryManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.PowerManager;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;

public class BackgroundService extends Service {
  public static void startService(Context context) {
    context.startService(new Intent(context.getApplicationContext(), BackgroundService.class));    
  }
  
  private static String EXTRA_ALARM_CALLBACK = "eu.chainfire.geolog.EXTRA.ALARM_CALLBACK";
  
  private volatile ServiceThread thread = null;
  private volatile PowerManager.WakeLock wakelock = null;

  private volatile NotificationManager notificationManager;
  private volatile PendingIntent notificationIntent;
  private volatile Notification.Builder notificationBuilder;
  
  @SuppressLint("NewApi")
  @Override
  public void onCreate() {
    super.onCreate();
    Debug.log("Service created");
    
    if (thread == null) {
      Debug.log("Launching thread");
      thread = new ServiceThread();
      thread.setContext(getApplicationContext());
      thread.start();
    }
    
    PowerManager pm = (PowerManager)getSystemService(POWER_SERVICE);
    wakelock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "GeoLog Wakelock");
    
    Intent i = new Intent();
    i.setAction(Intent.ACTION_MAIN);
    i.addCategory(Intent.CATEGORY_LAUNCHER);
    i.setClass(this, MainActivity.class);
    i.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_ACTIVITY_NEW_TASK);    
    notificationIntent = PendingIntent.getActivity(this, 0, i, 0);

    notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
    notificationBuilder = (new Notification.Builder(this)).
      setSmallIcon(R.drawable.ic_stat_service).
      setContentIntent(notificationIntent).
      setWhen(System.currentTimeMillis()).
      setAutoCancel(false).
      setOngoing(true).
      setContentTitle(getString(R.string.service_title)).
      setContentText(getString(R.string.service_waiting));
    
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
      notificationBuilder.setShowWhen(false);
    }
    
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
      /* quick turn off, maybe ? if added, make sure to add a button to preferences to disable these buttons
      notificationBuilder.
        setPriority(Notification.PRIORITY_MAX).
        addAction(0, "A", notificationIntent).
        addAction(0, "B", notificationIntent).
        addAction(0, "C", notificationIntent);
      */
    }
    
    updateNotification();    
  }
  
  @SuppressWarnings("deprecation")
  @SuppressLint("NewApi")
  private void updateNotification() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
      notificationManager.notify(1, notificationBuilder.build());           
    } else {
      notificationManager.notify(1, notificationBuilder.getNotification());                 
    }
  }
  
  @Override
  public void onDestroy() {    
    Debug.log("Stopping thread");
    thread.signalStop();
    try { thread.join(); } catch (Exception e) { }
    thread = null;
    
    ((NotificationManager)getSystemService(NOTIFICATION_SERVICE)).cancelAll();
    
    Debug.log("Service destroyed");
    super.onDestroy();
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    thread.processIntent(intent);
    return START_STICKY;
  }

  @Override
  public IBinder onBind(Intent intent) {
    return null;
  }
  
  private class ServiceThread extends Thread {
    private static final int FLAG_SETUP = 1;
    private static final int FLAG_ACTIVITY_UPDATE = 2;
    private static final int FLAG_LOCATION_UPDATE = 4;
    private static final int FLAG_PROFILE = 8;

    private volatile Context context = null;
    private volatile Handler handler = null;
    
    private volatile AlarmManager alarm = null;
    private volatile PendingIntent alarmCallback = null;
    
    private volatile ActivityRecognitionClient activityClient = null;
    private volatile boolean activityConnected = false;
    private volatile PendingIntent activityIntent = null;
    
    private volatile LocationClient locationClient = null;
    private volatile boolean locationConnected = false;
    
    private volatile Database.Helper databaseHelper = null;
    
    private volatile boolean metric = true;
        
    private volatile Database.Activity lastActivity = Database.Activity.UNKNOWN;
    private volatile int lastConfidence = 0;
    private volatile Location lastLocLoc = null; 
    private volatile Database.Location lastLocation = null;
    private volatile long lastLocationDuplicates = 0;
    private volatile long lastNonUnknown = 0;
    
    private volatile Database.Accuracy lastLocationAccuracy = Database.Accuracy.NONE;
    private volatile int lastLocationInterval = -1;
    private volatile int lastActivityInterval = -1;
    private volatile int lastBatteryLevel = 0;
    private volatile boolean isSegmentStart = true;
    private volatile long lastProfileUpdate = SystemClock.elapsedRealtime();
    
    private volatile long scheduledReduceAccuracyTime = 0;
    
    private volatile SharedPreferences prefs = null;    
    private volatile Database.Profile currentProfile = null;
    
    // Main thread
    
    public void setContext(Context context) {
      this.context = context;      
    }
    
    public void signalStop() {
      if (handler != null) {
        handler.post(new Runnable() {          
          @Override
          public void run() {
            Looper.myLooper().quit();
          }
        });
      }
    }
    
    public boolean processIntent(Intent intent) {
      if (intent == null) return false;
      
      if (ActivityRecognitionResult.hasResult(intent)) {
        processActivity(intent);
        return true;
      } else if (intent.hasExtra(EXTRA_ALARM_CALLBACK)) {
        processAlarmCallback(intent);
        return true;
      }      
      
      return false;
    }
    
    private void processActivity(Intent intent) {
      if (handler != null) {
        final DetectedActivity activity = ActivityRecognitionResult.extractResult(intent).getMostProbableActivity();
        if (Database.isDetectedActivityValid(activity)) {
          wakelock.acquire();
          handler.post(new Runnable() {          
            @Override
            public void run() {
              setActivity(Database.activityFromDetectedActivity(activity), activity.getConfidence());
              wakelock.release();
            }
          });
        }
      }      
    }
    
    private void processAlarmCallback(Intent intent) {
      if (handler != null) {
        wakelock.acquire();
        handler.post(new Runnable() {          
          @Override
          public void run() {
            updateListeners(0);
            wakelock.release();
          }
        });
      }            
    }
    
    // Service thread
            
    private void setActivity(Database.Activity activity, int confidence) {
      if ((activity == Activity.UNKNOWN) && (SystemClock.elapsedRealtime() < lastNonUnknown + (2 * 60 * 1000)) && (SystemClock.elapsedRealtime() > lastNonUnknown)) {
        return;
      }
      if (activity != Activity.UNKNOWN) {
        lastNonUnknown = SystemClock.elapsedRealtime();
      }
      
      Debug.log(String.format(Locale.ENGLISH, "A: %s (%d%%)", Database.activityToString(activity), confidence));
      
      lastActivity = activity;
      lastConfidence = confidence;
      updateListeners(FLAG_ACTIVITY_UPDATE);
    }
    
    private void setLocation(Location location) {
      Debug.log(String.format(Locale.ENGLISH, "L: lat=%.8f long=%.5f alt=%.5f bearing=%.4f speed=%.4f accuracy=%.2f", location.getLatitude(), location.getLongitude(), location.getAltitude(), location.getBearing(), location.getSpeed(), location.getAccuracy()));

      lastLocLoc = location;
      updateListeners(FLAG_LOCATION_UPDATE);
    }
    
    @SuppressLint("NewApi")
    private void updateListeners(int flags) {
      if (!(activityConnected && locationConnected && (currentProfile != null))) return;      

      if (currentProfile.getType() == Type.OFF) {
        stopSelf();
      }
      
      if ((flags & FLAG_PROFILE) == FLAG_PROFILE) {
        Debug.log("Profile update");
        
        lastActivity = Activity.UNKNOWN;
        lastConfidence = 0;
        
        scheduledReduceAccuracyTime = 0L;
        lastProfileUpdate = SystemClock.elapsedRealtime();
      }
      
      Accuracy originalAccuracy = lastLocationAccuracy;
      
      Database.Profile.ActivitySettings wanted = currentProfile.getActivitySettings(lastActivity);
      Database.Accuracy wantedAccuracy = wanted.getAccuracy();
      int wantedLocationInterval = wanted.getLocationInterval();
      int wantedActivityInterval = wanted.getActivityInterval();
      
      boolean allowUpdateActivityInterval = true;
      boolean allowUpdateLocationInterval = true;
      boolean allowUpdateLocationAccuracy = true;
      
      if (
          (
              (SystemClock.elapsedRealtime() > lastProfileUpdate + (90 * 1000)) || 
              (SystemClock.elapsedRealtime() < lastProfileUpdate)
          ) &&
          (currentProfile.getReduceAccuracyDelay() > 0) && 
          (
              (wantedActivityInterval > lastActivityInterval) ||
              (wantedLocationInterval > lastLocationInterval) || 
              (Database.accuracyToInt(wantedAccuracy) < Database.accuracyToInt(lastLocationAccuracy))
          )
      ) {
        long left = 0;
        
        if (scheduledReduceAccuracyTime == 0) {
          left = currentProfile.getReduceAccuracyDelay() * 1000;
          scheduledReduceAccuracyTime = SystemClock.elapsedRealtime() + left;          
          alarm.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, scheduledReduceAccuracyTime + 1000, alarmCallback);
        } else {
          left = scheduledReduceAccuracyTime - SystemClock.elapsedRealtime();
        }
        
        if (left <= 0) scheduledReduceAccuracyTime = 0L;

        allowUpdateActivityInterval = ((left <= 0) || (wantedActivityInterval < lastActivityInterval) || (lastActivityInterval == -1));
        allowUpdateLocationInterval = ((left <= 0) || (wantedLocationInterval < lastLocationInterval) || (lastLocationInterval == -1));
        allowUpdateLocationAccuracy = ((left <= 0) || (Database.accuracyToInt(wantedAccuracy) > Database.accuracyToInt(lastLocationAccuracy)));        
        
        if (!allowUpdateActivityInterval) wantedActivityInterval = lastActivityInterval;
        if (!allowUpdateLocationInterval) wantedLocationInterval = lastLocationInterval;
        if (!allowUpdateLocationAccuracy) wantedAccuracy = lastLocationAccuracy;

        if (!allowUpdateActivityInterval) Debug.log(String.format(Locale.ENGLISH, "ActivityInterval --> Delay (%ds remaining)", (left / 1000)));
        if (!allowUpdateLocationInterval) Debug.log(String.format(Locale.ENGLISH, "LocationInterval --> Delay (%ds remaining)", (left / 1000)));
        if (!allowUpdateLocationAccuracy) Debug.log(String.format(Locale.ENGLISH, "LocationAccuracy --> Delay (%ds remaining)", (left / 1000)));
      } else {
        scheduledReduceAccuracyTime = 0;
        alarm.cancel(alarmCallback);
      }
      
      if ((wantedAccuracy != lastLocationAccuracy) || (wantedLocationInterval != lastLocationInterval)) {
        String s = "NONE";
        if (wantedAccuracy == Accuracy.LOW) s = "LOW";
        if (wantedAccuracy == Accuracy.HIGH) s = "HIGH";
        Debug.log(String.format(Locale.ENGLISH, "Location --> %s %ds", s, wantedLocationInterval));
        
        locationClient.removeLocationUpdates(locationListener);
        
        if ((wantedAccuracy != Accuracy.NONE) && (wantedLocationInterval > 0)) {
          if ((lastLocationAccuracy == Accuracy.NONE) || (lastLocationInterval == 0)) isSegmentStart = true;
          
          LocationRequest req = new LocationRequest();
          req.setFastestInterval(wantedLocationInterval * 250);
          req.setInterval(wantedLocationInterval * 1000);
          if (lastLocationAccuracy == Accuracy.NONE) req.setPriority(LocationRequest.PRIORITY_NO_POWER);
          if (lastLocationAccuracy == Accuracy.LOW) req.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
          if (lastLocationAccuracy == Accuracy.HIGH) req.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
          locationClient.requestLocationUpdates(req, locationListener);
        }
        
        lastLocationAccuracy = wantedAccuracy;
        lastLocationInterval = wantedLocationInterval;
      }
      
      if (wantedActivityInterval != lastActivityInterval) {
        Debug.log(String.format(Locale.ENGLISH, "Activity --> %ds", wantedActivityInterval));

        activityClient.removeActivityUpdates(activityIntent);
        
        if ((wantedActivityInterval == 0) && (lastActivityInterval != 0)) {
          lastActivity = Activity.UNKNOWN;
          lastConfidence = 0;          
        }
        
        if (wantedActivityInterval != 0) {
          activityClient.requestActivityUpdates(wantedActivityInterval * 1000, activityIntent);
        }
        
        lastActivityInterval = wantedActivityInterval;
      }
            
      if ((flags & FLAG_ACTIVITY_UPDATE) == FLAG_ACTIVITY_UPDATE) {
        if (
            (lastLocation == null) || 
            (lastLocation.getActivity() != lastActivity) || 
            (lastLocation.getConfidence() != lastConfidence)
        ) {
          Debug.log("Activity update");
          if (lastLocation == null) {
            lastLocationDuplicates = 0;
            
            lastLocation = new Database.Location();
            lastLocation.setTime(System.currentTimeMillis());
          }
          lastLocation.setActivity(lastActivity);
          lastLocation.setConfidence(lastConfidence);
        }
      } else if ((flags & FLAG_LOCATION_UPDATE) == FLAG_LOCATION_UPDATE) {
        if (
            (lastLocation == null) ||
            (lastLocLoc == null) ||
            (lastLocation.getLatitude() != lastLocLoc.getLatitude()) || 
            (lastLocation.getLongitude() != lastLocLoc.getLongitude()) ||
            (lastLocation.getAccuracyDistance() > lastLocLoc.getAccuracy()) ||
            (lastLocation.getActivity() != lastActivity) ||
            (lastLocation.getConfidence() != lastConfidence) ||
            (lastLocation.getAccuracySetting() != originalAccuracy) ||
            (isSegmentStart)
        ) {        
          Debug.log("Location update");
          
          if (lastLocationDuplicates > 0) {
            Debug.log("Saving last duplicate (out of " + String.valueOf(lastLocationDuplicates) + ")");
            Database.Location.copy(databaseHelper, lastLocation);
          }

          lastLocationDuplicates = 0;
          
          Database.Location loc = new Database.Location();
          loc.setActivity(lastActivity);
          loc.setConfidence(lastConfidence);
          loc.setBattery(lastBatteryLevel);
          loc.setAccuracySetting(originalAccuracy);
          loc.isSegmentStart(isSegmentStart);
          loc.loadFromLocation(lastLocLoc);
          Debug.log("Saved to database: " + String.valueOf(loc.saveToDatabase(databaseHelper)));
        
          lastLocation = loc;
          isSegmentStart = false;
        } else if (
            (lastLocation != null) &&
            (lastLocLoc != null)
        ) {
          lastLocationDuplicates++;

          lastLocation.setActivity(lastActivity);
          lastLocation.setConfidence(lastConfidence);
          lastLocation.setBattery(lastBatteryLevel);
          lastLocation.setAccuracySetting(originalAccuracy);
          lastLocation.isSegmentStart(isSegmentStart);
          lastLocation.loadFromLocation(lastLocLoc);
        }
      }
        
      if (lastLocation != null) {
        notificationBuilder.
          setWhen(lastLocation.getTime()).
          setContentText(String.format(Locale.ENGLISH, "%s ~ %d%% / %.5f, %.5f ~ %.0f%s", Database.activityToString(lastLocation.getActivity()), lastLocation.getConfidence(), lastLocation.getLatitude(), lastLocation.getLongitude(), metric ? lastLocation.getAccuracyDistance() : lastLocation.getAccuracyDistance() * SettingsFragment.METER_FEET_RATIO, metric ? "m" : "ft"));
        
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
          notificationBuilder.setShowWhen(true);
        }
          
        updateNotification();
      }
    }
    
    private ConnectionCallbacks activityConnectionCallbacks = new ConnectionCallbacks() {
      @Override
      public void onConnected(Bundle arg0) {
        Debug.log("ActivityRecognitionClient connected");

        activityConnected = true;
        
        updateListeners(FLAG_SETUP);
      }
      
      @Override
      public void onDisconnected() {
        Debug.log("ActivityRecognitionClient disconnected");

        activityConnected = false;
      }        
    };
    
    private OnConnectionFailedListener activityConnectionFailed = new OnConnectionFailedListener() {      
      @Override
      public void onConnectionFailed(ConnectionResult arg0) {
        Debug.log("ActivityRecognitionClient connection failed");

        activityConnected = false;        
        signalStop();
      }
    };
    
    private LocationListener locationListener = new LocationListener() {      
      @Override
      public void onLocationChanged(Location arg0) {
        wakelock.acquire();
        try {
          setLocation(arg0);
        } finally {
          wakelock.release();
        }
      }
    };

    private ConnectionCallbacks locationConnectionCallbacks = new ConnectionCallbacks() {
      @Override
      public void onConnected(Bundle arg0) {
        Debug.log("LocationClient connected");
        
        locationConnected = true;
        
        updateListeners(FLAG_SETUP);        
      }
      
      @Override
      public void onDisconnected() {
        Debug.log("LocationClient disconnected");
        
        locationConnected = false;
      }        
    };
    
    private OnConnectionFailedListener locationConnectionFailed = new OnConnectionFailedListener() {      
      @Override
      public void onConnectionFailed(ConnectionResult arg0) {
        Debug.log("LocationClient connection failed");

        locationConnected = false;      
        signalStop();
      }
    };
    
    private BroadcastReceiver databaseUpdated = new BroadcastReceiver() {      
      @Override
      public void onReceive(Context context, Intent intent) {
        if (
            (currentProfile != null) &&
            (intent != null) &&
            intent.hasExtra(Database.Helper.EXTRA_TABLE) &&
            intent.getStringExtra(Database.Helper.EXTRA_TABLE).equals(Database.Profile.TABLE_NAME) &&
            intent.hasExtra(Database.Helper.EXTRA_ID) &&
            (intent.getLongExtra(Database.Helper.EXTRA_ID, 0) == currentProfile.getId()) 
        ) {
          currentProfile = Database.Profile.getById(databaseHelper, intent.getLongExtra(Database.Helper.EXTRA_ID, 0), currentProfile);
          updateListeners(FLAG_PROFILE);
        }
      }
    };
    
    private OnSharedPreferenceChangeListener preferencesUpdated = new OnSharedPreferenceChangeListener() {      
      @Override
      public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        if (key.equals(SettingsFragment.PREF_UNITS)) {
          metric = !prefs.getString(SettingsFragment.PREF_UNITS, SettingsFragment.PREF_UNITS_DEFAULT).equals(SettingsFragment.VALUE_UNITS_IMPERIAL);          
          updateListeners(0);
        }
        if (key.equals(SettingsFragment.PREF_CURRENT_PROFILE)) {
          currentProfile = Database.Profile.getById(databaseHelper, sharedPreferences.getLong(key, 0), currentProfile);
          updateListeners(FLAG_PROFILE);
        }
      }
    };
    
    private BroadcastReceiver batteryReceiver = new BroadcastReceiver() {      
      @Override
      public void onReceive(Context context, Intent intent) {
        int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
        boolean plugged = (intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0);
        
        boolean charging = ( 
            (status == BatteryManager.BATTERY_STATUS_CHARGING) ||
                      ((status == BatteryManager.BATTERY_STATUS_FULL) && plugged)
              );
        
        int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
        if (charging) level += 100;
        
        lastBatteryLevel = level;
      }
    };

    @Override
    public void run() {
      Debug.log("Thread init");
            
      databaseHelper = Database.Helper.getInstance(context);
      
      alarm = (AlarmManager)context.getSystemService(ALARM_SERVICE);
      {
        Intent i = new Intent(context.getApplicationContext(), BackgroundService.class);
        i.putExtra(EXTRA_ALARM_CALLBACK, 1);
        alarmCallback =  PendingIntent.getService(BackgroundService.this, 0, i, 0);
      }

      Looper.prepare();
      handler = new Handler();
          
      Debug.log("Registering for updates");      
      prefs = PreferenceManager.getDefaultSharedPreferences(context);          
      long id = prefs.getLong(SettingsFragment.PREF_CURRENT_PROFILE, 0);
      if (id > 0) currentProfile = Database.Profile.getById(databaseHelper, id, null);
      if (currentProfile == null) currentProfile = Database.Profile.getOffProfile(databaseHelper);
      metric = !prefs.getString(SettingsFragment.PREF_UNITS, SettingsFragment.PREF_UNITS_DEFAULT).equals(SettingsFragment.VALUE_UNITS_IMPERIAL);
      prefs.registerOnSharedPreferenceChangeListener(preferencesUpdated);
      LocalBroadcastManager.getInstance(context).registerReceiver(databaseUpdated, new IntentFilter(Database.Helper.NOTIFY_BROADCAST));
      
      Debug.log("Registering for power levels");
      context.registerReceiver(batteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
      
      Debug.log("Connecting ActivityRecognitionClient");
      activityIntent = PendingIntent.getService(context, 1, new Intent(context, BackgroundService.class), 0);
      activityClient = new ActivityRecognitionClient(context, activityConnectionCallbacks, activityConnectionFailed);
      activityClient.connect();

      Debug.log("Connecting LocationClient");
      locationClient = new LocationClient(context, locationConnectionCallbacks, locationConnectionFailed);
      locationClient.connect();
      
      Debug.log("Entering loop");
      handler.post(new Runnable() {        
        @Override
        public void run() {
          updateListeners(FLAG_SETUP);
        }
      });            
      Looper.loop();      
      Debug.log("Exiting loop");
      
      context.unregisterReceiver(batteryReceiver);
      
      LocalBroadcastManager.getInstance(context).unregisterReceiver(databaseUpdated);
      prefs.unregisterOnSharedPreferenceChangeListener(preferencesUpdated);      
      
      if (activityConnected) {
        activityClient.removeActivityUpdates(activityIntent);
        activityClient.disconnect();
      }
      if (locationConnected) {
        locationClient.removeLocationUpdates(locationListener);
        locationClient.disconnect();
      }      
    }    
  }
}




Java Source Code List

eu.chainfire.geolog.Application.java
eu.chainfire.geolog.CrashCatcher.java
eu.chainfire.geolog.Debug.java
eu.chainfire.geolog.data.Database.java
eu.chainfire.geolog.data.Exporter.java
eu.chainfire.geolog.data.LogsProvider.java
eu.chainfire.geolog.data.ProfilesProvider.java
eu.chainfire.geolog.service.BackgroundService.java
eu.chainfire.geolog.service.BootCompleteReceiver.java
eu.chainfire.geolog.ui.ExportActivity.java
eu.chainfire.geolog.ui.LogsFragment.java
eu.chainfire.geolog.ui.MainActivity.java
eu.chainfire.geolog.ui.Pref.java
eu.chainfire.geolog.ui.PreferenceListFragment.java
eu.chainfire.geolog.ui.ProfileActivity.java
eu.chainfire.geolog.ui.ProfilesFragment.java
eu.chainfire.geolog.ui.SettingsFragment.java