├── .gitignore
├── AndroidManifest.xml
├── README.md
├── libs
└── android-support-v13.jar
├── proguard-project.txt
├── project.properties
├── res
├── drawable-hdpi
│ └── ic_launcher.png
├── drawable-ldpi
│ └── ic_launcher.png
├── drawable-mdpi
│ └── ic_launcher.png
├── drawable-xhdpi
│ └── ic_launcher.png
├── layout
│ ├── main.xml
│ └── row.xml
└── values
│ └── strings.xml
└── src
└── com
└── yyl
└── locationservice
├── AlarmReceiver.java
├── LocationServiceActivity.java
├── UpdateLocation.java
└── database
├── LocContentProvider.java
├── LocDatabaseHelper.java
└── LocTable.java
/.gitignore:
--------------------------------------------------------------------------------
1 | # built application files
2 | *.apk
3 | *.ap_
4 |
5 | # files for the dex VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # generated files
12 | bin/
13 | gen/
14 |
15 | # Local configuration file (sdk path, etc)
16 | local.properties
17 |
18 | # Eclipse project files
19 | .classpath
20 | .project
21 |
22 | .DS_Store
23 |
24 |
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
15 |
16 |
19 |
20 |
21 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Android Location Tracking
2 | ===
3 |
4 | **update**: I realized several people forked this recently. This is an old version. New and optimized one could be found in my other repo: [Tracking map on Android](https://github.com/yyl/Tracking-map-on-android).
5 |
6 | This application is used to track user's location regularly and store them into a database in the background. It will work even if user quits it. It has a turn on/off function for user to stop it.
7 |
8 | In this application I use `Sevice`, `AlarmManager`, `Fragment`, `SQLiteOpenHelper`, `Content Provider` and `LoaderManager` classess. It runs on SDK 10 (2.3.3) and up. The `Fragment` class requires support package, which could be downloaded using Android SDK manager.
9 |
10 | I build it as a research tool; feel free to fork or use it.
11 |
--------------------------------------------------------------------------------
/libs/android-support-v13.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yyl/android-location-tracking/f7e9f5a13f30939e4bef54da44d698bf1fd21506/libs/android-support-v13.jar
--------------------------------------------------------------------------------
/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-10
15 |
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yyl/android-location-tracking/f7e9f5a13f30939e4bef54da44d698bf1fd21506/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yyl/android-location-tracking/f7e9f5a13f30939e4bef54da44d698bf1fd21506/res/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yyl/android-location-tracking/f7e9f5a13f30939e4bef54da44d698bf1fd21506/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yyl/android-location-tracking/f7e9f5a13f30939e4bef54da44d698bf1fd21506/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
19 |
20 |
26 |
27 |
33 |
34 |
40 |
41 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/res/layout/row.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
19 |
20 |
25 |
26 |
32 |
33 |
38 |
39 |
40 |
46 |
47 |
52 |
53 | 
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Hello World, LocationServiceActivity!
5 | LocationService
6 |
7 |
--------------------------------------------------------------------------------
/src/com/yyl/locationservice/AlarmReceiver.java:
--------------------------------------------------------------------------------
1 | package com.yyl.locationservice;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.util.Log;
7 |
8 | public class AlarmReceiver extends BroadcastReceiver {
9 |
10 | private static final String DEBUG_TAG = "AlarmReceiver";
11 |
12 | @Override
13 | public void onReceive(Context context, Intent intent) {
14 | Log.d(DEBUG_TAG, "Recurring alarm; requesting location tracking.");
15 | // start the service
16 | Intent tracking = new Intent(context, UpdateLocation.class);
17 | context.startService(tracking);
18 | }
19 | }
--------------------------------------------------------------------------------
/src/com/yyl/locationservice/LocationServiceActivity.java:
--------------------------------------------------------------------------------
1 | package com.yyl.locationservice;
2 | import com.yyl.locationservice.database.*;
3 |
4 | import java.util.Calendar;
5 | import android.app.AlarmManager;
6 | import android.app.PendingIntent;
7 | import android.content.Context;
8 | import android.content.Intent;
9 | import android.database.Cursor;
10 | import android.os.Bundle;
11 | import android.util.Log;
12 | import android.view.View;
13 | import android.widget.ListView;
14 | import android.widget.TextView;
15 | import android.support.v4.content.Loader;
16 | import android.support.v4.widget.SimpleCursorAdapter;
17 | import android.support.v4.app.FragmentActivity;
18 | import android.support.v4.app.LoaderManager;
19 | import android.support.v4.content.CursorLoader;
20 |
21 | public class LocationServiceActivity extends FragmentActivity
22 | implements LoaderManager.LoaderCallbacks{
23 |
24 | private TextView tv;
25 | private PendingIntent tracking;
26 | private AlarmManager alarms;
27 | SimpleCursorAdapter adapter;
28 |
29 | private long UPDATE_INTERVAL = 30000;
30 | private int START_DELAY = 5;
31 | private String DEBUG_TAG = "LocationServiceActivity";
32 |
33 | /** Called when the activity is first created. */
34 | @Override
35 | public void onCreate(Bundle savedInstanceState) {
36 | super.onCreate(savedInstanceState);
37 | setContentView(R.layout.main);
38 | drawTable();
39 | alarms = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
40 | }
41 |
42 | public void start(View view){
43 | tv = (TextView) findViewById(R.id.tv1);
44 | tv.setText("Start tracking");
45 | setRecurringAlarm(getBaseContext());
46 | }
47 |
48 | public void stop(View view){
49 | tv = (TextView) findViewById(R.id.tv1);
50 | tv.setText("Stop tracking");
51 | Intent intent = new Intent(getBaseContext(), AlarmReceiver.class);
52 | tracking = PendingIntent.getBroadcast(getBaseContext(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
53 | alarms = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
54 | alarms.cancel(tracking);
55 | Log.d(DEBUG_TAG, ">>>Stop tracking()");
56 | }
57 |
58 | private void setRecurringAlarm(Context context) {
59 |
60 | // get a Calendar object with current time
61 | Calendar cal = Calendar.getInstance();
62 | // add 5 minutes to the calendar object
63 | cal.add(Calendar.SECOND, START_DELAY);
64 |
65 | Intent intent = new Intent(context, AlarmReceiver.class);
66 |
67 | tracking = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
68 |
69 | alarms.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), UPDATE_INTERVAL, tracking);
70 | }
71 |
72 | @Override
73 | public void onResume() {
74 | super.onResume();
75 | drawTable();
76 | }
77 |
78 | @Override
79 | public void onPause() {
80 | super.onPause();
81 | }
82 |
83 | private void drawTable() {
84 | // Fields from the database (projection)
85 | // Must include the _id column for the adapter to work
86 | String[] from = new String[] { LocTable.COLUMN_ID, LocTable.COLUMN_TIME,
87 | LocTable.COLUMN_LONGITUDE, LocTable.COLUMN_LATITUDE };
88 | // Fields on the UI to which we map
89 | int[] to = new int[] { R.id.rowid, R.id.time, R.id.longitude, R.id.latitude };
90 | getSupportLoaderManager().initLoader(0, null, this);
91 | adapter = new SimpleCursorAdapter(this, R.layout.row, null, from,
92 | to, 0);
93 | ListView listview = (ListView) findViewById(R.id.list);
94 | listview.setAdapter(adapter);
95 | }
96 |
97 | // Creates a new loader after the initLoader () call
98 | @Override
99 | public Loader onCreateLoader(int id, Bundle args) {
100 | String[] projection = { LocTable.COLUMN_ID, LocTable.COLUMN_TIME,
101 | LocTable.COLUMN_LONGITUDE, LocTable.COLUMN_LATITUDE };
102 | CursorLoader cursorLoader = new CursorLoader(this,
103 | LocContentProvider.CONTENT_URI, projection, null, null, null);
104 | return cursorLoader;
105 | }
106 |
107 | @Override
108 | public void onLoadFinished(Loader loader, Cursor data) {
109 | adapter.swapCursor(data);
110 | }
111 |
112 | @Override
113 | public void onLoaderReset(Loader loader) {
114 | // data is not available anymore, delete reference
115 | adapter.swapCursor(null);
116 | }
117 | }
--------------------------------------------------------------------------------
/src/com/yyl/locationservice/UpdateLocation.java:
--------------------------------------------------------------------------------
1 | package com.yyl.locationservice;
2 |
3 | import java.text.DateFormat;
4 | import java.util.TimeZone;
5 |
6 | import com.yyl.locationservice.database.*;
7 |
8 | import android.app.Service;
9 | import android.content.ContentValues;
10 | import android.content.Intent;
11 | import android.location.Criteria;
12 | import android.location.Location;
13 | import android.location.LocationListener;
14 | import android.location.LocationManager;
15 | import android.os.Bundle;
16 | import android.os.Handler;
17 | import android.os.HandlerThread;
18 | import android.os.IBinder;
19 | import android.os.Looper;
20 | import android.os.Message;
21 | import android.util.Log;
22 | import android.widget.Toast;
23 |
24 | public class UpdateLocation extends Service implements
25 | LocationListener{
26 |
27 | private Looper mServiceLooper;
28 | private ServiceHandler mServiceHandler;
29 | private final String DEBUG_TAG = "UpdateLocation::Service";
30 | private LocationManager mgr;
31 | private String best;
32 |
33 |
34 | // Handler that receives messages from the thread
35 | private final class ServiceHandler extends Handler {
36 | public ServiceHandler(Looper looper) {
37 | super(looper);
38 | }
39 |
40 | @Override
41 | public void handleMessage(Message msg) {
42 | Location location = mgr.getLastKnownLocation(best);
43 | mServiceHandler.post(new MakeToast(trackLocation(location)));
44 | // Stop the service using the startId, so that we don't stop
45 | // the service in the middle of handling another job
46 | stopSelf(msg.arg1);
47 | }
48 | }
49 |
50 | @Override
51 | public void onCreate() {
52 | // Start up the thread running the service. Note that we create a
53 | // separate thread because the service normally runs in the process's
54 | // main thread, which we don't want to block. We also make it
55 | // background priority so CPU-intensive work will not disrupt our UI.
56 | HandlerThread thread = new HandlerThread("ServiceStartArguments",
57 | android.os.Process.THREAD_PRIORITY_BACKGROUND);
58 | thread.start();
59 | Log.d(DEBUG_TAG, ">>>onCreate()");
60 | // Get the HandlerThread's Looper and use it for our Handler
61 | mServiceLooper = thread.getLooper();
62 | mServiceHandler = new ServiceHandler(mServiceLooper);
63 | mgr = (LocationManager) getSystemService(LOCATION_SERVICE);
64 | Criteria criteria = new Criteria();
65 | best = mgr.getBestProvider(criteria, true);
66 | mgr.requestLocationUpdates(best, 15000, 1, this);
67 | }
68 |
69 | @Override
70 | public int onStartCommand(Intent intent, int flags, int startId) {
71 | // Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
72 |
73 | // For each start request, send a message to start a job and deliver the
74 | // start ID so we know which request we're stopping when we finish the job
75 | Message msg = mServiceHandler.obtainMessage();
76 | msg.arg1 = startId;
77 | mServiceHandler.sendMessage(msg);
78 | Log.d(DEBUG_TAG, ">>>onStartCommand()");
79 | // If we get killed, after returning from here, restart
80 | return START_STICKY;
81 | }
82 |
83 | @Override
84 | public IBinder onBind(Intent intent) {
85 | // We don't provide binding, so return null
86 | return null;
87 | }
88 |
89 | @Override
90 | public void onDestroy() {
91 | // Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
92 | Log.d(DEBUG_TAG, ">>>onDestroy()");
93 | }
94 |
95 | //obtain current location, insert into database and make toast notification on screen
96 | private String trackLocation(Location location) {
97 | double longitude;
98 | double latitude;
99 | String time;
100 | String result = "Location currently unavailable.";
101 |
102 | // Insert a new record into the Events data source.
103 | // You would do something similar for delete and update.
104 | if (location != null)
105 | {
106 | longitude = location.getLongitude();
107 | latitude = location.getLatitude();
108 | time = parseTime(location.getTime());
109 | ContentValues values = new ContentValues();
110 | values.put(LocTable.COLUMN_TIME, time);
111 | values.put(LocTable.COLUMN_LATITUDE, latitude);
112 | values.put(LocTable.COLUMN_LONGITUDE, longitude);
113 | getContentResolver().insert(LocContentProvider.CONTENT_URI, values);
114 | result = "Location: " + Double.toString(longitude)+", "+Double.toString(latitude);
115 | }
116 | return result;
117 | }
118 |
119 | private String parseTime(long t) {
120 | DateFormat df = DateFormat.getTimeInstance(DateFormat.MEDIUM);
121 | df.setTimeZone(TimeZone.getTimeZone("GMT-4"));
122 | String gmtTime = df.format(t);
123 | return gmtTime;
124 | }
125 |
126 | private class MakeToast implements Runnable {
127 | String txt;
128 |
129 | public MakeToast(String text){
130 | txt = text;
131 | }
132 | public void run(){
133 | Toast.makeText(getApplicationContext(), txt, Toast.LENGTH_SHORT).show();
134 | }
135 | }
136 |
137 | @Override
138 | public void onLocationChanged(Location location) {
139 | // mHandler.post(new MakeToast(trackLocation(location)));
140 | }
141 |
142 | @Override
143 | public void onProviderDisabled(String provider) {
144 | Log.w(DEBUG_TAG, ">>>provider disabled: " + provider);
145 | }
146 |
147 |
148 | @Override
149 | public void onProviderEnabled(String provider) {
150 | Log.w(DEBUG_TAG, ">>>provider enabled: " + provider);
151 | }
152 |
153 |
154 | @Override
155 | public void onStatusChanged(String provider, int status, Bundle extras) {
156 | Log.w(DEBUG_TAG, ">>>provider status changed: " + provider);
157 | }
158 | }
--------------------------------------------------------------------------------
/src/com/yyl/locationservice/database/LocContentProvider.java:
--------------------------------------------------------------------------------
1 | package com.yyl.locationservice.database;
2 |
3 | import java.util.Arrays;
4 | import java.util.HashSet;
5 |
6 | import android.content.ContentProvider;
7 | import android.content.ContentResolver;
8 | import android.content.ContentValues;
9 | import android.content.UriMatcher;
10 | import android.database.Cursor;
11 | import android.database.sqlite.SQLiteDatabase;
12 | import android.database.sqlite.SQLiteQueryBuilder;
13 | import android.net.Uri;
14 | import android.text.TextUtils;
15 |
16 | public class LocContentProvider extends ContentProvider {
17 |
18 | // database
19 | private LocDatabaseHelper database;
20 |
21 | // Used for the UriMacher
22 | private static final int TODOS = 10;
23 | private static final int TODO_ID = 20;
24 |
25 | private static final String AUTHORITY = "com.yyl.locationservice.database";
26 |
27 | private static final String BASE_PATH = "todos";
28 | public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY
29 | + "/" + BASE_PATH);
30 |
31 | public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE
32 | + "/todos";
33 | public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE
34 | + "/todo";
35 |
36 | private static final UriMatcher sURIMatcher = new UriMatcher(
37 | UriMatcher.NO_MATCH);
38 | static {
39 | sURIMatcher.addURI(AUTHORITY, BASE_PATH, TODOS);
40 | sURIMatcher.addURI(AUTHORITY, BASE_PATH + "/#", TODO_ID);
41 | }
42 |
43 | @Override
44 | public boolean onCreate() {
45 | database = new LocDatabaseHelper(getContext());
46 | return false;
47 | }
48 |
49 | @Override
50 | public Cursor query(Uri uri, String[] projection, String selection,
51 | String[] selectionArgs, String sortOrder) {
52 |
53 | // Using SQLiteQueryBuilder instead of query() method
54 | SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
55 |
56 | // Check if the caller has requested a column which does not exists
57 | checkColumns(projection);
58 |
59 | // Set the table
60 | queryBuilder.setTables(LocTable.TABLE_TODO);
61 |
62 | int uriType = sURIMatcher.match(uri);
63 | switch (uriType) {
64 | case TODOS:
65 | break;
66 | case TODO_ID:
67 | // Adding the ID to the original query
68 | queryBuilder.appendWhere(LocTable.COLUMN_ID + "="
69 | + uri.getLastPathSegment());
70 | break;
71 | default:
72 | throw new IllegalArgumentException("Unknown URI: " + uri);
73 | }
74 |
75 | SQLiteDatabase db = database.getWritableDatabase();
76 | Cursor cursor = queryBuilder.query(db, projection, selection,
77 | selectionArgs, null, null, sortOrder);
78 | // Make sure that potential listeners are getting notified
79 | cursor.setNotificationUri(getContext().getContentResolver(), uri);
80 |
81 | return cursor;
82 | }
83 |
84 | @Override
85 | public String getType(Uri uri) {
86 | return null;
87 | }
88 |
89 | @Override
90 | public Uri insert(Uri uri, ContentValues values) {
91 | int uriType = sURIMatcher.match(uri);
92 | SQLiteDatabase sqlDB = database.getWritableDatabase();
93 | long id = 0;
94 | switch (uriType) {
95 | case TODOS:
96 | id = sqlDB.insert(LocTable.TABLE_TODO, null, values);
97 | break;
98 | default:
99 | throw new IllegalArgumentException("Unknown URI: " + uri);
100 | }
101 | getContext().getContentResolver().notifyChange(uri, null);
102 | return Uri.parse(BASE_PATH + "/" + id);
103 | }
104 |
105 | @Override
106 | public int delete(Uri uri, String selection, String[] selectionArgs) {
107 | int uriType = sURIMatcher.match(uri);
108 | SQLiteDatabase sqlDB = database.getWritableDatabase();
109 | int rowsDeleted = 0;
110 | switch (uriType) {
111 | case TODOS:
112 | rowsDeleted = sqlDB.delete(LocTable.TABLE_TODO, selection,
113 | selectionArgs);
114 | break;
115 | case TODO_ID:
116 | String id = uri.getLastPathSegment();
117 | if (TextUtils.isEmpty(selection)) {
118 | rowsDeleted = sqlDB.delete(
119 | LocTable.TABLE_TODO,
120 | LocTable.COLUMN_ID + "=" + id,
121 | null);
122 | } else {
123 | rowsDeleted = sqlDB.delete(
124 | LocTable.TABLE_TODO,
125 | LocTable.COLUMN_ID + "=" + id
126 | + " and " + selection,
127 | selectionArgs);
128 | }
129 | break;
130 | default:
131 | throw new IllegalArgumentException("Unknown URI: " + uri);
132 | }
133 | getContext().getContentResolver().notifyChange(uri, null);
134 | return rowsDeleted;
135 | }
136 |
137 | @Override
138 | public int update(Uri uri, ContentValues values, String selection,
139 | String[] selectionArgs) {
140 |
141 | int uriType = sURIMatcher.match(uri);
142 | SQLiteDatabase sqlDB = database.getWritableDatabase();
143 | int rowsUpdated = 0;
144 | switch (uriType) {
145 | case TODOS:
146 | rowsUpdated = sqlDB.update(LocTable.TABLE_TODO,
147 | values,
148 | selection,
149 | selectionArgs);
150 | break;
151 | case TODO_ID:
152 | String id = uri.getLastPathSegment();
153 | if (TextUtils.isEmpty(selection)) {
154 | rowsUpdated = sqlDB.update(LocTable.TABLE_TODO,
155 | values,
156 | LocTable.COLUMN_ID + "=" + id,
157 | null);
158 | } else {
159 | rowsUpdated = sqlDB.update(LocTable.TABLE_TODO,
160 | values,
161 | LocTable.COLUMN_ID + "=" + id
162 | + " and "
163 | + selection,
164 | selectionArgs);
165 | }
166 | break;
167 | default:
168 | throw new IllegalArgumentException("Unknown URI: " + uri);
169 | }
170 | getContext().getContentResolver().notifyChange(uri, null);
171 | return rowsUpdated;
172 | }
173 |
174 | private void checkColumns(String[] projection) {
175 | String[] available = { LocTable.COLUMN_TIME,
176 | LocTable.COLUMN_LONGITUDE, LocTable.COLUMN_LATITUDE,
177 | LocTable.COLUMN_ID };
178 | if (projection != null) {
179 | HashSet requestedColumns = new HashSet(
180 | Arrays.asList(projection));
181 | HashSet availableColumns = new HashSet(
182 | Arrays.asList(available));
183 | // Check if all columns which are requested are available
184 | if (!availableColumns.containsAll(requestedColumns)) {
185 | throw new IllegalArgumentException(
186 | "Unknown columns in projection");
187 | }
188 | }
189 | }
190 |
191 | }
192 |
--------------------------------------------------------------------------------
/src/com/yyl/locationservice/database/LocDatabaseHelper.java:
--------------------------------------------------------------------------------
1 | package com.yyl.locationservice.database;
2 |
3 | import android.content.Context;
4 | import android.database.sqlite.SQLiteDatabase;
5 | import android.database.sqlite.SQLiteOpenHelper;
6 |
7 | public class LocDatabaseHelper extends SQLiteOpenHelper {
8 |
9 | public static final String DEBUG_TAG = "location table";
10 | private static final String DATABASE_NAME = "loctable.db";
11 | private static final int DATABASE_VERSION = 2;
12 |
13 | public LocDatabaseHelper(Context context) {
14 | super(context, DATABASE_NAME, null, DATABASE_VERSION);
15 | }
16 |
17 | // Method is called during creation of the database
18 | @Override
19 | public void onCreate(SQLiteDatabase database) {
20 | LocTable.onCreate(database);
21 | }
22 |
23 | // Method is called during an upgrade of the database,
24 | // e.g. if you increase the database version
25 | @Override
26 | public void onUpgrade(SQLiteDatabase database, int oldVersion,
27 | int newVersion) {
28 | LocTable.onUpgrade(database, oldVersion, newVersion);
29 | }
30 | }
--------------------------------------------------------------------------------
/src/com/yyl/locationservice/database/LocTable.java:
--------------------------------------------------------------------------------
1 | package com.yyl.locationservice.database;
2 |
3 | import android.database.sqlite.SQLiteDatabase;
4 | import android.util.Log;
5 |
6 | public class LocTable {
7 |
8 | // Database table
9 | public static final String TABLE_TODO = "loc";
10 | public static final String COLUMN_ID = "_id";
11 | public static final String COLUMN_TIME = "time";
12 | public static final String COLUMN_LONGITUDE = "longitude";
13 | public static final String COLUMN_LATITUDE = "latitude";
14 |
15 | // Database creation SQL statement
16 | private static final String DATABASE_CREATE = "create table "
17 | + TABLE_TODO
18 | + " ("
19 | + COLUMN_ID + " integer primary key autoincrement, "
20 | + COLUMN_TIME + " text not null, "
21 | + COLUMN_LONGITUDE + " text not null, "
22 | + COLUMN_LATITUDE + " text not null"
23 | + ");";
24 |
25 | public static void onCreate(SQLiteDatabase database) {
26 | database.execSQL(DATABASE_CREATE);
27 | }
28 |
29 | public static void onUpgrade(SQLiteDatabase database, int oldVersion,
30 | int newVersion) {
31 | Log.w(LocTable.class.getName(), "Upgrading database from version "
32 | + oldVersion + " to " + newVersion
33 | + ", which will destroy all old data");
34 | database.execSQL("DROP TABLE IF EXISTS " + TABLE_TODO);
35 | onCreate(database);
36 | }
37 | }
--------------------------------------------------------------------------------