M7350v1_en_gpl

This commit is contained in:
T
2024-09-09 08:52:07 +00:00
commit f9cc65cfda
65988 changed files with 26357421 additions and 0 deletions

View File

@@ -0,0 +1,10 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := LocationTracker
LOCAL_MODULE_TAGS := tests
include $(BUILD_PACKAGE)

View File

@@ -0,0 +1,30 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.locationtracker">
<!-- Permissions for the Location Service -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- Permission for wifi -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- give the location tracker ability to induce device insomnia -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- Permission for SD card -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application android:label="@string/app_label">
<activity android:name="TrackerActivity" android:label="Location Tracker">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".TrackerService" />
<activity android:label="@string/settings_menu" android:name="SettingsActivity" />
<provider android:name=".data.TrackerProvider"
android:authorities="com.android.locationtracker" />
</application>
</manifest>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* Copyright (C) 2006-2008 The Android Open Source Project
*
* 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.
*/
-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/entrylist_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
/>

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/**
* Copyright (c) 2008 The Android Open Source Project
*
* 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.
*/
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/start_service_menu"
android:title="@string/start_service_menu" />
<item android:id="@+id/stop_service_menu"
android:title="@string/stop_service_menu" />
<item android:id="@+id/settings_menu"
android:title="@string/settings_menu" />
<item android:id="@+id/export_sub_menu"
android:title="@string/export_sub_menu">
<menu>
<item android:id="@+id/export_kml"
android:title="@string/export_kml" />
<item android:id="@+id/export_csv"
android:title="@string/export_csv" />
</menu>
</item>
<item android:title="@string/clear_data"
android:id="@+id/clear_data_menu"/>
</menu>

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* Copyright (C) 2008 The Android Open Source Project
*
* 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.
*/
-->
<resources>
<string name="start_service_menu">Start Service</string>
<string name="stop_service_menu">Stop Service</string>
<string name="settings_menu">Settings</string>
<string name="update_preference">Update frequency</string>
<string name="title_mintime_preference">Minimum update time</string>
<string name="summary_mintime_preference">The suggested minimum time interval for location updates, in seconds</string>
<string name="dialog_title_mintime_preference">Minimum update time</string>
<string name="title_mindistance_preference">Minimum distance</string>
<string name="summary_mindistance_preference">Minimum distance interval for location updates, in meters</string>
<string name="dialog_title_mindistance_preference">Minimum distance</string>
<string name="provider_preferences">Location providers</string>
<string name="title_network_preference">Network location</string>
<string name="summary_network_preference">Listen for updates to network location (Wi-Fi/cellid)</string>
<string name="title_gps_preference">GPS location</string>
<string name="summary_gps_preference">Listen for updates to GPS location</string>
<string name="title_signal_preference">Signal strength</string>
<string name="summary_signal_preference">Listen for updates to signal strength</string>
<string name="advanced_preferences">Advanced</string>
<string name="title_advanced_log_preference">Location debug logging</string>
<string name="summary_advanced_preference">Logs detailed location data, only relevant for location/test engineers</string>
<string name="app_label">Location Tracker</string>
<string name="export_sub_menu">Export\u2026</string>
<string name="export_kml">Export As KML</string>
<string name="export_csv">Export As CSV</string>
<string name="clear_data">Clear data</string>
<string name="delete_confirm">All current tracking data will be deleted.</string>
<string name="confirm_title">Clear data</string>
</resources>

View File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2008 The Android Open Source Project
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.
-->
<!-- The Location preferences UI -->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="@string/update_preference">
<EditTextPreference android:key="mintime_preference"
android:defaultValue="0"
android:title="@string/title_mintime_preference"
android:summary="@string/summary_mintime_preference"
android:dialogTitle="@string/dialog_title_mintime_preference" />
<EditTextPreference android:key="mindistance_preference"
android:defaultValue="0"
android:title="@string/title_mindistance_preference"
android:summary="@string/summary_mindistance_preference"
android:dialogTitle="@string/dialog_title_mindistance_preference" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/provider_preferences">
<CheckBoxPreference android:key="network_preference"
android:defaultValue="true"
android:title="@string/title_network_preference"
android:summary="@string/summary_network_preference" />
<CheckBoxPreference android:key="gps_preference"
android:defaultValue="true"
android:title="@string/title_gps_preference"
android:summary="@string/summary_gps_preference" />
<CheckBoxPreference android:key="signal_preference"
android:defaultValue="false"
android:title="@string/title_signal_preference"
android:summary="@string/summary_signal_preference" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/advanced_preferences">
<CheckBoxPreference android:key="advanced_log_preference"
android:defaultValue="false"
android:title="@string/title_advanced_log_preference"
android:summary="@string/summary_advanced_preference" />
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* 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.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);
}
}

View File

@@ -0,0 +1,226 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* 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.android.locationtracker;
import com.android.locationtracker.data.DateUtils;
import com.android.locationtracker.data.TrackerDataHelper;
import com.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);
}
}

View File

@@ -0,0 +1,445 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* 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.android.locationtracker;
import com.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, false);
}
private boolean trackSignalStrength() {
return getPreferences().getBoolean(SIGNAL_PREF, false);
}
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();
}
}
}
}

View File

@@ -0,0 +1,87 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* 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.android.locationtracker.data;
import com.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 "";
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* 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.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);
}
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* 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.android.locationtracker.data;
/**
* interface for formatting tracker data output
*/
interface IFormatter {
String getHeader();
String getOutput(TrackerEntry entry);
String getFooter();
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* 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.android.locationtracker.data;
import com.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();
}
}
}

View File

@@ -0,0 +1,173 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* 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.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;
}
}

View File

@@ -0,0 +1,253 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* 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.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;
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* 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.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.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);
}
}
}

View File

@@ -0,0 +1,126 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* 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.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.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();
}
}