Move LocationTracker test app from vendor/google to frameworks/base/tests
Change-Id: I49f1bfe2081f2c48fcb22b74aa2377857c2bae6d Signed-off-by: Mike Lockwood <lockwood@android.com>
This commit is contained in:
10
tests/LocationTracker/Android.mk
Normal file
10
tests/LocationTracker/Android.mk
Normal 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)
|
||||
30
tests/LocationTracker/AndroidManifest.xml
Normal file
30
tests/LocationTracker/AndroidManifest.xml
Normal 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>
|
||||
25
tests/LocationTracker/res/layout/entrylist_item.xml
Normal file
25
tests/LocationTracker/res/layout/entrylist_item.xml
Normal 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"
|
||||
/>
|
||||
37
tests/LocationTracker/res/menu/menu.xml
Normal file
37
tests/LocationTracker/res/menu/menu.xml
Normal 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>
|
||||
48
tests/LocationTracker/res/values/strings.xml
Normal file
48
tests/LocationTracker/res/values/strings.xml
Normal 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>
|
||||
63
tests/LocationTracker/res/xml/preferences.xml
Executable file
63
tests/LocationTracker/res/xml/preferences.xml
Executable 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>
|
||||
35
tests/LocationTracker/src/com/android/locationtracker/SettingsActivity.java
Executable file
35
tests/LocationTracker/src/com/android/locationtracker/SettingsActivity.java
Executable 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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, 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 "";
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user