Java tutorial
/* * Copyright (C) 2014 jonas.oreland@gmail.com * * 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, see <http://www.gnu.org/licenses/>. */ package org.runnerup.tracker.component; import android.Manifest; import android.annotation.TargetApi; import android.content.Context; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.location.Location; import android.location.LocationManager; import android.os.Build; import android.os.Handler; import android.preference.PreferenceManager; import android.support.v4.content.ContextCompat; import org.runnerup.R; import org.runnerup.tracker.GpsStatus; import org.runnerup.tracker.Tracker; import org.runnerup.util.TickListener; import static android.location.LocationManager.GPS_PROVIDER; import static android.location.LocationManager.NETWORK_PROVIDER; import static android.location.LocationManager.PASSIVE_PROVIDER; /** * Created by jonas on 12/11/14. */ @TargetApi(Build.VERSION_CODES.FROYO) public class TrackerGPS extends DefaultTrackerComponent implements TickListener { private boolean mWithoutGps = false; private int frequency_ms = 0; private Location mLastLocation; private final Tracker tracker; private static final String NAME = "GPS"; private GpsStatus mGpsStatus; private Callback mConnectCallback; @Override public String getName() { return NAME; } public TrackerGPS(Tracker tracker) { this.tracker = tracker; } @Override public ResultCode onInit(final Callback callback, Context context) { try { LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); if (lm == null) { return ResultCode.RESULT_NOT_SUPPORTED; } if (lm.getProvider(LocationManager.GPS_PROVIDER) == null) { return ResultCode.RESULT_NOT_SUPPORTED; } } catch (Exception ex) { return ResultCode.RESULT_ERROR; } return ResultCode.RESULT_OK; } @Override public ResultCode onConnecting(final Callback callback, Context context) { if (ContextCompat.checkSelfPermission(this.tracker, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { mWithoutGps = true; } try { LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); frequency_ms = Integer .valueOf(preferences.getString(context.getString(R.string.pref_pollInterval), "500")); if (!mWithoutGps) { String frequency_meters = preferences.getString(context.getString(R.string.pref_pollDistance), "5"); lm.requestLocationUpdates(GPS_PROVIDER, frequency_ms, Integer.valueOf(frequency_meters), tracker); mGpsStatus = new GpsStatus(context); mGpsStatus.start(this); mConnectCallback = callback; return ResultCode.RESULT_PENDING; } else { String list[] = { GPS_PROVIDER, NETWORK_PROVIDER, PASSIVE_PROVIDER }; mLastLocation = null; for (String s : list) { Location tmp = lm.getLastKnownLocation(s); if (mLastLocation == null || tmp.getTime() > mLastLocation.getTime()) { mLastLocation = tmp; } } if (mLastLocation != null) { mLastLocation.removeSpeed(); mLastLocation.removeAltitude(); mLastLocation.removeAccuracy(); mLastLocation.removeBearing(); } gpsLessLocationProvider.run(); return ResultCode.RESULT_OK; } } catch (Exception ex) { return ResultCode.RESULT_ERROR; } } @Override public boolean isConnected() { return (mWithoutGps) || (mGpsStatus != null) && mGpsStatus.isFixed(); } @Override public ResultCode onEnd(Callback callback, Context context) { if (!mWithoutGps) { LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); try { lm.removeUpdates(tracker); } catch (SecurityException ex) { ex.printStackTrace(); } catch (Exception ex) { ex.printStackTrace(); } if (mGpsStatus != null) { mGpsStatus.stop(this); } mGpsStatus = null; mConnectCallback = null; } return ResultCode.RESULT_OK; } private final Runnable gpsLessLocationProvider = new Runnable() { Location location = null; final Handler handler = new Handler(); @Override public void run() { if (location == null) { location = new Location(mLastLocation); mLastLocation = null; } location.setTime(System.currentTimeMillis()); switch (tracker.getState()) { case INIT: case CLEANUP: case ERROR: /* end loop be returning directly here */ return; case INITIALIZING: case INITIALIZED: case STARTED: case PAUSED: /* continue looping */ break; } tracker.onLocationChanged(location); handler.postDelayed(this, frequency_ms); } }; @Override public void onTick() { if (mGpsStatus == null) return; if (!mGpsStatus.isFixed()) return; if (mConnectCallback == null) return; Callback tmp = mConnectCallback; mConnectCallback = null; mGpsStatus.stop(this); //note: Don't reset mGpsStatus, it's used for isConnected() tmp.run(this, ResultCode.RESULT_OK); } }