diff options
Diffstat (limited to 'tests/LocationTracker/src')
11 files changed, 1596 insertions, 0 deletions
diff --git a/tests/LocationTracker/src/com/google/android/locationtracker/SettingsActivity.java b/tests/LocationTracker/src/com/google/android/locationtracker/SettingsActivity.java new file mode 100755 index 0000000..edfe65a --- /dev/null +++ b/tests/LocationTracker/src/com/google/android/locationtracker/SettingsActivity.java @@ -0,0 +1,35 @@ +/*
+ * Copyright (C) 2008 Google Inc.
+ *
+ * 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.google.android.locationtracker;
+
+import android.os.Bundle;
+import android.preference.PreferenceActivity;
+
+/**
+ * Settings preference screen for location tracker
+ */
+public class SettingsActivity extends PreferenceActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Load the preferences from an XML resource
+ addPreferencesFromResource(R.xml.preferences);
+ }
+
+}
diff --git a/tests/LocationTracker/src/com/google/android/locationtracker/TrackerActivity.java b/tests/LocationTracker/src/com/google/android/locationtracker/TrackerActivity.java new file mode 100644 index 0000000..a96c6bb --- /dev/null +++ b/tests/LocationTracker/src/com/google/android/locationtracker/TrackerActivity.java @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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.google.android.locationtracker; + +import com.google.android.locationtracker.data.DateUtils; +import com.google.android.locationtracker.data.TrackerDataHelper; +import com.google.android.locationtracker.data.TrackerListHelper; + +import android.app.AlertDialog; +import android.app.ListActivity; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.content.Intent; +import android.database.Cursor; +import android.location.LocationManager; +import android.os.Bundle; +import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.widget.Toast; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; + +/** + * Activity for location tracker service + * + * Contains facilities for starting and + * stopping location tracker service, as well as displaying the current location + * data + * + * Future enhancements: + * - export data as dB + * - enable/disable "start service" and "stop service" menu items as + * appropriate + */ +public class TrackerActivity extends ListActivity { + + static final String LOG_TAG = "LocationTracker"; + + private TrackerListHelper mDataHelper; + + /** + * Retrieves and displays the currently logged location data from file + * + * @param icicle + */ + @Override + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); + + mDataHelper = new TrackerListHelper(this); + mDataHelper.bindListUI(R.layout.entrylist_item); + } + + /** + * Builds the menu + * + * @param menu - menu to add items to + */ + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater menuInflater = getMenuInflater(); + menuInflater.inflate(R.menu.menu, menu); + return true; + } + + /** + * Handles menu item selection + * + * @param item - the selected menu item + */ + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.start_service_menu: { + startService(new Intent(TrackerActivity.this, + TrackerService.class)); + break; + } + case R.id.stop_service_menu: { + stopService(new Intent(TrackerActivity.this, + TrackerService.class)); + break; + } + case R.id.settings_menu: { + launchSettings(); + break; + } + case R.id.export_kml: { + exportKML(); + break; + } + case R.id.export_csv: { + exportCSV(); + break; + } + case R.id.clear_data_menu: { + clearData(); + break; + } + } + return super.onOptionsItemSelected(item); + } + + private void clearData() { + Runnable clearAction = new Runnable() { + public void run() { + TrackerDataHelper helper = + new TrackerDataHelper(TrackerActivity.this); + helper.deleteAll(); + } + }; + showConfirm(R.string.delete_confirm, clearAction); + } + + private void showConfirm(int textId, final Runnable onConfirmAction) { + AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this); + dialogBuilder.setTitle(R.string.confirm_title); + dialogBuilder.setMessage(textId); + dialogBuilder.setPositiveButton(android.R.string.ok, + new OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + onConfirmAction.run(); + } + }); + dialogBuilder.setNegativeButton(android.R.string.cancel, + new OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + // do nothing + } + }); + dialogBuilder.show(); + } + + private void exportCSV() { + String exportFileName = getUniqueFileName("csv"); + exportFile(null, exportFileName, new TrackerDataHelper(this, + TrackerDataHelper.CSV_FORMATTER)); + } + + private void exportKML() { + String exportFileName = getUniqueFileName( + LocationManager.NETWORK_PROVIDER + ".kml"); + exportFile(LocationManager.NETWORK_PROVIDER, exportFileName, + new TrackerDataHelper(this, TrackerDataHelper.KML_FORMATTER)); + exportFileName = getUniqueFileName( + LocationManager.GPS_PROVIDER + ".kml"); + exportFile(LocationManager.GPS_PROVIDER, exportFileName, + new TrackerDataHelper(this, TrackerDataHelper.KML_FORMATTER)); + } + + private void exportFile(String tagFilter, + String exportFileName, + TrackerDataHelper trackerData) { + BufferedWriter exportWriter = null; + Cursor cursor = trackerData.query(tagFilter); + try { + exportWriter = new BufferedWriter(new FileWriter(exportFileName)); + exportWriter.write(trackerData.getOutputHeader()); + + String line = null; + + while ((line = trackerData.getNextOutput(cursor)) != null) { + exportWriter.write(line); + } + exportWriter.write(trackerData.getOutputFooter()); + Toast.makeText(this, "Successfully exported data to " + + exportFileName, Toast.LENGTH_SHORT).show(); + + } catch (IOException e) { + Toast.makeText(this, "Error exporting file: " + + e.getLocalizedMessage(), Toast.LENGTH_SHORT).show(); + + Log.e(LOG_TAG, "Error exporting file", e); + } finally { + closeWriter(exportWriter); + if (cursor != null) { + cursor.close(); + } + } + } + + private void closeWriter(Writer exportWriter) { + if (exportWriter != null) { + try { + exportWriter.close(); + } catch (IOException e) { + Log.e(LOG_TAG, "error closing file", e); + } + } + } + + private String getUniqueFileName(String ext) { + File dir = new File("/sdcard/locationtracker"); + if (!dir.exists()) { + dir.mkdir(); + } + return "/sdcard/locationtracker/tracking-" + + DateUtils.getCurrentTimestamp() + "." + ext; + } + + private void launchSettings() { + Intent settingsIntent = new Intent(); + settingsIntent.setClass(this, SettingsActivity.class); + startActivity(settingsIntent); + } +} diff --git a/tests/LocationTracker/src/com/google/android/locationtracker/TrackerService.java b/tests/LocationTracker/src/com/google/android/locationtracker/TrackerService.java new file mode 100644 index 0000000..e7fdc494 --- /dev/null +++ b/tests/LocationTracker/src/com/google/android/locationtracker/TrackerService.java @@ -0,0 +1,445 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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.google.android.locationtracker; + +import com.google.android.locationtracker.data.TrackerDataHelper; + +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.location.LocationListener; +import android.location.LocationManager; +import android.net.ConnectivityManager; +import android.net.wifi.ScanResult; +import android.net.wifi.WifiManager; +import android.os.Bundle; +import android.os.IBinder; +import android.preference.PreferenceManager; +import android.telephony.CellLocation; +import android.telephony.PhoneStateListener; +import android.telephony.SignalStrength; +import android.telephony.TelephonyManager; +import android.telephony.cdma.CdmaCellLocation; +import android.telephony.gsm.GsmCellLocation; +import android.util.Log; +import android.widget.Toast; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Location Tracking service + * + * Records location updates for all registered location providers, and cell + * location updates + */ +public class TrackerService extends Service { + + private List<LocationTrackingListener> mListeners; + + private static final String LOG_TAG = TrackerActivity.LOG_TAG; + + // controls which location providers to track + private Set<String> mTrackedProviders; + + private TrackerDataHelper mTrackerData; + + private TelephonyManager mTelephonyManager; + private Location mNetworkLocation; + + // Handlers and Receivers for phone and network state + private NetworkStateBroadcastReceiver mNetwork; + private static final String CELL_PROVIDER_TAG = "cell"; + // signal strength updates + private static final String SIGNAL_PROVIDER_TAG = "signal"; + private static final String WIFI_PROVIDER_TAG = "wifi"; + // tracking tag for data connectivity issues + private static final String DATA_CONN_PROVIDER_TAG = "data"; + + // preference constants + private static final String MIN_TIME_PREF = "mintime_preference"; + private static final String MIN_DIS_PREF = "mindistance_preference"; + private static final String GPS_PREF = "gps_preference"; + private static final String NETWORK_PREF = "network_preference"; + private static final String SIGNAL_PREF = "signal_preference"; + private static final String DEBUG_PREF = "advanced_log_preference"; + + private PreferenceListener mPrefListener; + + public TrackerService() { + } + + @Override + public IBinder onBind(Intent intent) { + // ignore - nothing to do + return null; + } + + /** + * registers location listeners + * + * @param intent + * @param startId + */ + @Override + public void onStart(Intent intent, int startId) { + super.onStart(intent, startId); + mNetworkLocation = null; + + initLocationListeners(); + Toast.makeText(this, "Tracking service started", Toast.LENGTH_SHORT); + } + + private synchronized void initLocationListeners() { + mTrackerData = new TrackerDataHelper(this); + LocationManager lm = getLocationManager(); + + mTrackedProviders = getTrackedProviders(); + + List<String> locationProviders = lm.getAllProviders(); + mListeners = new ArrayList<LocationTrackingListener>( + locationProviders.size()); + + long minUpdateTime = getLocationUpdateTime(); + float minDistance = getLocationMinDistance(); + + for (String providerName : locationProviders) { + if (mTrackedProviders.contains(providerName)) { + Log.d(LOG_TAG, "Adding location listener for provider " + + providerName); + if (doDebugLogging()) { + mTrackerData.writeEntry("init", String.format( + "start listening to %s : %d ms; %f meters", + providerName, minUpdateTime, minDistance)); + } + LocationTrackingListener listener = + new LocationTrackingListener(); + lm.requestLocationUpdates(providerName, minUpdateTime, + minDistance, listener); + mListeners.add(listener); + } + } + mTelephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE); + + if (doDebugLogging()) { + // register for cell location updates + mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CELL_LOCATION); + + // Register for Network (Wifi or Mobile) updates + mNetwork = new NetworkStateBroadcastReceiver(); + IntentFilter mIntentFilter; + mIntentFilter = new IntentFilter(); + mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); + mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); + mIntentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); + Log.d(LOG_TAG, "registering receiver"); + registerReceiver(mNetwork, mIntentFilter); + } + + if (trackSignalStrength()) { + mTelephonyManager.listen(mPhoneStateListener, + PhoneStateListener.LISTEN_SIGNAL_STRENGTHS); + } + + // register for preference changes, so we can restart listeners on + // pref changes + mPrefListener = new PreferenceListener(); + getPreferences().registerOnSharedPreferenceChangeListener(mPrefListener); + } + + private Set<String> getTrackedProviders() { + Set<String> providerSet = new HashSet<String>(); + + if (trackGPS()) { + providerSet.add(LocationManager.GPS_PROVIDER); + } + if (trackNetwork()) { + providerSet.add(LocationManager.NETWORK_PROVIDER); + } + return providerSet; + } + + private SharedPreferences getPreferences() { + return PreferenceManager.getDefaultSharedPreferences(this); + } + + private boolean trackNetwork() { + return getPreferences().getBoolean(NETWORK_PREF, true); + } + + private boolean trackGPS() { + return getPreferences().getBoolean(GPS_PREF, true); + } + + private boolean doDebugLogging() { + return getPreferences().getBoolean(DEBUG_PREF, true); + } + + private boolean trackSignalStrength() { + return getPreferences().getBoolean(SIGNAL_PREF, true); + } + + private float getLocationMinDistance() { + try { + String disString = getPreferences().getString(MIN_DIS_PREF, "0"); + return Float.parseFloat(disString); + } + catch (NumberFormatException e) { + Log.e(LOG_TAG, "Invalid preference for location min distance", e); + } + return 0; + } + + private long getLocationUpdateTime() { + try { + String timeString = getPreferences().getString(MIN_TIME_PREF, "0"); + long secondsTime = Long.valueOf(timeString); + return secondsTime * 1000; + } + catch (NumberFormatException e) { + Log.e(LOG_TAG, "Invalid preference for location min time", e); + } + return 0; + } + + /** + * Shuts down this service + */ + @Override + public void onDestroy() { + super.onDestroy(); + Log.d(LOG_TAG, "Removing location listeners"); + stopListeners(); + Toast.makeText(this, "Tracking service stopped", Toast.LENGTH_SHORT); + } + + /** + * De-registers all location listeners, closes persistent storage + */ + protected synchronized void stopListeners() { + LocationManager lm = getLocationManager(); + if (mListeners != null) { + for (LocationTrackingListener listener : mListeners) { + lm.removeUpdates(listener); + } + mListeners.clear(); + } + mListeners = null; + + // stop cell state listener + if (mTelephonyManager != null) { + mTelephonyManager.listen(mPhoneStateListener, 0); + } + + // stop network/wifi listener + if (mNetwork != null) { + unregisterReceiver(mNetwork); + } + mNetwork = null; + + mTrackerData = null; + if (mPrefListener != null) { + getPreferences().unregisterOnSharedPreferenceChangeListener(mPrefListener); + mPrefListener = null; + } + } + + private LocationManager getLocationManager() { + return (LocationManager) getSystemService(Context.LOCATION_SERVICE); + } + + /** + * Determine the current distance from given location to the last + * approximated network location + * + * @param location - new location + * + * @return float distance in meters + */ + private synchronized float getDistanceFromNetwork(Location location) { + float value = 0; + if (mNetworkLocation != null) { + value = location.distanceTo(mNetworkLocation); + } + if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) { + mNetworkLocation = location; + } + return value; + } + + private class LocationTrackingListener implements LocationListener { + + /** + * Writes details of location update to tracking file, including + * recording the distance between this location update and the last + * network location update + * + * @param location - new location + */ + public void onLocationChanged(Location location) { + if (location == null) { + return; + } + float distance = getDistanceFromNetwork(location); + mTrackerData.writeEntry(location, distance); + } + + /** + * Writes update to tracking file + * + * @param provider - name of disabled provider + */ + public void onProviderDisabled(String provider) { + if (doDebugLogging()) { + mTrackerData.writeEntry(provider, "provider disabled"); + } + } + + /** + * Writes update to tracking file + * + * @param provider - name of enabled provider + */ + public void onProviderEnabled(String provider) { + if (doDebugLogging()) { + mTrackerData.writeEntry(provider, "provider enabled"); + } + } + + /** + * Writes update to tracking file + * + * @param provider - name of provider whose status changed + * @param status - new status + * @param extras - optional set of extra status messages + */ + public void onStatusChanged(String provider, int status, Bundle extras) { + if (doDebugLogging()) { + mTrackerData.writeEntry(provider, "status change: " + status); + } + } + } + + PhoneStateListener mPhoneStateListener = new PhoneStateListener() { + @Override + public void onCellLocationChanged(CellLocation location) { + try { + if (location instanceof GsmCellLocation) { + GsmCellLocation cellLocation = (GsmCellLocation)location; + String updateMsg = "cid=" + cellLocation.getCid() + + ", lac=" + cellLocation.getLac(); + mTrackerData.writeEntry(CELL_PROVIDER_TAG, updateMsg); + } else if (location instanceof CdmaCellLocation) { + CdmaCellLocation cellLocation = (CdmaCellLocation)location; + String updateMsg = "BID=" + cellLocation.getBaseStationId() + + ", SID=" + cellLocation.getSystemId() + + ", NID=" + cellLocation.getNetworkId() + + ", lat=" + cellLocation.getBaseStationLatitude() + + ", long=" + cellLocation.getBaseStationLongitude() + + ", SID=" + cellLocation.getSystemId() + + ", NID=" + cellLocation.getNetworkId(); + mTrackerData.writeEntry(CELL_PROVIDER_TAG, updateMsg); + } + } catch (Exception e) { + Log.e(LOG_TAG, "Exception in CellStateHandler.handleMessage:", e); + } + } + + public void onSignalStrengthsChanged(SignalStrength signalStrength) { + if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) { + String updateMsg = "cdma dBM=" + signalStrength.getCdmaDbm(); + mTrackerData.writeEntry(SIGNAL_PROVIDER_TAG, updateMsg); + } else if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) { + String updateMsg = "gsm signal=" + signalStrength.getGsmSignalStrength(); + mTrackerData.writeEntry(SIGNAL_PROVIDER_TAG, updateMsg); + } + } + }; + + /** + * Listener + recorder for mobile or wifi updates + */ + private class NetworkStateBroadcastReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + + if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) { + WifiManager wifiManager = + (WifiManager) context.getSystemService(Context.WIFI_SERVICE); + List<ScanResult> wifiScanResults = wifiManager.getScanResults(); + String updateMsg = "num scan results=" + + (wifiScanResults == null ? "0" : wifiScanResults.size()); + mTrackerData.writeEntry(WIFI_PROVIDER_TAG, updateMsg); + + } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { + String updateMsg; + boolean noConnectivity = + intent.getBooleanExtra( + ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); + if (noConnectivity) { + updateMsg = "no connectivity"; + } + else { + updateMsg = "connection available"; + } + mTrackerData.writeEntry(DATA_CONN_PROVIDER_TAG, updateMsg); + + } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { + int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, + WifiManager.WIFI_STATE_UNKNOWN); + + String stateString = "unknown"; + switch (state) { + case WifiManager.WIFI_STATE_DISABLED: + stateString = "disabled"; + break; + case WifiManager.WIFI_STATE_DISABLING: + stateString = "disabling"; + break; + case WifiManager.WIFI_STATE_ENABLED: + stateString = "enabled"; + break; + case WifiManager.WIFI_STATE_ENABLING: + stateString = "enabling"; + break; + } + mTrackerData.writeEntry(WIFI_PROVIDER_TAG, + "state = " + stateString); + } + } + } + + private class PreferenceListener implements OnSharedPreferenceChangeListener { + + public void onSharedPreferenceChanged( + SharedPreferences sharedPreferences, String key) { + Log.d(LOG_TAG, "restarting listeners due to preference change"); + synchronized (TrackerService.this) { + stopListeners(); + initLocationListeners(); + } + } + } +} diff --git a/tests/LocationTracker/src/com/google/android/locationtracker/data/CSVFormatter.java b/tests/LocationTracker/src/com/google/android/locationtracker/data/CSVFormatter.java new file mode 100644 index 0000000..cd48db4 --- /dev/null +++ b/tests/LocationTracker/src/com/google/android/locationtracker/data/CSVFormatter.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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.google.android.locationtracker.data; + +import com.google.android.locationtracker.data.TrackerEntry.EntryType; + +/** + * Formats tracker data as CSV output + */ +class CSVFormatter implements IFormatter { + + private static final String DELIMITER = ", "; + + public String getHeader() { + StringBuilder csvBuilder = new StringBuilder(); + for (String col : TrackerEntry.ATTRIBUTES) { + // skip type and id column + if (!TrackerEntry.ENTRY_TYPE.equals(col) && + !TrackerEntry.ID_COL.equals(col)) { + csvBuilder.append(col); + csvBuilder.append(DELIMITER); + } + } + csvBuilder.append("\n"); + return csvBuilder.toString(); + } + + public String getOutput(TrackerEntry entry) { + StringBuilder rowOutput = new StringBuilder(); + // these must match order of columns added in getHeader + rowOutput.append(entry.getTimestamp()); + rowOutput.append(DELIMITER); + rowOutput.append(entry.getTag()); + rowOutput.append(DELIMITER); + //rowOutput.append(entry.getType()); + //rowOutput.append(DELIMITER); + if (entry.getType() == EntryType.LOCATION_TYPE) { + if (entry.getLocation().hasAccuracy()) { + rowOutput.append(entry.getLocation().getAccuracy()); + } + rowOutput.append(DELIMITER); + rowOutput.append(entry.getLocation().getLatitude()); + rowOutput.append(DELIMITER); + rowOutput.append(entry.getLocation().getLongitude()); + rowOutput.append(DELIMITER); + if (entry.getLocation().hasAltitude()) { + rowOutput.append(entry.getLocation().getAltitude()); + } + rowOutput.append(DELIMITER); + if (entry.getLocation().hasSpeed()) { + rowOutput.append(entry.getLocation().getSpeed()); + } + rowOutput.append(DELIMITER); + if (entry.getLocation().hasBearing()) { + rowOutput.append(entry.getLocation().getBearing()); + } + rowOutput.append(DELIMITER); + rowOutput.append(entry.getDistFromNetLocation()); + rowOutput.append(DELIMITER); + rowOutput.append(DateUtils.getKMLTimestamp(entry.getLocation() + .getTime())); + rowOutput.append(DELIMITER); + } + rowOutput.append(entry.getLogMsg()); + rowOutput.append("\n"); + return rowOutput.toString(); + } + + public String getFooter() { + // not needed, return empty string + return ""; + } +} diff --git a/tests/LocationTracker/src/com/google/android/locationtracker/data/DateUtils.java b/tests/LocationTracker/src/com/google/android/locationtracker/data/DateUtils.java new file mode 100644 index 0000000..78d6705 --- /dev/null +++ b/tests/LocationTracker/src/com/google/android/locationtracker/data/DateUtils.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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.google.android.locationtracker.data; + +import java.util.Calendar; +import java.util.TimeZone; + +/** + * Provides formatting date as string utilities + */ +public class DateUtils { + + private DateUtils() { + + } + + /** + * Returns timestamp given by param in KML format ie yyyy-mm-ddThh:mm:ssZ, + * where T is the separator between the date and the time and the time zone + * is Z (for UTC) + * + * @return KML timestamp as String + */ + public static String getKMLTimestamp(long when) { + TimeZone tz = TimeZone.getTimeZone("GMT"); + Calendar c = Calendar.getInstance(tz); + c.setTimeInMillis(when); + return String.format("%tY-%tm-%tdT%tH:%tM:%tSZ", c, c, c, c, c, c); + } + + /** + * Helper version of getKMLTimestamp, that returns timestamp for current + * time + */ + public static String getCurrentKMLTimestamp() { + return getKMLTimestamp(System.currentTimeMillis()); + } + + /** + * Returns timestamp in following format: yyyy-mm-dd-hh-mm-ss + */ + public static String getCurrentTimestamp() { + Calendar c = Calendar.getInstance(); + c.setTimeInMillis(System.currentTimeMillis()); + return String.format("%tY-%tm-%td-%tH-%tM-%tS", c, c, c, c, c, c); + } +} diff --git a/tests/LocationTracker/src/com/google/android/locationtracker/data/IFormatter.java b/tests/LocationTracker/src/com/google/android/locationtracker/data/IFormatter.java new file mode 100644 index 0000000..d921249 --- /dev/null +++ b/tests/LocationTracker/src/com/google/android/locationtracker/data/IFormatter.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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.google.android.locationtracker.data; + +/** + * interface for formatting tracker data output + */ +interface IFormatter { + + String getHeader(); + String getOutput(TrackerEntry entry); + String getFooter(); +} diff --git a/tests/LocationTracker/src/com/google/android/locationtracker/data/KMLFormatter.java b/tests/LocationTracker/src/com/google/android/locationtracker/data/KMLFormatter.java new file mode 100644 index 0000000..a49827c --- /dev/null +++ b/tests/LocationTracker/src/com/google/android/locationtracker/data/KMLFormatter.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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.google.android.locationtracker.data; + +import com.google.android.locationtracker.data.TrackerEntry.EntryType; + +import android.location.Location; + +/** + * Formats tracker data as KML output + */ +class KMLFormatter implements IFormatter { + + public String getHeader() { + LineBuilder builder = new LineBuilder(); + builder.addLine("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); + builder.addLine("<kml xmlns=\"http://earth.google.com/kml/2.2\">"); + builder.addLine("<Document>"); + return builder.toString(); + } + + public String getFooter() { + LineBuilder builder = new LineBuilder(); + builder.addLine("</Document>"); + builder.addLine("</kml>"); + return builder.toString(); + } + + public String getOutput(TrackerEntry entry) { + LineBuilder builder = new LineBuilder(); + + if (entry.getType() == EntryType.LOCATION_TYPE) { + + Location loc = entry.getLocation(); + builder.addLine("<Placemark>"); + builder.addLine("<description>"); + builder.addLine("accuracy = " + loc.getAccuracy()); + builder.addLine("distance from last network location = " + + entry.getDistFromNetLocation()); + builder.addLine("</description>"); + builder.addLine("<TimeStamp>"); + builder.addLine("<when>" + entry.getTimestamp() + "</when>"); + builder.addLine("</TimeStamp>"); + builder.addLine("<Point>"); + builder.addLine("<coordinates>"); + builder.addLine(loc.getLongitude() + "," + loc.getLatitude() + "," + + loc.getAltitude()); + builder.addLine("</coordinates>"); + builder.addLine("</Point>"); + builder.addLine("</Placemark>"); + } + return builder.toString(); + } + + private static class LineBuilder { + private StringBuilder mBuilder; + + public LineBuilder() { + mBuilder = new StringBuilder(); + } + + public void addLine(String line) { + mBuilder.append(line); + mBuilder.append("\n"); + } + + @Override + public String toString() { + return mBuilder.toString(); + } + + } + +} diff --git a/tests/LocationTracker/src/com/google/android/locationtracker/data/TrackerDataHelper.java b/tests/LocationTracker/src/com/google/android/locationtracker/data/TrackerDataHelper.java new file mode 100644 index 0000000..cdcc2b3 --- /dev/null +++ b/tests/LocationTracker/src/com/google/android/locationtracker/data/TrackerDataHelper.java @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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.google.android.locationtracker.data; + +import android.content.Context; +import android.database.Cursor; +import android.location.Location; + +/** + * Helper class for writing and retrieving data using the TrackerProvider + * content provider + * + */ +public class TrackerDataHelper { + + private Context mContext; + /** formats data output */ + protected IFormatter mFormatter; + + /** formats output as Comma separated value CSV file */ + public static final IFormatter CSV_FORMATTER = new CSVFormatter(); + /** formats output as KML file */ + public static final IFormatter KML_FORMATTER = new KMLFormatter(); + /** provides no formatting */ + public static final IFormatter NO_FORMATTER = new IFormatter() { + public String getFooter() { + return ""; + } + + public String getHeader() { + return ""; + } + + public String getOutput(TrackerEntry entry) { + return ""; + } + }; + + /** + * Creates instance + * + * @param context - content context + * @param formatter - formats the output from the get*Output* methods + */ + public TrackerDataHelper(Context context, IFormatter formatter) { + mContext = context; + mFormatter = formatter; + } + + /** + * Creates a instance with no output formatting capabilities. Useful for + * clients that require write-only access + */ + public TrackerDataHelper(Context context) { + this(context, NO_FORMATTER); + } + + /** + * insert given TrackerEntry into content provider + */ + void writeEntry(TrackerEntry entry) { + mContext.getContentResolver().insert(TrackerProvider.CONTENT_URI, + entry.getAsContentValues()); + } + + /** + * insert given location into tracker data + */ + public void writeEntry(Location loc, float distFromNetLoc) { + writeEntry(TrackerEntry.createEntry(loc, distFromNetLoc)); + } + + /** + * insert given log message into tracker data + */ + public void writeEntry(String tag, String logMsg) { + writeEntry(TrackerEntry.createEntry(tag, logMsg)); + } + + /** + * Deletes all tracker entries + */ + public void deleteAll() { + mContext.getContentResolver().delete(TrackerProvider.CONTENT_URI, null, + null); + } + + /** + * Query tracker data, filtering by given tag + * + * @param tag + * @return Cursor to data + */ + public Cursor query(String tag, int limit) { + String selection = (tag == null ? null : TrackerEntry.TAG + "=?"); + String[] selectionArgs = (tag == null ? null : new String[] {tag}); + Cursor cursor = mContext.getContentResolver().query( + TrackerProvider.CONTENT_URI, TrackerEntry.ATTRIBUTES, + selection, selectionArgs, null); + if (cursor == null) { + return cursor; + } + int pos = (cursor.getCount() < limit ? 0 : cursor.getCount() - limit); + cursor.moveToPosition(pos); + return cursor; + } + + /** + * Retrieves a cursor that starts at the last limit rows + * + * @param limit + * @return a cursor, null if bad things happened + */ + public Cursor query(int limit) { + return query(null, limit); + } + + /** + * Query tracker data, filtering by given tag. mo limit to number of rows + * returned + * + * @param tag + * @return Cursor to data + */ + public Cursor query(String tag) { + return query(tag, Integer.MAX_VALUE); + } + + /** + * Returns the output header particular to the associated formatter + */ + public String getOutputHeader() { + return mFormatter.getHeader(); + } + + /** + * Returns the output footer particular to the associated formatter + */ + public String getOutputFooter() { + return mFormatter.getFooter(); + } + + /** + * Helper method which converts row referenced by given cursor to a string + * output + * + * @param cursor + * @return CharSequence output, null if given cursor is invalid or no more + * data + */ + public String getNextOutput(Cursor cursor) { + if (cursor == null || cursor.isAfterLast()) { + return null; + } + String output = mFormatter.getOutput(TrackerEntry.createEntry(cursor)); + cursor.moveToNext(); + return output; + } +} diff --git a/tests/LocationTracker/src/com/google/android/locationtracker/data/TrackerEntry.java b/tests/LocationTracker/src/com/google/android/locationtracker/data/TrackerEntry.java new file mode 100644 index 0000000..91e6dcc --- /dev/null +++ b/tests/LocationTracker/src/com/google/android/locationtracker/data/TrackerEntry.java @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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.google.android.locationtracker.data; + +import android.content.ContentValues; +import android.database.Cursor; +import android.location.Location; + + +/** + * Class that holds a tracker entry. An entry can be either a valid location, or + * a simple log msg + * + * It provides a concrete data structure to represent data stored in the + * TrackerProvider + */ +class TrackerEntry { + + static final String TIMESTAMP = "Timestamp"; + static final String TAG = "Tag"; + static final String ENTRY_TYPE = "Type"; + + private Location mLocation; + private float mDistFromNetLocation; + private String mLogMsg; + + static final String ID_COL = "_id"; + static final String ACCURACY = "Accuracy"; + static final String LATITUDE = "Latitude"; + static final String LONGITUDE = "Longitude"; + static final String ALTITUDE = "Altitude"; + static final String SPEED = "Speed"; + static final String BEARING = "Bearing"; + static final String DIST_NET_LOCATION = "DistFromNetLocation"; + static final String LOC_TIME = "LocationTime"; + static final String DEBUG_INFO = "DebugInfo"; + + static final String STRING_DATA = "STRING"; + static final String INT_DATA = "INTEGER"; + static final String REAL_DATA = "REAL"; + static final String BLOB_DATA = "BLOB"; + + static final String[] ATTRIBUTES = { + ID_COL, TIMESTAMP, TAG, ENTRY_TYPE, ACCURACY, LATITUDE, LONGITUDE, + ALTITUDE, SPEED, BEARING, DIST_NET_LOCATION, LOC_TIME, DEBUG_INFO}; + static final String[] ATTRIBUTES_DATA_TYPE = { + INT_DATA + " PRIMARY KEY", STRING_DATA, STRING_DATA, STRING_DATA, + REAL_DATA, REAL_DATA, REAL_DATA, REAL_DATA, REAL_DATA, REAL_DATA, + REAL_DATA, INT_DATA, STRING_DATA}; + + // location extra keys used to retrieve debug info + private static final String NETWORK_LOCATION_SOURCE_KEY = + "networkLocationSource"; + private static final String NETWORK_LOCATION_TYPE_KEY = + "networkLocationType"; + private static final String[] LOCATION_DEBUG_KEYS = { + NETWORK_LOCATION_SOURCE_KEY, NETWORK_LOCATION_TYPE_KEY}; + + enum EntryType { + LOCATION_TYPE, LOG_TYPE + } + + private String mTimestamp; + private String mTag; + private EntryType mType; + + private TrackerEntry(String tag, EntryType type) { + mType = type; + mTag = tag; + mLocation = null; + } + + private TrackerEntry(Location loc) { + this(loc.getProvider(), EntryType.LOCATION_TYPE); + mLocation = new Location(loc); + } + + /** + * Creates a TrackerEntry from a Location + */ + static TrackerEntry createEntry(Location loc, float distFromNetLocation) { + TrackerEntry entry = new TrackerEntry(loc); + + String timestampVal = DateUtils.getCurrentKMLTimestamp(); + entry.setTimestamp(timestampVal); + entry.setDistFromNetLocation(distFromNetLocation); + return entry; + } + + /** + * Creates a TrackerEntry from a log msg + */ + static TrackerEntry createEntry(String tag, String msg) { + TrackerEntry entry = new TrackerEntry(tag, EntryType.LOG_TYPE); + String timestampVal = DateUtils.getCurrentKMLTimestamp(); + entry.setTimestamp(timestampVal); + entry.setLogMsg(msg); + return entry; + } + + private void setTimestamp(String timestamp) { + mTimestamp = timestamp; + } + + EntryType getType() { + return mType; + } + + private void setDistFromNetLocation(float distFromNetLocation) { + mDistFromNetLocation = distFromNetLocation; + } + + private void setLogMsg(String msg) { + mLogMsg = msg; + } + + private void setLocation(Location location) { + mLocation = location; + } + + String getTimestamp() { + return mTimestamp; + } + + String getTag() { + return mTag; + } + + Location getLocation() { + return mLocation; + } + + String getLogMsg() { + return mLogMsg; + } + + float getDistFromNetLocation() { + return mDistFromNetLocation; + } + + static void buildCreationString(StringBuilder builder) { + if (ATTRIBUTES.length != ATTRIBUTES_DATA_TYPE.length) { + throw new IllegalArgumentException( + "Attribute length does not match data type length"); + } + for (int i = 0; i < ATTRIBUTES_DATA_TYPE.length; i++) { + if (i != 0) { + builder.append(", "); + } + builder.append(String.format("%s %s", ATTRIBUTES[i], + ATTRIBUTES_DATA_TYPE[i])); + } + } + + ContentValues getAsContentValues() { + ContentValues cValues = new ContentValues(ATTRIBUTES.length); + cValues.put(TIMESTAMP, mTimestamp); + cValues.put(TAG, mTag); + cValues.put(ENTRY_TYPE, mType.toString()); + if (mType == EntryType.LOCATION_TYPE) { + cValues.put(LATITUDE, mLocation.getLatitude()); + cValues.put(LONGITUDE, mLocation.getLongitude()); + if (mLocation.hasAccuracy()) { + cValues.put(ACCURACY, mLocation.getAccuracy()); + } + if (mLocation.hasAltitude()) { + cValues.put(ALTITUDE, mLocation.getAltitude()); + } + if (mLocation.hasSpeed()) { + cValues.put(SPEED, mLocation.getSpeed()); + } + if (mLocation.hasBearing()) { + cValues.put(BEARING, mLocation.getBearing()); + } + cValues.put(DIST_NET_LOCATION, mDistFromNetLocation); + cValues.put(LOC_TIME, mLocation.getTime()); + StringBuilder debugBuilder = new StringBuilder(""); + if (mLocation.getExtras() != null) { + for (String key : LOCATION_DEBUG_KEYS) { + Object val = mLocation.getExtras().get(key); + if (val != null) { + debugBuilder.append(String.format("%s=%s; ", key, val + .toString())); + } + } + } + cValues.put(DEBUG_INFO, debugBuilder.toString()); + } else { + cValues.put(DEBUG_INFO, mLogMsg); + } + return cValues; + } + + static TrackerEntry createEntry(Cursor cursor) { + String timestamp = cursor.getString(cursor.getColumnIndex(TIMESTAMP)); + String tag = cursor.getString(cursor.getColumnIndex(TAG)); + String sType = cursor.getString(cursor.getColumnIndex(ENTRY_TYPE)); + TrackerEntry entry = new TrackerEntry(tag, EntryType.valueOf(sType)); + entry.setTimestamp(timestamp); + if (entry.getType() == EntryType.LOCATION_TYPE) { + Location location = new Location(tag); + location.setLatitude(cursor.getFloat(cursor + .getColumnIndexOrThrow(LATITUDE))); + location.setLongitude(cursor.getFloat(cursor + .getColumnIndexOrThrow(LONGITUDE))); + + Float accuracy = getNullableFloat(cursor, ACCURACY); + if (accuracy != null) { + location.setAccuracy(accuracy); + } + Float altitude = getNullableFloat(cursor, ALTITUDE); + if (altitude != null) { + location.setAltitude(altitude); + } + Float bearing = getNullableFloat(cursor, BEARING); + if (bearing != null) { + location.setBearing(bearing); + } + Float speed = getNullableFloat(cursor, SPEED); + if (speed != null) { + location.setSpeed(speed); + } + location.setTime(cursor.getLong(cursor.getColumnIndex(LOC_TIME))); + entry.setLocation(location); + } + entry.setLogMsg(cursor.getString(cursor.getColumnIndex(DEBUG_INFO))); + + return entry; + } + + private static Float getNullableFloat(Cursor cursor, String colName) { + Float retValue = null; + int colIndex = cursor.getColumnIndexOrThrow(colName); + if (!cursor.isNull(colIndex)) { + retValue = cursor.getFloat(colIndex); + } + return retValue; + } +} diff --git a/tests/LocationTracker/src/com/google/android/locationtracker/data/TrackerListHelper.java b/tests/LocationTracker/src/com/google/android/locationtracker/data/TrackerListHelper.java new file mode 100644 index 0000000..e292b45b --- /dev/null +++ b/tests/LocationTracker/src/com/google/android/locationtracker/data/TrackerListHelper.java @@ -0,0 +1,75 @@ +/*
+ * Copyright (C) 2008 Google Inc.
+ *
+ * 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.google.android.locationtracker.data;
+
+import android.app.ListActivity;
+import android.content.Context;
+import android.database.Cursor;
+import android.view.View;
+import android.widget.ResourceCursorAdapter;
+import android.widget.TextView;
+
+import com.google.android.locationtracker.R;
+
+/**
+ * Used to bind Tracker data to a list view UI
+ */
+public class TrackerListHelper extends TrackerDataHelper {
+
+ private ListActivity mActivity;
+
+ // sort entries by most recent first
+ private static final String SORT_ORDER = TrackerEntry.ID_COL + " DESC";
+
+ public TrackerListHelper(ListActivity activity) {
+ super(activity, TrackerDataHelper.CSV_FORMATTER);
+ mActivity = activity;
+ }
+
+ /**
+ * Helper method for binding the list activities UI to the tracker data
+ * Tracker data will be sorted in most-recent first order
+ * Will enable automatic UI changes as tracker data changes
+ *
+ * @param layout - layout to populate data
+ */
+ public void bindListUI(int layout) {
+ Cursor cursor = mActivity.managedQuery(TrackerProvider.CONTENT_URI,
+ TrackerEntry.ATTRIBUTES, null, null, SORT_ORDER);
+ // Used to map tracker entries from the database to views
+ TrackerAdapter adapter = new TrackerAdapter(mActivity, layout, cursor);
+ mActivity.setListAdapter(adapter);
+ cursor.setNotificationUri(mActivity.getContentResolver(),
+ TrackerProvider.CONTENT_URI);
+
+ }
+
+ private class TrackerAdapter extends ResourceCursorAdapter {
+
+ public TrackerAdapter(Context context, int layout, Cursor c) {
+ super(context, layout, c);
+ }
+
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ final TextView v = (TextView) view
+ .findViewById(R.id.entrylist_item);
+ String rowText = mFormatter.getOutput(TrackerEntry
+ .createEntry(cursor));
+ v.setText(rowText);
+ }
+ }
+}
diff --git a/tests/LocationTracker/src/com/google/android/locationtracker/data/TrackerProvider.java b/tests/LocationTracker/src/com/google/android/locationtracker/data/TrackerProvider.java new file mode 100644 index 0000000..052d813 --- /dev/null +++ b/tests/LocationTracker/src/com/google/android/locationtracker/data/TrackerProvider.java @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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.google.android.locationtracker.data; + +import android.content.ContentProvider; +import android.content.ContentUris; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.net.Uri; +import android.util.Log; + +/** + * Content provider for location tracking. + * + * It is recommended to use the TrackerDataHelper class to access this data + * rather than this class directly + */ +public class TrackerProvider extends ContentProvider { + + public static final Uri CONTENT_URI = Uri + .parse("content://com.google.android.locationtracker"); + + private static final String DB_NAME = "tracking.db"; + private static final String TABLE_NAME = "tracking"; + private static final int DB_VERSION = 1; + + private static final String LOG_TAG = "TrackerProvider"; + + /** + * This class helps open, create, and upgrade the database file. + */ + private static class DatabaseHelper extends SQLiteOpenHelper { + + DatabaseHelper(Context context) { + super(context, DB_NAME, null, DB_VERSION); + } + + @Override + public void onCreate(SQLiteDatabase db) { + StringBuilder queryBuilder = new StringBuilder(); + queryBuilder.append(String.format("CREATE TABLE %s (", TABLE_NAME)); + TrackerEntry.buildCreationString(queryBuilder); + + queryBuilder.append(");"); + db.execSQL(queryBuilder.toString()); + db.setVersion(DB_VERSION); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + // TODO: reimplement this when dB version changes + Log.w(LOG_TAG, "Upgrading database from version " + oldVersion + + " to " + newVersion + + ", which will destroy all old data"); + db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); + onCreate(db); + } + } + + private DatabaseHelper mOpenHelper; + + @Override + public boolean onCreate() { + mOpenHelper = new DatabaseHelper(getContext()); + return true; + } + + @Override + public int delete(Uri uri, String selection, String[] selectionArgs) { + SQLiteDatabase db = mOpenHelper.getWritableDatabase(); + int result = db.delete(TABLE_NAME, selection, selectionArgs); + getContext().getContentResolver().notifyChange(uri, null); + return result; + } + + @Override + public String getType(Uri uri) { + throw new UnsupportedOperationException(); + } + + @Override + public Uri insert(Uri uri, ContentValues values) { + SQLiteDatabase db = mOpenHelper.getWritableDatabase(); + long rowId = db.insert(TABLE_NAME, null, values); + if (rowId > 0) { + Uri addedUri = ContentUris.withAppendedId(CONTENT_URI, rowId); + getContext().getContentResolver().notifyChange(addedUri, null); + return addedUri; + } + return null; + } + + @Override + public Cursor query(Uri uri, String[] projection, String selection, + String[] selectionArgs, String sortOrder) { + SQLiteDatabase db = mOpenHelper.getReadableDatabase(); + // TODO: extract limit from URI ? + Cursor cursor = db.query(TABLE_NAME, projection, selection, + selectionArgs, null, null, sortOrder); + getContext().getContentResolver().notifyChange(uri, null); + return cursor; + } + + @Override + public int update(Uri uri, ContentValues values, String selection, + String[] selectionArgs) { + throw new UnsupportedOperationException(); + } +} |