com.kevinquan.android.location.SimpleRecordedLocation.java Source code

Java tutorial

Introduction

Here is the source code for com.kevinquan.android.location.SimpleRecordedLocation.java

Source

/*
 * Copyright 2014 Kevin Quan (kevin.quan@gmail.com)
 * 
 * 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.kevinquan.android.location;

import java.util.Comparator;

import org.json.JSONObject;

import android.content.ContentValues;
import android.database.Cursor;
import android.location.Location;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.Log;

import com.kevinquan.android.utils.CursorUtils;
import com.kevinquan.android.utils.JSONUtils;

/**
 * This class models a recorded physical location position. 
 * 
 * @author Kevin Quan (kevin.quan@gmail.com)
 *
 */
public class SimpleRecordedLocation implements Parcelable {

    public static final Parcelable.Creator<SimpleRecordedLocation> CREATOR = new Parcelable.Creator<SimpleRecordedLocation>() {
        public SimpleRecordedLocation createFromParcel(Parcel in) {
            return new SimpleRecordedLocation(in);
        }

        public SimpleRecordedLocation[] newArray(int size) {
            return new SimpleRecordedLocation[size];
        }
    };

    public static class PositionTimestampComparator implements Comparator<SimpleRecordedLocation> {

        protected boolean mIsDescending;

        public PositionTimestampComparator() {
            mIsDescending = false;
        }

        public PositionTimestampComparator(boolean isDescending) {
            mIsDescending = isDescending;
        }

        @Override
        public int compare(SimpleRecordedLocation lhs, SimpleRecordedLocation rhs) {
            int result = ((Long) lhs.getRecordedAt()).compareTo(rhs.getRecordedAt());
            return mIsDescending ? -1 * result : result;
        }

    }

    private static final String TAG = SimpleRecordedLocation.class.getSimpleName();

    public enum LocationProviderType {
        Unknown(0), GooglePlayServices(1), GooglePlayServicesHighAccuracy(2), CellID(3), WiFi(4), GPS(
                5), CreatedProgramatically(6), CreatedFromPreferences(7), CreatedFromSelf(8), // From SimpleRecordedLocation.asLocation()
        ;

        protected static final String PLAY_SERVICES_LITERAL = "fused";
        // The functionality around this field is preventing this class from being pushed into utils library.
        protected static final String CREATED_PROGRAMATICALLY_LITERAL = LocationUtils.CONSTRUCTED_LOCATION_PROVIDER_NAME;
        protected static final String CREATED_FROM_PREFERENCES_LITERAL = LocationUtils.CONSTRUCTED_FROM_PREFERENCES_PROVIDER_NAME;

        private int mDbId;

        private LocationProviderType(int dbId) {
            mDbId = dbId;
        }

        public int getDbId() {
            return mDbId;
        }

        public static LocationProviderType fromDbId(int dbId) {
            switch (dbId) {
            case 1:
                return GooglePlayServices;
            case 2:
                return GooglePlayServicesHighAccuracy;
            case 3:
                return CellID;
            case 4:
                return WiFi;
            case 5:
                return GPS;
            case 6:
                return CreatedProgramatically;
            case 7:
                return CreatedFromPreferences;
            case 8:
                return CreatedFromSelf;
            default:
                return Unknown;
            }
        }

        public static LocationProviderType fromLiteral(String value) {
            if (TextUtils.isEmpty(value)) {
                return LocationProviderType.Unknown;
            }
            if (PLAY_SERVICES_LITERAL.equals(value)) {
                return LocationProviderType.GooglePlayServices;
            } else if (CREATED_PROGRAMATICALLY_LITERAL.equals(value)) {
                return LocationProviderType.CreatedProgramatically;
            } else if (CREATED_FROM_PREFERENCES_LITERAL.equals(value)) {
                return LocationProviderType.CreatedFromPreferences;
            } else if (TAG.equals(value)) {
                return LocationProviderType.CreatedFromSelf;
            }
            Log.w(TAG, "Could not find location provider type with literal value: " + value);
            return LocationProviderType.Unknown;
        }

        public static LocationProviderType fromValue(String value) {
            if (TextUtils.isEmpty(value)) {
                return LocationProviderType.Unknown;
            }
            for (LocationProviderType type : LocationProviderType.values()) {
                if (type.toString().equals(value)) {
                    return type;
                }
            }
            Log.w(TAG, "Could not find location provider type with value: " + value);
            return LocationProviderType.Unknown;
        }
    }

    public static final String JSON_FIELD_LATITUDE = "latitude";
    public static final String JSON_FIELD_LONGITUDE = "longitude";
    public static final String JSON_FIELD_ACCURACY = "accuracy";
    public static final String JSON_FIELD_ALTITUDE = "altitude";
    public static final String JSON_FIELD_BEARING = "bearing";
    public static final String JSON_FIELD_SPEED = "speed";
    public static final String JSON_FIELD_RECORDED_AT = "recordedAt";
    public static final String JSON_FIELD_PROVIDER_ID = "providerId";

    public static final String COLUMN_LATITUDE = "latitude";
    public static final String COLUMN_LONGITUDE = "longitude";
    public static final String COLUMN_ACCURACY = "accuracy";
    public static final String COLUMN_ALTITUDE = "altitude";
    public static final String COLUMN_BEARING = "bearing";
    public static final String COLUMN_SPEED = "speed";
    public static final String COLUMN_RECORDED_AT = "recordedAt";
    // Note: This field should actually store {@link LocationProviderType}.getDbId()
    public static final String COLUMN_PROVIDER_ID = "provider";

    public static final float UNKNOWN_ACCURACY = -1;
    public static final double UNKNOWN_ALTITUDE = -1;
    public static final float UNKNOWN_BEARING = -1;
    public static final float UNKNOWN_SPEED = -1;

    protected double mLatitude;
    protected double mLongitude;
    protected float mAccuracy;
    protected double mAltitude;
    protected float mBearing;
    protected float mSpeed;
    protected long mRecordedAt;
    protected LocationProviderType mProvider;

    protected SimpleRecordedLocation() {
        mLatitude = LocationUtils.NO_VALUE;
        mLongitude = LocationUtils.NO_VALUE;
        mAccuracy = UNKNOWN_ACCURACY;
        mAltitude = UNKNOWN_ALTITUDE;
        mBearing = UNKNOWN_BEARING;
        mSpeed = UNKNOWN_SPEED;
        mRecordedAt = 0;
        mProvider = LocationProviderType.Unknown;
    }

    public SimpleRecordedLocation(Location location) {
        this(location, location != null ? LocationProviderType.fromLiteral(location.getProvider())
                : LocationProviderType.Unknown);
    }

    public SimpleRecordedLocation(Location location, LocationProviderType provider) {
        this();
        if (location == null) {
            Log.w(TAG, "Location provided to construct position was null.");
            return;
        }
        mLatitude = location.getLatitude();
        mLongitude = location.getLongitude();
        mAccuracy = location.getAccuracy();
        mAltitude = location.getAltitude();
        mBearing = location.getBearing();
        mSpeed = location.getSpeed();
        mRecordedAt = location.getTime();
        mProvider = provider;
    }

    public SimpleRecordedLocation(Cursor row) {
        this();
        if (row == null) {
            Log.w(TAG, "Cursor provided to construct position was null.");
            return;
        }
        mLatitude = LocationUtils.parseLocationValueFromString(CursorUtils.safeGetString(row, COLUMN_LATITUDE));
        mLongitude = LocationUtils.parseLocationValueFromString(CursorUtils.safeGetString(row, COLUMN_LONGITUDE));
        mAccuracy = CursorUtils.safeGetFloat(row, COLUMN_ACCURACY, UNKNOWN_ACCURACY);
        mAltitude = CursorUtils.safeGetDouble(row, COLUMN_ALTITUDE, UNKNOWN_ALTITUDE);
        mBearing = CursorUtils.safeGetFloat(row, COLUMN_BEARING, UNKNOWN_BEARING);
        mSpeed = CursorUtils.safeGetFloat(row, COLUMN_SPEED, UNKNOWN_SPEED);
        mRecordedAt = CursorUtils.safeGetLong(row, COLUMN_RECORDED_AT, 0);
        mProvider = LocationProviderType
                .fromDbId(CursorUtils.safeGetInt(row, COLUMN_PROVIDER_ID, LocationProviderType.Unknown.getDbId()));
    }

    public SimpleRecordedLocation(Parcel in) {
        this();
        mLatitude = in.readDouble();
        mLongitude = in.readDouble();
        mAccuracy = in.readFloat();
        mAltitude = in.readDouble();
        mBearing = in.readFloat();
        mSpeed = in.readFloat();
        mRecordedAt = in.readLong();
        mProvider = LocationProviderType.fromValue(in.readString());
    }

    public SimpleRecordedLocation(JSONObject object) {
        this();
        mLatitude = JSONUtils.safeGetDouble(object, JSON_FIELD_LATITUDE, LocationUtils.NO_VALUE);
        mLongitude = JSONUtils.safeGetDouble(object, JSON_FIELD_LONGITUDE, LocationUtils.NO_VALUE);
        mAccuracy = (float) JSONUtils.safeGetDouble(object, JSON_FIELD_ACCURACY, UNKNOWN_ACCURACY);
        mAltitude = JSONUtils.safeGetDouble(object, JSON_FIELD_ALTITUDE, UNKNOWN_ALTITUDE);
        mBearing = (float) JSONUtils.safeGetDouble(object, JSON_FIELD_BEARING, UNKNOWN_BEARING);
        mSpeed = (float) JSONUtils.safeGetDouble(object, JSON_FIELD_SPEED, UNKNOWN_SPEED);
        mRecordedAt = JSONUtils.safeGetLong(object, JSON_FIELD_RECORDED_AT, 0);
        mProvider = LocationProviderType.fromDbId(
                JSONUtils.safeGetInt(object, JSON_FIELD_PROVIDER_ID, LocationProviderType.Unknown.getDbId()));
    }

    public SimpleRecordedLocation(SimpleRecordedLocation original) {
        mLatitude = original.mLatitude;
        mLongitude = original.mLongitude;
        mAccuracy = original.mAccuracy;
        mAltitude = original.mAltitude;
        mBearing = original.mBearing;
        mSpeed = original.mSpeed;
        mRecordedAt = original.mRecordedAt;
        mProvider = original.mProvider;
    }

    public double getLatitude() {
        return mLatitude;
    }

    public double getLongitude() {
        return mLongitude;
    }

    public float getAccuracy() {
        return mAccuracy;
    }

    public double getAltitude() {
        return mAltitude;
    }

    public float getBearing() {
        return mBearing;
    }

    public float getSpeed() {
        return mSpeed;
    }

    public long getRecordedAt() {
        return mRecordedAt;
    }

    public LocationProviderType getProvider() {
        return mProvider;
    }

    public Location asLocation() {
        Location location = new Location(TAG);
        location.setLatitude(mLatitude);
        location.setLongitude(mLongitude);
        location.setAccuracy(mAccuracy);
        location.setAltitude(mAltitude);
        location.setBearing(mBearing);
        location.setSpeed(mSpeed);
        location.setTime(mRecordedAt);
        return location;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeDouble(mLatitude);
        dest.writeDouble(mLongitude);
        dest.writeFloat(mAccuracy);
        dest.writeDouble(mAltitude);
        dest.writeFloat(mBearing);
        dest.writeFloat(mSpeed);
        dest.writeLong(mRecordedAt);
        dest.writeString(mProvider.toString());
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public boolean equals(Object o) {
        if (!(o instanceof SimpleRecordedLocation)) {
            return false;
        }
        SimpleRecordedLocation other = (SimpleRecordedLocation) o;
        return mRecordedAt == other.getRecordedAt() && mLatitude == other.getLatitude()
                && mLongitude == other.getLongitude() && mAccuracy == other.getAccuracy()
                && mAltitude == other.getAltitude() && mBearing == other.getBearing() && mSpeed == other.getSpeed()
                && mProvider == other.getProvider();
    }

    public JSONObject asJson(boolean concise) {
        JSONObject output = new JSONObject();
        JSONUtils.safePutDouble(output, JSON_FIELD_LATITUDE, mLatitude);
        JSONUtils.safePutDouble(output, JSON_FIELD_LONGITUDE, mLongitude);
        JSONUtils.safePutFloat(output, JSON_FIELD_ACCURACY, mAccuracy);
        if (!concise) {
            JSONUtils.safePutDouble(output, JSON_FIELD_ALTITUDE, mAltitude);
            JSONUtils.safePutFloat(output, JSON_FIELD_BEARING, mBearing);
            JSONUtils.safePutFloat(output, JSON_FIELD_SPEED, mSpeed);
        }
        JSONUtils.safePutLong(output, JSON_FIELD_RECORDED_AT, mRecordedAt);
        JSONUtils.safePutInt(output, JSON_FIELD_PROVIDER_ID, mProvider.getDbId());
        return output;
    }

    public ContentValues getContentValues() {
        ContentValues values = new ContentValues();
        values.put(COLUMN_LATITUDE, getLatitude());
        values.put(COLUMN_LONGITUDE, getLongitude());
        values.put(COLUMN_ACCURACY, getAccuracy());
        values.put(COLUMN_ALTITUDE, getAltitude());
        values.put(COLUMN_BEARING, getBearing());
        values.put(COLUMN_SPEED, getSpeed());
        values.put(COLUMN_RECORDED_AT, getRecordedAt());
        values.put(COLUMN_PROVIDER_ID, getProvider().getDbId());
        return values;
    }
}