/*
* Copyright (C) 2013 Jorrit "Chainfire" Jongma
*
* 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.data;
import java.util.Locale;
import java.util.concurrent.locks.ReentrantLock;
import com.google.android.gms.location.DetectedActivity;
import eu.chainfire.geolog.R;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
import android.provider.BaseColumns;
import android.support.v4.content.LocalBroadcastManager;
public class Database {
private static final String TYPE_TEXT = " TEXT";
private static final String TYPE_INTEGER = " INTEGER";
private static final String COMMA_SEP = ",";
public static final int INTERVAL_OFF = 0;
// +- 25m max distance between intervals, 6 km/h, 20 km/h, 100 km/h
public static final int INTERVAL_NAVIGATION_HIGH_ACCURACY_FOOT = 15;
public static final int INTERVAL_NAVIGATION_HIGH_ACCURACY_BICYCLE = 5;
public static final int INTERVAL_NAVIGATION_HIGH_ACCURACY_VEHICLE = 1;
public static final int INTERVAL_NAVIGATION_HIGH_ACCURACY_FIXED = 90;
// += 150m max distance between intervals
public static final int INTERVAL_NAVIGATION_LOW_POWER_FOOT = 90;
public static final int INTERVAL_NAVIGATION_LOW_POWER_BICYCLE = 30;
public static final int INTERVAL_NAVIGATION_LOW_POWER_VEHICLE = 6;
public static final int INTERVAL_NAVIGATION_LOW_POWER_FIXED = 180;
public static final int INTERVAL_VERY_FAST = 30;
public static final int INTERVAL_FASTER = 60;
public static final int INTERVAL_FAST = 2 * 60;
public static final int INTERVAL_MEDIUM_FAST = 3 * 60;
public static final int INTERVAL_MEDIUM = 5 * 60;
public static final int INTERVAL_SLOW = 10 * 60;
public static final int INTERVAL_SLOWER = 15 * 60;
public static enum Activity { UNKNOWN, STILL, FOOT, BICYCLE, VEHICLE };
public static enum Accuracy { NONE, LOW, HIGH };
public static Activity activityFromInt(int activity) {
switch (activity) {
case 0: return Activity.UNKNOWN;
case 1: return Activity.STILL;
case 2: return Activity.FOOT;
case 3: return Activity.BICYCLE;
case 4: return Activity.VEHICLE;
}
return Activity.UNKNOWN;
}
public static int activityToInt(Activity activity) {
switch (activity) {
case UNKNOWN: return 0;
case STILL: return 1;
case FOOT: return 2;
case BICYCLE: return 3;
case VEHICLE: return 4;
}
return 0;
}
public static String activityToString(Activity activity) {
switch (activity) {
case UNKNOWN: return "Unknown";
case STILL: return "Still";
case FOOT: return "Foot";
case BICYCLE: return "Bicycle";
case VEHICLE: return "Vehicle";
}
return "Unknown";
}
public static Activity activityFromDetectedActivity(DetectedActivity activity) {
switch (activity.getType()) {
case DetectedActivity.UNKNOWN: return Activity.UNKNOWN;
case DetectedActivity.STILL: return Activity.STILL;
case DetectedActivity.ON_FOOT: return Activity.FOOT;
case DetectedActivity.ON_BICYCLE: return Activity.BICYCLE;
case DetectedActivity.IN_VEHICLE: return Activity.VEHICLE;
}
return Activity.UNKNOWN;
}
public static boolean isDetectedActivityValid(DetectedActivity activity) {
// conversion succeeds and is not unknown (default result), unless original is actually unknown
return (
(activity.getType() == DetectedActivity.UNKNOWN) ||
(activityFromDetectedActivity(activity) != Activity.UNKNOWN)
);
}
public static Accuracy accuracyFromInt(int accuracy) {
if (accuracy == 0) return Accuracy.NONE;
if (accuracy == 1) return Accuracy.LOW;
return Accuracy.HIGH;
}
public static int accuracyToInt(Accuracy accuracy) {
if (accuracy == Accuracy.NONE) return 0;
if (accuracy == Accuracy.LOW) return 1;
return 2;
}
public static class Helper extends SQLiteOpenHelper {
public static final int DATABASE_VERSION = 1;
public static final String DATABASE_NAME = "geolog.db";
public static final String NOTIFY_BROADCAST = "eu.chainfire.geolog.DATABASE.UPDATED";
public static final String EXTRA_TABLE = "eu.chainfire.geolog.EXTRA.TABLE";
public static final String EXTRA_ID = "eu.chainfire.geolog.EXTRA.ID";
private static Helper instance = null;
public static Helper getInstance(Context context) {
if (instance == null) instance = new Helper(context.getApplicationContext());
return instance;
}
private ReentrantLock lock = new ReentrantLock(true);
private final Context context;
private Helper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.context = context;
getReadableDatabase();
createDefaultEntries(getWritableDatabase());
}
public void acquireLock() {
lock.lock();
}
public void releaseLock() {
lock.unlock();
}
public void notifyUri(Uri uri) {
context.getContentResolver().notifyChange(uri, null);
}
public void notifyBroadcast(String table, long id) {
Intent i = new Intent(NOTIFY_BROADCAST);
i.putExtra(EXTRA_TABLE, table);
i.putExtra(EXTRA_ID, id);
LocalBroadcastManager.getInstance(context).sendBroadcast(i);
}
@Override
public void onCreate(SQLiteDatabase db) {
// Profiles
db.execSQL(Profile.SQL_CREATE_TABLE);
for (String index : Profile.SQL_CREATE_INDICES) {
db.execSQL(index);
}
// Locations
db.execSQL(Location.SQL_CREATE_TABLE);
for (String index : Location.SQL_CREATE_INDICES) {
db.execSQL(index);
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL(Profile.SQL_DROP_TABLE);
db.execSQL(Location.SQL_DROP_TABLE);
onCreate(db);
}
private void createDefaultEntries(SQLiteDatabase db) {
//db.execSQL("DELETE FROM " + Profile.TABLE_NAME); //TODO
//db.execSQL("ALTER TABLE " + Location.TABLE_NAME + " ADD COLUMN " + Location.COLUMN_NAME_LOG_ID + " " + TYPE_INTEGER);
//db.execSQL("UPDATE " + Location.TABLE_NAME + " SET " + Location.COLUMN_NAME_LOG_ID + " = 0");
//db.execSQL("ALTER TABLE " + Profile.TABLE_NAME + " ADD COLUMN " + Profile.COLUMN_NAME_REDUCE_ACCURACY_DELAY + " " + TYPE_INTEGER);
//db.execSQL("UPDATE " + Profile.TABLE_NAME + " SET " + Profile.COLUMN_NAME_REDUCE_ACCURACY_DELAY + " = 300");
if (DatabaseUtils.queryNumEntries(db, Profile.TABLE_NAME) == 0) {
{
Profile p = new Profile();
p.setType(Profile.Type.OFF);
p.setName(context.getString(R.string.profile_name_off));
p.saveToDatabase(this);
}
{
Profile p = new Profile();
p.setType(Profile.Type.PRESET);
p.setName(context.getString(R.string.profile_name_low_power_slow));
p.setReduceAccuracyDelay(300);
p.getUnknown().setAccuracy(Accuracy.LOW).setActivityInterval(INTERVAL_NAVIGATION_LOW_POWER_VEHICLE * 12).setLocationInterval(INTERVAL_NAVIGATION_LOW_POWER_VEHICLE * 12);
p.getStill().setAccuracy(Accuracy.NONE).setActivityInterval(INTERVAL_NAVIGATION_LOW_POWER_FOOT * 4).setLocationInterval(INTERVAL_NAVIGATION_LOW_POWER_FOOT * 4);
p.getFoot().setAccuracy(Accuracy.LOW).setActivityInterval(INTERVAL_NAVIGATION_LOW_POWER_FOOT * 4).setLocationInterval(INTERVAL_NAVIGATION_LOW_POWER_FOOT * 4);
p.getBicycle().setAccuracy(Accuracy.LOW).setActivityInterval(INTERVAL_NAVIGATION_LOW_POWER_BICYCLE * 8).setLocationInterval(INTERVAL_NAVIGATION_LOW_POWER_BICYCLE * 8);
p.getVehicle().setAccuracy(Accuracy.LOW).setActivityInterval(INTERVAL_NAVIGATION_LOW_POWER_VEHICLE * 12).setLocationInterval(INTERVAL_NAVIGATION_LOW_POWER_VEHICLE * 12);
p.saveToDatabase(this);
}
{
Profile p = new Profile();
p.setType(Profile.Type.PRESET);
p.setName(context.getString(R.string.profile_name_low_power_fast));
p.setReduceAccuracyDelay(300);
p.getUnknown().setAccuracy(Accuracy.LOW).setActivityInterval(INTERVAL_NAVIGATION_LOW_POWER_VEHICLE).setLocationInterval(INTERVAL_NAVIGATION_LOW_POWER_VEHICLE);
p.getStill().setAccuracy(Accuracy.NONE).setActivityInterval(INTERVAL_NAVIGATION_LOW_POWER_FOOT).setLocationInterval(INTERVAL_NAVIGATION_LOW_POWER_FOOT);
p.getFoot().setAccuracy(Accuracy.LOW).setActivityInterval(INTERVAL_NAVIGATION_LOW_POWER_FOOT).setLocationInterval(INTERVAL_NAVIGATION_LOW_POWER_FOOT);
p.getBicycle().setAccuracy(Accuracy.LOW).setActivityInterval(INTERVAL_NAVIGATION_LOW_POWER_BICYCLE).setLocationInterval(INTERVAL_NAVIGATION_LOW_POWER_BICYCLE);
p.getVehicle().setAccuracy(Accuracy.LOW).setActivityInterval(INTERVAL_NAVIGATION_LOW_POWER_VEHICLE).setLocationInterval(INTERVAL_NAVIGATION_LOW_POWER_VEHICLE);
p.saveToDatabase(this);
}
{
Profile p = new Profile();
p.setType(Profile.Type.PRESET);
p.setName(context.getString(R.string.profile_name_low_power_fixed));
p.setReduceAccuracyDelay(300);
p.getUnknown().setAccuracy(Accuracy.LOW).setActivityInterval(INTERVAL_OFF).setLocationInterval(INTERVAL_NAVIGATION_LOW_POWER_FIXED);
p.getStill().setAccuracy(Accuracy.LOW).setActivityInterval(INTERVAL_NAVIGATION_LOW_POWER_FIXED).setLocationInterval(INTERVAL_NAVIGATION_LOW_POWER_FIXED);
p.getFoot().setAccuracy(Accuracy.LOW).setActivityInterval(INTERVAL_NAVIGATION_LOW_POWER_FIXED).setLocationInterval(INTERVAL_NAVIGATION_LOW_POWER_FIXED);
p.getBicycle().setAccuracy(Accuracy.LOW).setActivityInterval(INTERVAL_NAVIGATION_LOW_POWER_FIXED).setLocationInterval(INTERVAL_NAVIGATION_LOW_POWER_FIXED);
p.getVehicle().setAccuracy(Accuracy.LOW).setActivityInterval(INTERVAL_NAVIGATION_LOW_POWER_FIXED).setLocationInterval(INTERVAL_NAVIGATION_LOW_POWER_FIXED);
p.saveToDatabase(this);
}
{
Profile p = new Profile();
p.setType(Profile.Type.PRESET);
p.setName(context.getString(R.string.profile_name_high_accuracy_slow));
p.setReduceAccuracyDelay(300);
p.getUnknown().setAccuracy(Accuracy.HIGH).setActivityInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_VEHICLE * 36).setLocationInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_VEHICLE * 36);
p.getStill().setAccuracy(Accuracy.NONE).setActivityInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_FOOT * 8).setLocationInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_FOOT * 8);
p.getFoot().setAccuracy(Accuracy.HIGH).setActivityInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_FOOT * 8).setLocationInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_FOOT * 8);
p.getBicycle().setAccuracy(Accuracy.HIGH).setActivityInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_BICYCLE * 16).setLocationInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_BICYCLE * 16);
p.getVehicle().setAccuracy(Accuracy.HIGH).setActivityInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_VEHICLE * 36).setLocationInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_VEHICLE * 36);
p.saveToDatabase(this);
}
{
Profile p = new Profile();
p.setType(Profile.Type.PRESET);
p.setName(context.getString(R.string.profile_name_high_accuracy_fast));
p.setReduceAccuracyDelay(300);
p.getUnknown().setAccuracy(Accuracy.HIGH).setActivityInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_VEHICLE).setLocationInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_VEHICLE);
p.getStill().setAccuracy(Accuracy.NONE).setActivityInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_FOOT).setLocationInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_FOOT);
p.getFoot().setAccuracy(Accuracy.HIGH).setActivityInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_FOOT).setLocationInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_FOOT);
p.getBicycle().setAccuracy(Accuracy.HIGH).setActivityInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_BICYCLE).setLocationInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_BICYCLE);
p.getVehicle().setAccuracy(Accuracy.HIGH).setActivityInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_VEHICLE).setLocationInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_VEHICLE);
p.saveToDatabase(this);
}
{
Profile p = new Profile();
p.setType(Profile.Type.PRESET);
p.setName(context.getString(R.string.profile_name_high_accuracy_fixed));
p.setReduceAccuracyDelay(300);
p.getUnknown().setAccuracy(Accuracy.HIGH).setActivityInterval(INTERVAL_OFF).setLocationInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_FIXED);
p.getStill().setAccuracy(Accuracy.HIGH).setActivityInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_FIXED).setLocationInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_FIXED);
p.getFoot().setAccuracy(Accuracy.HIGH).setActivityInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_FIXED).setLocationInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_FIXED);
p.getBicycle().setAccuracy(Accuracy.HIGH).setActivityInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_FIXED).setLocationInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_FIXED);
p.getVehicle().setAccuracy(Accuracy.HIGH).setActivityInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_FIXED).setLocationInterval(INTERVAL_NAVIGATION_HIGH_ACCURACY_FIXED);
p.saveToDatabase(this);
}
{
Profile p = new Profile();
p.setType(Profile.Type.PRESET);
p.setName(context.getString(R.string.profile_name_photo_walk_low_power));
p.setReduceAccuracyDelay(300);
p.getUnknown().setAccuracy(Accuracy.LOW).setActivityInterval(INTERVAL_VERY_FAST).setLocationInterval(INTERVAL_MEDIUM_FAST);
p.getStill().setAccuracy(Accuracy.NONE).setActivityInterval(INTERVAL_FASTER).setLocationInterval(INTERVAL_MEDIUM_FAST);
p.getFoot().setAccuracy(Accuracy.LOW).setActivityInterval(INTERVAL_MEDIUM_FAST).setLocationInterval(INTERVAL_MEDIUM_FAST);
p.getBicycle().setAccuracy(Accuracy.NONE).setActivityInterval(INTERVAL_MEDIUM_FAST).setLocationInterval(INTERVAL_MEDIUM_FAST);
p.getVehicle().setAccuracy(Accuracy.NONE).setActivityInterval(INTERVAL_MEDIUM_FAST).setLocationInterval(INTERVAL_MEDIUM_FAST);
p.saveToDatabase(this);
}
{
Profile p = new Profile();
p.setType(Profile.Type.PRESET);
p.setName(context.getString(R.string.profile_name_photo_walk_high_accuracy));
p.setReduceAccuracyDelay(300);
p.getUnknown().setAccuracy(Accuracy.HIGH).setActivityInterval(INTERVAL_VERY_FAST).setLocationInterval(INTERVAL_MEDIUM_FAST);
p.getStill().setAccuracy(Accuracy.NONE).setActivityInterval(INTERVAL_FASTER).setLocationInterval(INTERVAL_MEDIUM_FAST);
p.getFoot().setAccuracy(Accuracy.HIGH).setActivityInterval(INTERVAL_MEDIUM_FAST).setLocationInterval(INTERVAL_MEDIUM_FAST);
p.getBicycle().setAccuracy(Accuracy.NONE).setActivityInterval(INTERVAL_MEDIUM_FAST).setLocationInterval(INTERVAL_MEDIUM_FAST);
p.getVehicle().setAccuracy(Accuracy.NONE).setActivityInterval(INTERVAL_MEDIUM_FAST).setLocationInterval(INTERVAL_MEDIUM_FAST);
p.saveToDatabase(this);
}
}
}
}
public static class Profile implements BaseColumns {
public static final String BASE_INTERVAL_ACTIVITY = "%s_interval_activity";
public static final String BASE_INTERVAL_LOCATION = "%s_interval_location";
public static final String BASE_ACCURACY = "%s_accuracy";
public static final String BASE_UNKNOWN = "unknown";
public static final String BASE_STILL = "still";
public static final String BASE_FOOT = "foot";
public static final String BASE_BICYCLE = "bicycle";
public static final String BASE_VEHICLE = "vehicle";
public static final String TABLE_NAME = "profiles";
public static final String COLUMN_NAME_NAME = "name";
public static final String COLUMN_NAME_TYPE = "type";
public static final String COLUMN_NAME_REDUCE_ACCURACY_DELAY = "reduce_accuracy_delay";
public static final String COLUMN_NAME_UNKNOWN_INTERVAL_ACTIVITY = String.format(Locale.ENGLISH, BASE_INTERVAL_ACTIVITY, BASE_UNKNOWN);
public static final String COLUMN_NAME_UNKNOWN_INTERVAL_LOCATION = String.format(Locale.ENGLISH, BASE_INTERVAL_LOCATION, BASE_UNKNOWN);
public static final String COLUMN_NAME_UNKNOWN_ACCURACY = String.format(Locale.ENGLISH, BASE_ACCURACY, BASE_UNKNOWN);
public static final String COLUMN_NAME_STILL_INTERVAL_ACTIVITY = String.format(Locale.ENGLISH, BASE_INTERVAL_ACTIVITY, BASE_STILL);
public static final String COLUMN_NAME_STILL_INTERVAL_LOCATION = String.format(Locale.ENGLISH, BASE_INTERVAL_LOCATION, BASE_STILL);
public static final String COLUMN_NAME_STILL_ACCURACY = String.format(Locale.ENGLISH, BASE_ACCURACY, BASE_STILL);
public static final String COLUMN_NAME_FOOT_INTERVAL_ACTIVITY = String.format(Locale.ENGLISH, BASE_INTERVAL_ACTIVITY, BASE_FOOT);
public static final String COLUMN_NAME_FOOT_INTERVAL_LOCATION = String.format(Locale.ENGLISH, BASE_INTERVAL_LOCATION, BASE_FOOT);
public static final String COLUMN_NAME_FOOT_ACCURACY = String.format(Locale.ENGLISH, BASE_ACCURACY, BASE_FOOT);
public static final String COLUMN_NAME_BICYCLE_INTERVAL_ACTIVITY = String.format(Locale.ENGLISH, BASE_INTERVAL_ACTIVITY, BASE_BICYCLE);
public static final String COLUMN_NAME_BICYCLE_INTERVAL_LOCATION = String.format(Locale.ENGLISH, BASE_INTERVAL_LOCATION, BASE_BICYCLE);
public static final String COLUMN_NAME_BICYCLE_ACCURACY = String.format(Locale.ENGLISH, BASE_ACCURACY, BASE_BICYCLE);
public static final String COLUMN_NAME_VEHICLE_INTERVAL_ACTIVITY = String.format(Locale.ENGLISH, BASE_INTERVAL_ACTIVITY, BASE_VEHICLE);
public static final String COLUMN_NAME_VEHICLE_INTERVAL_LOCATION = String.format(Locale.ENGLISH, BASE_INTERVAL_LOCATION, BASE_VEHICLE);
public static final String COLUMN_NAME_VEHICLE_ACCURACY = String.format(Locale.ENGLISH, BASE_ACCURACY, BASE_VEHICLE);
public static final String SQL_CREATE_TABLE =
"CREATE TABLE " + TABLE_NAME + " (" +
_ID + " INTEGER PRIMARY KEY AUTOINCREMENT" + COMMA_SEP +
COLUMN_NAME_NAME + TYPE_TEXT + COMMA_SEP +
COLUMN_NAME_TYPE + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_REDUCE_ACCURACY_DELAY + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_UNKNOWN_INTERVAL_ACTIVITY + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_UNKNOWN_INTERVAL_LOCATION + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_UNKNOWN_ACCURACY + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_STILL_INTERVAL_ACTIVITY + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_STILL_INTERVAL_LOCATION + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_STILL_ACCURACY + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_FOOT_INTERVAL_ACTIVITY + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_FOOT_INTERVAL_LOCATION + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_FOOT_ACCURACY + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_BICYCLE_INTERVAL_ACTIVITY + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_BICYCLE_INTERVAL_LOCATION + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_BICYCLE_ACCURACY + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_VEHICLE_INTERVAL_ACTIVITY + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_VEHICLE_INTERVAL_LOCATION + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_VEHICLE_ACCURACY + TYPE_INTEGER +
")";
public static final String[] SQL_CREATE_INDICES = new String[] {
};
public static final String SQL_DROP_TABLE =
"DROP TABLE IF EXISTS " + TABLE_NAME;
public static enum Type { OFF, PRESET, USER };
private static Type typeFromInt(int type) {
if (type == 0) return Type.OFF;
if (type == 1) return Type.PRESET;
return Type.USER;
}
private static int typeToInt(Type type) {
if (type == Type.OFF) return 0;
if (type == Type.PRESET) return 1;
return 2;
}
public class ActivitySettings {
private int activityInterval = 0;
private int locationInterval = 0;
private Accuracy accuracy = Accuracy.NONE;
public int getActivityInterval() { return activityInterval; }
public int getLocationInterval() { return locationInterval; }
public Accuracy getAccuracy() { return accuracy; }
public ActivitySettings setActivityInterval(int activityInterval) { this.activityInterval = activityInterval; return this; }
public ActivitySettings setLocationInterval(int locationInterval) { this.locationInterval = locationInterval; return this; }
public ActivitySettings setAccuracy(Accuracy accuracy) { this.accuracy = accuracy; return this; }
public void loadFromCursor(Cursor cursor, String base) {
activityInterval = cursor.getInt(cursor.getColumnIndex(String.format(Locale.ENGLISH, BASE_INTERVAL_ACTIVITY, base)));
locationInterval = cursor.getInt(cursor.getColumnIndex(String.format(Locale.ENGLISH, BASE_INTERVAL_LOCATION, base)));
accuracy = accuracyFromInt(cursor.getInt(cursor.getColumnIndex(String.format(Locale.ENGLISH, BASE_ACCURACY, base))));
}
public void saveToContentValues(ContentValues values, String base) {
values.put(String.format(Locale.ENGLISH, BASE_INTERVAL_ACTIVITY, base), activityInterval);
values.put(String.format(Locale.ENGLISH, BASE_INTERVAL_LOCATION, base), locationInterval);
values.put(String.format(Locale.ENGLISH, BASE_ACCURACY, base), accuracyToInt(accuracy));
}
}
private long id = -1;
private String name = "OFF";
private Type type = Type.OFF;
private int reduceAccuracyDelay = 0;
private final ActivitySettings unknown = new ActivitySettings();
private final ActivitySettings still = new ActivitySettings();
private final ActivitySettings foot = new ActivitySettings();
private final ActivitySettings bicycle = new ActivitySettings();
private final ActivitySettings vehicle = new ActivitySettings();
public long getId() { return id; }
public String getName() { return name; }
public Type getType() { return type; }
public int getReduceAccuracyDelay() { return reduceAccuracyDelay; }
public ActivitySettings getUnknown() { return unknown; }
public ActivitySettings getStill() { return still; }
public ActivitySettings getFoot() { return foot; }
public ActivitySettings getBicycle() { return bicycle; }
public ActivitySettings getVehicle() { return vehicle; }
public ActivitySettings getActivitySettings(Activity activity) {
switch (activity) {
case UNKNOWN: return getUnknown();
case STILL: return getStill();
case FOOT: return getFoot();
case BICYCLE: return getBicycle();
case VEHICLE: return getVehicle();
}
return getUnknown();
}
public Profile setType(Type type) { this.type = type; return this; }
public Profile setName(String name) { this.name = name; return this; }
public Profile setReduceAccuracyDelay(int reduceAccuracyDelay) { this.reduceAccuracyDelay = reduceAccuracyDelay; return this; }
public void loadFromCursor(Cursor cursor) {
id = cursor.getLong(cursor.getColumnIndex(_ID));
name = cursor.getString(cursor.getColumnIndex(COLUMN_NAME_NAME));
type = typeFromInt(cursor.getInt(cursor.getColumnIndex(COLUMN_NAME_TYPE)));
reduceAccuracyDelay = cursor.getInt(cursor.getColumnIndex(COLUMN_NAME_REDUCE_ACCURACY_DELAY));
unknown.loadFromCursor(cursor, BASE_UNKNOWN);
still.loadFromCursor(cursor, BASE_STILL);
foot.loadFromCursor(cursor, BASE_FOOT);
bicycle.loadFromCursor(cursor, BASE_BICYCLE);
vehicle.loadFromCursor(cursor, BASE_VEHICLE);
}
public long saveToDatabase(Helper helper) {
SQLiteDatabase db = helper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(COLUMN_NAME_NAME, name);
values.put(COLUMN_NAME_TYPE, typeToInt(type));
values.put(COLUMN_NAME_REDUCE_ACCURACY_DELAY, reduceAccuracyDelay);
unknown.saveToContentValues(values, BASE_UNKNOWN);
still.saveToContentValues(values, BASE_STILL);
foot.saveToContentValues(values, BASE_FOOT);
bicycle.saveToContentValues(values, BASE_BICYCLE);
vehicle.saveToContentValues(values, BASE_VEHICLE);
if (id < 0) {
id = db.insert(TABLE_NAME, null, values);
} else {
db.update(TABLE_NAME, values, _ID + " = ?", new String[] { String.valueOf(id) });
}
if (id >= 0) {
helper.notifyUri(ProfilesProvider.URILocations());
helper.notifyUri(ProfilesProvider.URILocation(id));
helper.notifyBroadcast(TABLE_NAME, id);
}
return id;
}
public static Profile getById(Helper helper, long id, Profile into) {
Cursor cursor = helper.getReadableDatabase().rawQuery("SELECT * FROM " + TABLE_NAME + " WHERE " + _ID + " = ?", new String[] { String.valueOf(id) });
if (cursor != null) {
try {
if (cursor.moveToFirst()) {
if (into == null) into = new Profile();
into.loadFromCursor(cursor);
return into;
}
} finally {
cursor.close();
}
}
return null;
}
public static void delete(Helper helper, long id) {
helper.getWritableDatabase().delete(TABLE_NAME, _ID + " = ?", new String[] { String.valueOf(id) });
helper.notifyUri(ProfilesProvider.URILocations());
helper.notifyUri(ProfilesProvider.URILocation(id));
helper.notifyBroadcast(TABLE_NAME, id);
}
private static void copyActivitySettings(ActivitySettings source, ActivitySettings destination) {
destination.setAccuracy(source.getAccuracy());
destination.setLocationInterval(source.getLocationInterval());
destination.setActivityInterval(source.getActivityInterval());
}
public static Profile copy(Helper helper, Profile profile, String name) {
Profile ret = new Profile();
ret.setName(name);
ret.setType(Type.USER);
ret.setReduceAccuracyDelay(profile.getReduceAccuracyDelay());
copyActivitySettings(profile.getUnknown() , ret.getUnknown() );
copyActivitySettings(profile.getStill() , ret.getStill() );
copyActivitySettings(profile.getFoot() , ret.getFoot() );
copyActivitySettings(profile.getBicycle() , ret.getBicycle() );
copyActivitySettings(profile.getVehicle() , ret.getVehicle() );
ret.saveToDatabase(helper);
return ret;
}
public static Cursor list(Helper helper) {
return helper.getReadableDatabase().query(TABLE_NAME, null, COLUMN_NAME_TYPE + " <> ?", new String[] { String.valueOf(typeToInt(Type.OFF)) }, null, null, _ID);
}
public static Profile getOffProfile(Helper helper) {
Cursor cursor = helper.getReadableDatabase().rawQuery("SELECT * FROM " + TABLE_NAME + " WHERE " + COLUMN_NAME_TYPE + " = ?", new String[] { String.valueOf(typeToInt(Type.OFF)) });
if (cursor != null) {
try {
if (cursor.moveToFirst()) {
Profile into = new Profile();
into.loadFromCursor(cursor);
return into;
}
} finally {
cursor.close();
}
}
return null;
}
}
public static class Location implements BaseColumns {
public static final String TABLE_NAME = "locations";
public static final String COLUMN_NAME_LOG_ID = "log_id";
public static final String COLUMN_NAME_ACTIVITY = "activity";
public static final String COLUMN_NAME_CONFIDENCE = "confidence";
public static final String COLUMN_NAME_TIME = "time";
public static final String COLUMN_NAME_LATITUDE = "latitude";
public static final String COLUMN_NAME_LONGITUDE = "longitude";
public static final String COLUMN_NAME_ALTITUDE = "altitude";
public static final String COLUMN_NAME_HAS_ALTITUDE = "has_altitude";
public static final String COLUMN_NAME_BEARING = "bearing";
public static final String COLUMN_NAME_HAS_BEARING = "has_bearing";
public static final String COLUMN_NAME_SPEED = "speed";
public static final String COLUMN_NAME_HAS_SPEED = "has_speed";
public static final String COLUMN_NAME_ACCURACY_DISTANCE = "location_accuracy";
public static final String COLUMN_NAME_HAS_ACCURACY_DISTANCE = "has_location_accuracy";
public static final String COLUMN_NAME_BATTERY = "battery";
public static final String COLUMN_NAME_ACCURACY_SETTING = "accuracy_setting";
public static final String COLUMN_NAME_IS_SEGMENT_START = "is_segment_start";
public static final String SQL_CREATE_TABLE =
"CREATE TABLE " + TABLE_NAME + " (" +
_ID + " INTEGER PRIMARY KEY AUTOINCREMENT" + COMMA_SEP +
COLUMN_NAME_LOG_ID + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_ACTIVITY + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_CONFIDENCE + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_TIME + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_LATITUDE + TYPE_TEXT + COMMA_SEP +
COLUMN_NAME_LONGITUDE + TYPE_TEXT + COMMA_SEP +
COLUMN_NAME_ALTITUDE + TYPE_TEXT + COMMA_SEP +
COLUMN_NAME_HAS_ALTITUDE + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_BEARING + TYPE_TEXT + COMMA_SEP +
COLUMN_NAME_HAS_BEARING + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_SPEED + TYPE_TEXT + COMMA_SEP +
COLUMN_NAME_HAS_SPEED + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_ACCURACY_DISTANCE + TYPE_TEXT + COMMA_SEP +
COLUMN_NAME_HAS_ACCURACY_DISTANCE + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_BATTERY + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_ACCURACY_SETTING + TYPE_INTEGER + COMMA_SEP +
COLUMN_NAME_IS_SEGMENT_START + TYPE_INTEGER +
")";
public static final String[] SQL_CREATE_INDICES = new String[] {
};
public static final String SQL_DROP_TABLE =
"DROP TABLE IF EXISTS " + TABLE_NAME;
private long id = -1;
private long logid = 0;
private Activity activity = Activity.UNKNOWN;
private int confidence = 0;
private long time = 0;
private double latitude = 0;
private double longitude = 0;
private double altitude = 0;
private boolean hasAltitude = false;
private float bearing = 0;
private boolean hasBearing = false;
private float speed = 0;
private boolean hasSpeed = false;
private float accuracyDistance = 0;
private boolean hasAccuracyDistance = false;
private int battery = 0;
private Accuracy accuracySetting = Accuracy.NONE;
private boolean isSegmentStart = false;
public long getId() { return id; }
public long getLogId() { return logid; }
public Activity getActivity() { return activity; }
public int getConfidence() { return confidence; }
public long getTime() { return time; }
public double getLatitude() { return latitude; }
public double getLongitude() { return longitude; }
public double getAltitude() { return altitude; }
public boolean hasAltitude() { return hasAltitude; }
public float getBearing() { return bearing; }
public boolean hasBearing() { return hasBearing; }
public float getSpeed() { return speed; }
public boolean hasSpeed() { return hasSpeed; }
public float getAccuracyDistance() { return accuracyDistance; }
public boolean hasAccuracyDistance() { return hasAccuracyDistance; }
public int getBattery() { return battery; }
public Accuracy getAccuracySetting() { return accuracySetting; }
public boolean isSegmentStart() { return isSegmentStart; }
public Location setLogId(long logid) { this.logid = logid; return this; }
public Location setActivity(Activity activity) { this.activity = activity; return this; }
public Location setConfidence(int confidence) { this.confidence = confidence; return this; }
public Location setTime(long time) { this.time = time; return this; }
public Location setLatitude(double latitude) { this.latitude = latitude; return this; }
public Location setLongitude(double longitude) { this.longitude = longitude; return this; }
public Location setAltitude(double altitude) { this.altitude = altitude; return this; }
public Location hasAltitude(boolean hasAltitude) { this.hasAltitude = hasAltitude; return this; }
public Location setBearing(float bearing) { this.bearing = bearing; return this; }
public Location hasBearing(boolean hasBearing) { this.hasBearing = hasBearing; return this; }
public Location setSpeed(float speed) { this.speed = speed; return this; }
public Location hasSpeed(boolean hasSpeed) { this.hasSpeed = hasSpeed; return this; }
public Location setAccuracyDistance(float accuracyDistance) { this.accuracyDistance = accuracyDistance; return this; }
public Location hasAccuracyDistance(boolean hasAccuracyDistance) { this.hasAccuracyDistance = hasAccuracyDistance; return this; }
public Location setBattery(int battery) { this.battery = battery; return this; }
public Location setAccuracySetting(Accuracy accuracySetting) { this.accuracySetting = accuracySetting; return this; }
public Location isSegmentStart(boolean isSegmentStart) { this.isSegmentStart = isSegmentStart; return this; }
public void loadFromCursor(Cursor cursor) {
id = cursor.getLong(cursor.getColumnIndex(_ID));
logid = cursor.getLong(cursor.getColumnIndex(COLUMN_NAME_LOG_ID));
activity = activityFromInt(cursor.getInt(cursor.getColumnIndex(COLUMN_NAME_ACTIVITY)));
confidence = cursor.getInt(cursor.getColumnIndex(COLUMN_NAME_CONFIDENCE));
time = cursor.getLong(cursor.getColumnIndex(COLUMN_NAME_TIME));
latitude = Double.valueOf(cursor.getString(cursor.getColumnIndex(COLUMN_NAME_LATITUDE)));
longitude = Double.valueOf(cursor.getString(cursor.getColumnIndex(COLUMN_NAME_LONGITUDE)));
altitude = Double.valueOf(cursor.getString(cursor.getColumnIndex(COLUMN_NAME_ALTITUDE)));
hasAltitude = (cursor.getInt(cursor.getColumnIndex(COLUMN_NAME_HAS_ALTITUDE)) == 1);
bearing = Float.valueOf(cursor.getString(cursor.getColumnIndex(COLUMN_NAME_BEARING)));
hasBearing = (cursor.getInt(cursor.getColumnIndex(COLUMN_NAME_HAS_BEARING)) == 1);
speed = Float.valueOf(cursor.getString(cursor.getColumnIndex(COLUMN_NAME_SPEED)));
hasSpeed = (cursor.getInt(cursor.getColumnIndex(COLUMN_NAME_HAS_SPEED)) == 1);
accuracyDistance = Float.valueOf(cursor.getString(cursor.getColumnIndex(COLUMN_NAME_ACCURACY_DISTANCE)));
hasAccuracyDistance = (cursor.getInt(cursor.getColumnIndex(COLUMN_NAME_HAS_ACCURACY_DISTANCE)) == 1);
battery = cursor.getInt(cursor.getColumnIndex(COLUMN_NAME_BATTERY));
accuracySetting = accuracyFromInt(cursor.getInt(cursor.getColumnIndex(COLUMN_NAME_ACCURACY_SETTING)));
isSegmentStart = (cursor.getInt(cursor.getColumnIndex(COLUMN_NAME_IS_SEGMENT_START)) == 1);
}
public void loadFromDetectedActivity(DetectedActivity detectedActivity) {
activity = activityFromDetectedActivity(detectedActivity);
confidence = detectedActivity.getConfidence();
}
public void loadFromLocation(android.location.Location location) {
time = location.getTime();
latitude = location.getLatitude();
longitude = location.getLongitude();
altitude = location.getAltitude();
hasAltitude = location.hasAltitude();
bearing = location.getBearing();
hasBearing = location.hasBearing();
speed = location.getSpeed();
hasSpeed = location.hasSpeed();
accuracyDistance = location.getAccuracy();
hasAccuracyDistance = location.hasAccuracy();
}
public long saveToDatabase(Helper helper) {
SQLiteDatabase db = helper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(COLUMN_NAME_LOG_ID, logid);
values.put(COLUMN_NAME_ACTIVITY, activityToInt(activity));
values.put(COLUMN_NAME_CONFIDENCE, confidence);
values.put(COLUMN_NAME_TIME, time);
values.put(COLUMN_NAME_LATITUDE, String.valueOf(latitude));
values.put(COLUMN_NAME_LONGITUDE, String.valueOf(longitude));
values.put(COLUMN_NAME_ALTITUDE, String.valueOf(altitude));
values.put(COLUMN_NAME_HAS_ALTITUDE, hasAltitude ? 1 : 0);
values.put(COLUMN_NAME_BEARING, String.valueOf(bearing));
values.put(COLUMN_NAME_HAS_BEARING, hasBearing ? 1 : 0);
values.put(COLUMN_NAME_SPEED, String.valueOf(speed));
values.put(COLUMN_NAME_HAS_SPEED, hasSpeed ? 1 : 0);
values.put(COLUMN_NAME_ACCURACY_DISTANCE, String.valueOf(accuracyDistance));
values.put(COLUMN_NAME_HAS_ACCURACY_DISTANCE, hasAccuracyDistance ? 1 : 0);
values.put(COLUMN_NAME_BATTERY, battery);
values.put(COLUMN_NAME_ACCURACY_SETTING, accuracyToInt(accuracySetting));
values.put(COLUMN_NAME_IS_SEGMENT_START, isSegmentStart ? 1 : 0);
if (id < 0) {
id = db.insert(TABLE_NAME, null, values);
} else {
db.update(TABLE_NAME, values, _ID + " = ?", new String[] { String.valueOf(id) });
}
if (id >= 0) {
helper.notifyUri(LogsProvider.URILocations());
helper.notifyUri(LogsProvider.URILocation(id));
helper.notifyBroadcast(TABLE_NAME, id);
}
return id;
}
public static Location getById(Helper helper, long id, Location into) {
Cursor cursor = helper.getReadableDatabase().rawQuery("SELECT * FROM " + TABLE_NAME + " WHERE " + _ID + " = ?", new String[] { String.valueOf(id) });
if (cursor != null) {
try {
if (cursor.moveToFirst()) {
if (into == null) into = new Location();
into.loadFromCursor(cursor);
return into;
}
} finally {
cursor.close();
}
}
return null;
}
public static void delete(Helper helper, long id) {
helper.getWritableDatabase().delete(TABLE_NAME, _ID + " = ?", new String[] { String.valueOf(id) });
helper.notifyUri(LogsProvider.URILocations());
helper.notifyUri(LogsProvider.URILocation(id));
helper.notifyBroadcast(TABLE_NAME, id);
}
public static void deleteAll(Helper helper) {
helper.getWritableDatabase().delete(TABLE_NAME, null, null);
helper.notifyUri(LogsProvider.URILocations());
helper.notifyUri(LogsProvider.URILocation(0));
helper.notifyBroadcast(TABLE_NAME, 0);
}
public static Location copy(Helper helper, Location location) {
Location ret = new Location();
ret.setLogId(location.getLogId());
ret.setActivity(location.getActivity());
ret.setConfidence(location.getConfidence());
ret.setTime(location.getTime());
ret.setLatitude(location.getLatitude());
ret.setLongitude(location.getLongitude());
ret.setAltitude(location.getAltitude());
ret.hasAltitude(location.hasAltitude());
ret.setBearing(location.getBearing());
ret.hasBearing(location.hasBearing());
ret.setSpeed(location.getSpeed());
ret.hasSpeed(location.hasSpeed());
ret.setAccuracyDistance(location.getAccuracyDistance());
ret.hasAccuracyDistance(location.hasAccuracyDistance());
ret.setBattery(location.getBattery());
ret.setAccuracySetting(location.getAccuracySetting());
ret.isSegmentStart(location.isSegmentStart());
ret.saveToDatabase(helper);
return ret;
}
public static Cursor list(Helper helper) {
return helper.getReadableDatabase().query(TABLE_NAME, null, null, null, null, null, _ID);
}
}
}