Compare commits

...

279 Commits

Author SHA1 Message Date
Sandor Dornbush 62c9af5cba Release v 1.1.8 2011-08-17 09:34:56 -07:00
Sandor Dornbush a4f16a1f30 Pick up new Chinese translations 2011-08-13 08:25:45 -07:00
Sandor Dornbush 1b595ee7fe Pick up new Chinese translations 2011-08-13 08:24:12 -07:00
Sandor Dornbush fa556e4e33 Merged with head. 2011-08-11 09:28:10 -07:00
Sandor Dornbush 391d718909 Switch widget icons.
Fix errors in finish translation.
2011-08-11 09:06:32 -07:00
Rodrigo Damazio 2ce14e443d Merging to head. 2011-08-08 16:08:38 -03:00
Rodrigo Damazio cdf0a3a3e7 Fixing description/icon in waypoint creation request. 2011-08-07 03:48:59 -03:00
Rodrigo Damazio f00f9a5277 Added APN logging to the signal strength sampler.
(not tested on CDMA)
2011-08-07 03:47:03 -03:00
Ville Muurinen 7112642e89 Merging to head. 2011-08-04 20:50:50 +03:00
Ville Muurinen 3714c21f97 Changed and improved translation based on comments 2011-08-04 20:45:42 +03:00
Rodrigo Damazio 24c49b7f2f Merge with head. 2011-08-01 20:22:31 -03:00
Rodrigo Damazio b16429f3f8 Differentiating between GPS provider unavailable and disabled - unavailable, in some implementations (such as Samsung's) just means it doesn't have a fix.
(Fixes issue 505)
2011-08-01 15:31:42 -03:00
Rodrigo Damazio 27734495f4 Fixing race condition made evident by G1's slowness :) 2011-08-01 14:47:08 -03:00
Rodrigo Damazio 097b338d19 Fixing cupcake uploading by not referencing the Account object. 2011-08-01 14:46:51 -03:00
Sandor Dornbush cbb8450435 Merge with head. 2011-07-28 15:36:01 -07:00
Sandor Dornbush 3b7e0a91bd Tighten up the border. 2011-07-27 21:52:12 -07:00
Rodrigo Damazio d9a1e56282 Review suggestions 2011-07-25 21:33:58 -03:00
Rodrigo Damazio b63e74369c Attempt at working around Samsung bug which crashes the account manager service - the auth token call now synchronously calls 2011-07-22 21:04:15 -03:00
Rodrigo Damazio 4d0ba06cba Getting rid of backported accounts API since it's only used for API levels where we have native accounts. 2011-07-22 21:12:21 -03:00
Rodrigo Damazio c4369dc237 Bundling coding style into the projects themselves.
With this there's no need to manually import the xml files.
Downside is that if we decide to change something, we need import it in all projects (e.g. change in one, save as a template, then select that template on others).
2011-07-21 03:12:14 -03:00
Rodrigo Damazio 99dd212496 Updating main app to Honeycomb MR2.
(downgrading signal strength app to Gingerbread since it doesn't need anything more than that)
2011-07-20 14:27:06 -03:00
Rodrigo Damazio 6e41033ed6 Addressing review suggestions 2011-07-15 13:20:20 -03:00
Rodrigo Damazio 90a5cb7aae Enabling some sensible warnings which are not on by default in Eclipse. 2011-07-15 13:19:14 -03:00
Rodrigo Damazio bccfbaa03b Style and warning fixes. 2011-07-12 20:42:25 -03:00
Rodrigo Damazio e32ff7116d Simplyfing the authentication dance by handling both success and failure together, and both of them outside onActivityResult. 2011-07-12 20:19:59 -03:00
Rodrigo Damazio 00214843cb Improve state handling, specially in cases where SendActivity gets destroyed. 2011-07-12 20:11:47 -03:00
Sandor Dornbush dd4054c4fc Address comments. 2011-07-11 22:50:06 -07:00
Sandor Dornbush 0b40b92340 Clean up code + add pace. 2011-07-11 22:30:49 -07:00
Rodrigo Damazio 60a3c41003 Merge with head. 2011-07-11 18:01:39 -03:00
Sandor Dornbush f501c60de1 Address comments. 2011-07-11 11:32:54 -07:00
Sandor Dornbush b985a935b0 Address comments. 2011-07-07 22:25:41 -07:00
Rodrigo Damazio a2f1790db2 Merge with head. 2011-07-07 18:25:36 -03:00
Sandor Dornbush 5784ab63cc Final widget fixes. 2011-07-05 22:11:05 -07:00
Rodrigo Damazio fd857c2586 Fixing race condition in chart UI update thread. 2011-07-05 23:15:47 -03:00
Sandor Dornbush 29df8762e2 Merge with head. 2011-07-05 16:33:45 -07:00
Sandor Dornbush 32e13c3495 Fix polar tests and sensor strings. 2011-07-05 15:20:04 -07:00
Sandor Dornbush e6151b3b71 Fix polar tests and sensor strings. 2011-07-05 15:19:21 -07:00
Sandor Dornbush 6823b08651 Merge with head. 2011-07-03 15:47:20 -07:00
Sandor Dornbush b588bb02f4 Fix formatting. 2011-07-03 10:02:16 -07:00
Sandor Dornbush faf7b6efa2 Fix widget and address comments. 2011-07-03 09:58:04 -07:00
Rodrigo Damazio 03492da2cd Fixing time-based chart drawing by ensuring data is reloaded and fixing a race condition. 2011-07-01 03:56:33 -03:00
Rodrigo Damazio 8abfc2ada0 Removing old comment 2011-07-01 01:56:34 -03:00
Rodrigo Damazio a262a2ef71 Adressing review suggestion. 2011-07-01 01:11:00 -03:00
Ville Muurinen 435a38f1d1 Removed unnecessary files 2011-06-30 22:47:00 +03:00
Ville Muurinen 91d7db7c01 Added Finnish translation 2011-06-30 19:38:34 +03:00
Rodrigo Damazio e298c88728 "I see dead threads".
Removing handler threads which were left to die, forever alone with nothing to execute.
2011-06-30 04:03:30 -03:00
Rodrigo Damazio d58e7a58d0 Making the target account be selected only once. 2011-06-30 03:44:25 -03:00
Rodrigo Damazio e530412ef0 Adding state persistence for low-memory situations and handling the share action. 2011-06-30 03:20:08 -03:00
Rodrigo Damazio 1d5e2dc4d5 Addressing TODO: Making SendActivity a state machine. 2011-06-30 02:26:01 -03:00
Rodrigo Damazio d0b5faf266 Fixing a couple of race conditions. 2011-06-30 02:24:34 -03:00
Rodrigo Damazio 76e8a39276 Allowing SendActivity to receive sub-activity results (onActivityResult calls). 2011-06-30 02:23:48 -03:00
Rodrigo Damazio 66fe8e694f Addressing review suggestions. 2011-06-29 18:07:00 -03:00
Rodrigo Damazio abd8a230b4 Moving back to managed dialogs to make them still work cross-activity. 2011-06-28 05:58:54 -03:00
Rodrigo Damazio 565662a8aa Minor style fix in authentication classes 2011-06-28 02:38:12 -03:00
Rodrigo Damazio 0f00e71b5e Merging to head. 2011-06-27 05:40:36 -03:00
Rodrigo Damazio 44fea0117d Fixing the closing of send to google dialogs. 2011-06-27 05:20:54 -03:00
Rodrigo Damazio b9b39a24f7 Merging to head 2011-06-27 05:15:32 -03:00
Rodrigo Damazio 358fb87683 Addressing review suggestions 2011-06-24 16:20:29 -03:00
Rodrigo Damazio f0ef73d150 Merging to head. 2011-06-22 17:17:31 -03:00
Rodrigo Damazio 1d2297a5fc Fixing some nits from static analysis. 2011-06-22 17:16:40 -03:00
Rodrigo Damazio 862736bba4 Changing service connection to be a non-singleton, and properly handle its state. 2011-06-22 16:35:40 -03:00
Sandor Dornbush e30dac7cc2 Allow units not in metric. 2011-06-21 22:24:14 -07:00
Sandor Dornbush f97d5fa232 Clean up widget. 2011-06-21 22:00:40 -07:00
Rodrigo Damazio e909616aff Minor reorg in the service - just reordering methods. 2011-06-22 01:59:34 -03:00
Sandor Dornbush be219bbee6 Merged with 1.1.7 2011-06-21 21:19:01 -07:00
Sandor Dornbush 17c1c81b4e Try to clean up widget. 2011-06-21 21:17:03 -07:00
Sandor Dornbush bf0a16c707 Added tag v1.1.7 for changeset a9c635c8e7b4 2011-06-21 21:05:26 -07:00
Sandor Dornbush 86a54feb41 1.1.7 2011-06-21 21:02:57 -07:00
Rodrigo Damazio 2c923470f8 Removing service calls which were just delegates to the provider utils.
These weren't used anywhere, and this change makes a more clear separation between dealing with track data and dealing with the recording service.
2011-06-17 14:04:56 -03:00
Sandor Dornbush 5d26250b45 Revert overzealous argument checking. 2011-06-15 21:48:28 -07:00
Sandor Dornbush 6d90e0bf51 Minor fixes. 2011-06-14 21:43:06 -07:00
Rodrigo Damazio 51df795a8c Fixing leftovers from the merge 2011-06-14 20:48:00 -03:00
Rodrigo Damazio 9ee053e4f9 Merge to head (non-trivial merge) 2011-06-14 20:42:57 -03:00
Sandor Dornbush 4044185ab3 Set product version. 2011-06-14 10:32:37 -07:00
Sandor Dornbush f4fe825162 Fixed analytics. 2011-06-14 10:09:14 -07:00
Sandor Dornbush cb785b89f0 Add simple analytics. 2011-06-13 21:15:37 -07:00
JohnG 8289128399 String array sensor_type_options fix
Reverted .classpath.  (Oops)
Moved move the old strings from arrays.xml to strings.xml.
Created sensor_type_options string for "None" for language support.
2011-06-13 23:09:20 -04:00
Sandor Dornbush e9146f5fc1 Merge. 2011-06-12 22:34:18 -07:00
Sandor Dornbush bc7de458d3 Cap at 254. 2011-06-12 22:28:48 -07:00
Rodrigo Damazio 4aa44331f0 Adding new activity types, contributed by Marius F. 2011-06-10 20:00:47 -03:00
Rodrigo Damazio eada19f516 Addressing review suggestions and fixing text-to-speech initialization. 2011-06-10 19:52:18 -03:00
Sandor Dornbush 63677b1451 Merged widget. 2011-06-09 20:57:48 -07:00
Sandor Dornbush 5789d96a3d Cap cadence in TCX files. 2011-06-09 20:32:24 -07:00
Rodrigo Damazio 0afdeb9bcc Fixing a few less common issues from the Market console. 2011-06-09 22:22:57 -03:00
Rodrigo Damazio 79dd8f4e49 Fixing some of the top issues from the Market console:
- Not trying to show dialogs if activity is going away
- Properly handling when the user doesn't select an account
- Handling unwritable database (due to memory full?)
- Handling NPE from fusion tables upload
- Not trying to touch dialogs when we're about to restart the whole app
2011-06-09 22:07:25 -03:00
Rodrigo Damazio 93f204ba22 Uniformly handling id == 0 (it's not valid, but everywhere we only assume < 0 is invalid, so do the same here) 2011-06-09 19:45:08 -03:00
Rodrigo Damazio 98ad96115a Properly handling invalid track/point/waypoint IDs.
This makes the provider utils implementation return null for those cases, and fixes all callers which didn't check for that.
2011-06-09 19:12:51 -03:00
Rodrigo Damazio ae4ce12c17 Added tag v1.1.6 for changeset 43a7a27cd4f0 2011-06-03 19:23:24 -03:00
Rodrigo Damazio b8767042b4 Released version 1.1.6 2011-06-03 19:23:01 -03:00
Rodrigo Damazio 200e5f3373 Addressing review suggestion. 2011-06-03 11:19:24 -03:00
Rodrigo Damazio ebb68cccfe Fixing imports 2011-06-03 01:26:22 -03:00
Rodrigo Damazio cc4be23802 Fixing Toast calls outside the UI thread. 2011-06-03 01:24:42 -03:00
JohnG 9f44b1695d Merge error fix.
String polar_sensor_type was left out of Sensor Type array.
2011-06-02 20:58:27 -04:00
JohnG 94344deff3 Change sensor_type_options array to support different languages.
Moved sensor_type_options from arrays.xml to arrays_do_not_translate.xml.
Added strings to strings.xml.
2011-06-01 23:20:00 -04:00
Rodrigo Damazio a41994cb41 Review suggestions 2011-06-01 17:34:44 -03:00
Rodrigo Damazio eee6a713fa Clean-up of issues found by static analysis. 2011-06-01 05:23:25 -03:00
Rodrigo Damazio aed28fe503 Cosmetic and unused method changes. 2011-06-01 04:58:34 -03:00
Rodrigo Damazio 7bc72e683b Merging to head. 2011-06-01 02:45:41 -03:00
Rodrigo Damazio 31e386de44 Optimization: getting rid of some objects when the hub is stopped. 2011-06-01 02:02:49 -03:00
Rodrigo Damazio 31737efd87 And the moment we've been all waiting for....MyTracks is no longer a singleton. 2011-06-01 01:44:07 -03:00
Rodrigo Damazio be096b9657 Removing no-longer-necessary methods from the platform adapters. 2011-06-01 01:40:12 -03:00
Rodrigo Damazio 3e773ef94b Making TrackDataHub an application singleton (using the application context to ensure we don't leak MyTracks). 2011-06-01 01:39:51 -03:00
Rodrigo Damazio 111adc917b Getting rid of insertWaypoint singleton dependency. 2011-05-31 03:16:14 -03:00
Rodrigo Damazio 6a1b2861f3 Getting rid of unused DialogManager calls. 2011-05-31 03:10:25 -03:00
Rodrigo Damazio ed3ff01c22 Freeing MyTracks from isRecording() calls. 2011-05-31 03:09:08 -03:00
Rodrigo Damazio 73e4af98cc Cutting service binding and preferences dependencies to the MyTracks singleton. 2011-05-31 02:35:05 -03:00
Rodrigo Damazio 84835428ba Merging to head 2011-05-26 10:01:44 -03:00
Rodrigo Damazio 9f3099ef2b Addressing review suggestions 2011-05-26 09:58:29 -03:00
Rodrigo Damazio 412eed51cd Removing DialogManager test which is no longer needed. 2011-05-25 21:26:07 -03:00
Rodrigo Damazio bd20d1af02 Addressing review suggestions 2011-05-25 21:25:46 -03:00
Rodrigo Damazio a15932cc7f Passing track IDs as URIs instead of extras. 2011-05-25 20:13:49 -03:00
Rodrigo Damazio 8942c31a5c Making the "Show track" button after an import clear the stack. 2011-05-25 19:21:56 -03:00
Rodrigo Damazio 90fe6921e2 Moving track importing out of MyTracks class. 2011-05-25 19:19:21 -03:00
Rodrigo Damazio e8a872d351 Improving intent handling so each activity receives its data type. 2011-05-25 19:17:34 -03:00
Rodrigo Damazio a16ae846ae Added tag v1.1.5 for changeset a34fd36dffc6 2011-05-25 16:20:22 -03:00
Rodrigo Damazio 38de0e352f Releasing 1.1.5 2011-05-25 16:19:54 -03:00
Rodrigo Damazio eeaa50ddcb Removing singleton usage: moving all send and save logic out of the MyTracks class.
This is a non-trivial step: I decentralized dialog creation (since it made no sense to have a single place creating a lot of completely unrelated dialogs), made invisible activities just for sending/saving, and changed menu handling a bit, all to decentralize those functions from MyTracks.

There's still a TODO to handle GET_LOGIN more nicely instead of returning from the depths of auth management into the current activity.
2011-05-25 04:50:21 -03:00
Rodrigo Damazio 16b0d4eb24 Removing singleton usage: chart settings dialog 2011-05-25 02:13:38 -03:00
Rodrigo Damazio 053fb403c5 Merging 2011-05-24 14:19:12 -03:00
Rodrigo Damazio 1d70d4bca0 Merging 2011-05-24 14:18:57 -03:00
Rodrigo Damazio bba04ba1bd If the only listener is a new one (and since for optimization we keep its state as the global state), we want to reset the global state before loading points onto it. 2011-05-24 13:53:26 -03:00
nic e926180605 Updated tests for Zephyr HxM message parsing to check signed/unsigned conversion 2011-05-24 17:35:12 +02:00
nic 958b62f8c7 Reverting change that was proposed in review comments of revision 3dfdbcf78de0 for Line 39: the 0xFF bit mask is necessary as Java byte is -128 to 127, not 0 to 255. 2011-05-24 09:45:06 +02:00
JohnG d238a9e9dd Polar HRM cleanup, take III
Code review of May 20 comments addressed.
2011-05-21 09:01:41 -04:00
Rodrigo Damazio 1588c25fba Merging to head 2011-05-20 14:42:10 -03:00
JohnG fb993a7060 Polar HRM parser tests. 2011-05-20 00:38:39 -04:00
JohnG 6b375614ca Fixes for Polar HRM code review of May 1.
Addressed all comments.  Cleaned up Polar parser mostly.
Added decaying heart rate algo for now.

Tried to reach out to joni to work on merging projects.  No response yet.
2011-05-19 23:00:22 -04:00
Rodrigo Damazio da928fb549 Making data hub tests run considerably faster. 2011-05-19 21:42:40 -03:00
Rodrigo Damazio f657c2f1d1 Adding tests and making minor reorg changes. 2011-05-19 20:59:40 -03:00
nic 594cc0f06d Merge with a128c27963002c1d46170696e1c1045db4e1de87 2011-05-19 16:39:51 +02:00
nic d712bb1988 Updated tests for revisions d6fb857fb559 (Zephyr HxM message parsing) 2011-05-19 16:38:26 +02:00
Rodrigo Damazio d00c92ef99 Fixing incremental loading when there's only a single listener. 2011-05-18 17:55:39 -03:00
Rodrigo Damazio 59a30238eb Merging to head 2011-05-17 01:19:58 -03:00
Rodrigo Damazio cb75c6fbe6 Fixing eclipse warnings all over the project. 2011-05-17 00:15:02 -03:00
Rodrigo Damazio 8056b66714 Fixing sampling frequency calculation. 2011-05-16 23:43:24 -03:00
Rodrigo Damazio e09501d779 Minor reorg in sampling code. 2011-05-16 23:42:49 -03:00
nic 70192222ad - comment from http://code.google.com/r/nic-sensors/source/detail?r=116bf0d1136edaa75c6bb5609b3c16e99ecb1ad8 2011-05-13 08:49:20 +02:00
bartn cc253d4b33 Removed untranslated strings. 2011-05-12 14:51:13 -07:00
bartn 7d3918a1c6 Fix typos in Polish translations and a few missing translations. 2011-05-12 12:25:02 -07:00
nic e759a14909 -comments from http://code.google.com/r/nic-sensors/source/detail?r=7fd41979e22a99d8173fe91df25124e85c1766e9 2011-05-12 09:57:29 +02:00
nic fd5a1c5b4b - integrating comments from code review proposals http://code.google.com/r/sandordornbush-patches/source/detail?r=3dfdbcf78de082edb66a8994ffb604c84945df0d 2011-05-11 11:34:47 +02:00
nic c95dc12a96 Merge with 3dfdbcf78de082edb66a8994ffb604c84945df0d 2011-05-10 10:09:04 +02:00
Nico Laum 70ef5912c2 - new method to calculate an Int from Little Endian data (according to the HxM documentation the data is Little Endian)
- new methods to calculate the CRC8 checksum
- in ZephyrMessageParser the CRC8 now is used in isValid() and the cadence and power values are written to the SensorData objects
2011-05-09 09:53:59 +02:00
Rodrigo Damazio 79bb9db3b9 Backing out changeset f35dbbe86d616e41561839a2316867b8e7e68d88 (broke gmail sharing). 2011-05-06 15:51:46 -03:00
Rodrigo Damazio d3791ea99b Providing network or null locations to activities, in the appropriate situations, and addressing minor style suggestions. 2011-05-06 15:45:35 -03:00
Rodrigo Damazio 5982fed0b8 Fixing sampling for re-registered listeners. 2011-05-04 22:52:34 -03:00
Rodrigo Damazio 1254df2db1 We were already assuming that the sampled-out listeners are a subset of sampled listeners, so optimize state update. 2011-05-04 22:44:36 -03:00
Rodrigo Damazio 8a23af8581 Merge to head. 2011-05-04 22:06:16 -03:00
Rodrigo Damazio 9cabb27c39 Filtering out non-GPS updates 2011-05-04 22:03:20 -03:00
Rodrigo Damazio 5c17437ba6 Assuming that we have a GPS provider until we're told otherwise
(this avoid a startup toast saying we have no GPS).
2011-05-04 21:50:16 -03:00
Rodrigo Damazio 520c3659d2 Fixing clearing of stats at the start of recording. 2011-05-04 21:45:23 -03:00
Rodrigo Damazio 962374b765 Optimizing re-registration of listeners so they receive updates since they were unregistered instead of a full reload. 2011-05-04 20:48:52 -03:00
Rodrigo Damazio 8fcc809299 Standardizing the creator string across exported file formats. 2011-05-04 18:21:49 -03:00
Sandor Dornbush 8eac101082 Fix-up Zephyr
- Add cadence
- Add power
- Check crc
2011-05-03 21:27:45 -07:00
JohnG b1605ac44e Polar parser 2011-05-01 15:15:13 -04:00
JohnG 90afc1e221 Polar parser 2011-05-01 15:14:41 -04:00
JohnG adeba81340 Polar parser 2011-05-01 15:13:55 -04:00
JohnG 8c10b7ba04 Polar parser 2011-05-01 15:13:34 -04:00
JohnG 8aae77ff70 Polar parser 2011-05-01 15:13:06 -04:00
JohnG 7eeacc6268 Polar parser 2011-05-01 15:12:33 -04:00
JohnG 06e02781d2 Polar parser 2011-05-01 15:11:53 -04:00
Rodrigo Damazio 3b5625c663 Adding javadoc to ChartView. 2011-04-30 22:35:59 -03:00
Rodrigo Damazio ea47f93bc1 Breaking down chart drawing methods as suggested by Sandor. 2011-04-30 19:16:13 -03:00
Rodrigo Damazio c33c2de18b Adding missing return 2011-04-30 18:42:18 -03:00
Rodrigo Damazio f125a798bf Fixing a few of the issues in chart drawing. 2011-04-30 04:37:59 -03:00
Rodrigo Damazio 84d7281002 Test fix: Moving tests after the tested classes have moved. 2011-04-30 02:58:44 -03:00
Rodrigo Damazio d98a53ec43 Merging to head. 2011-04-30 02:42:35 -03:00
Rodrigo Damazio ee3026233e Fixing handling of no loaded track. 2011-04-30 02:40:46 -03:00
Rodrigo Damazio 8fb0b69a79 Further splitting the data hub. 2011-04-30 02:39:56 -03:00
Benjamin Hardill b hardill 03ce6c05a9 Remove extra MyTracksProviderUtils instance 2011-04-26 01:10:01 +01:00
Benjamin Hardill b hardill 1d3a03909b Added Track as an extra to the Intent used with Intent.ACTION_SEND
Also removed the Locations ArrayList from the Track writeToParcel and createFromParcel as it's no longer populated
2011-04-26 00:43:20 +01:00
saxman 7020b78faa Removed mytracks prefix from files and variables.
Moved colors to colors.xml.
Code clean-up and more documentation.
2011-04-25 09:00:39 -07:00
saxman f1746b41a2 Added widget for displaying track stats and starting/stopping tracks.
Added track update broadcast to TrackRecordingService.
Added start and end track actions to TrackRecordingService.
2011-04-23 23:59:47 -07:00
Rodrigo Damazio 22b96e4b24 Moving data hub and related classes to content package. 2011-04-23 04:05:58 -03:00
Rodrigo Damazio ddf684f6c6 Removing duplicate import_done string. 2011-04-23 03:00:37 -03:00
Sandor Dornbush cc9d327ea0 Kill second head. 2011-04-21 16:01:08 -07:00
Sandor Dornbush 47e23e3463 Make the empty chart slightly less ugly. 2011-04-21 15:57:59 -07:00
Sandor Dornbush 8feb903021 Fix minor bug in send to fusion tables. 2011-04-19 21:04:29 -07:00
Sandor Dornbush 124172e4d7 Disable import and export while recording. 2011-04-19 20:57:50 -07:00
Sandor Dornbush 9d4367cfac Fix waypoint selection. 2011-04-19 20:43:28 -07:00
Matthew Simmons 6cd9dfce8c Constants.TAG -> TAG 2011-04-12 17:37:10 -04:00
Matthew Simmons 4a3dbe4d60 Move ANT Sensor classes into the ANT subdirectory 2011-04-12 17:32:49 -04:00
Matthew Simmons 062ab5045a Add an enum which stores static data about ANT sensors. 2011-04-12 17:13:11 -04:00
Matthew Simmons ba472d3b7b Allow cancellation of track write 2011-04-12 15:43:54 -04:00
Rodrigo Damazio 82adcf37f4 Fixing stats screen registration. 2011-04-12 15:58:58 -03:00
Rodrigo Damazio 4f23690ab4 Fixing stats screen registration. 2011-04-12 15:22:23 -03:00
Rodrigo Damazio 17481aeb38 French string fix 2011-04-12 15:05:01 -03:00
Matthew Simmons 26adbb1717 code review comments 2011-04-12 13:14:05 -04:00
Matthew Simmons ffd2785499 merge 2011-04-12 12:49:17 -04:00
Rodrigo Damazio 5c6d160cbf Minor cleanup. 2011-04-12 02:00:18 -03:00
Rodrigo Damazio 28a5c5b343 Merging to head. 2011-04-12 01:42:27 -03:00
Rodrigo Damazio 3501fff7fc Fixing first-startup NPE. 2011-04-12 01:23:36 -03:00
Rodrigo Damazio 1988337598 Multiple improvements to the data hub:
* Making registration finer-grained so we only listen to the data we really need.
* Moving the system listener registration to an external class (for testability and readability)
* Adding a unit test (not yet complete)
* Adding documention and cleaning up comments

Still many things TODO:
* Allow pausing of registrations
* Add pause/resume to onPause/onResume of activities
* Move sampling logic out of the hub
* Optimize data reloading when display preferences change
* (maybe) move the data hub and related classes to the "content" package
2011-04-12 01:22:57 -03:00
Sandor Dornbush be2fdd5cfa Merge with ru. 2011-04-11 19:57:51 -07:00
Sandor Dornbush ef0837c514 Address comments. Merge in Rodrigo's Changes. 2011-04-11 19:26:52 -07:00
Sandor Dornbush 252f88e362 Address comments. Merge in Rodrigo's Changes. 2011-04-11 19:24:36 -07:00
Sandor Dornbush 8ba9b47141 Address comments. Add periodic task factories. 2011-04-07 11:55:36 -07:00
Matthew Simmons f984339b13 code review comments 2011-04-06 18:46:14 -04:00
Matthew Simmons a1ff1d2585 Add file export progress 2011-04-06 17:31:48 -04:00
Matthew Simmons 3bbe7d0322 add javadoc 2011-04-06 14:06:19 -04:00
Matthew Simmons 3fd729f1a2 Extract an interface from TrackWriter to ease testing. 2011-04-06 13:49:31 -04:00
Matthew Simmons 375b75c422 merge russian messages 2011-04-06 11:30:15 -04:00
Matthew Simmons 340a1e3e3a merge messages 2011-04-06 11:29:07 -04:00
Sandor Dornbush 8d3ab8f93b Refactor periodic tasks. 2011-04-05 21:34:47 -07:00
Sandor Dornbush 8dc52de871 Merging 2011-04-05 21:21:55 -07:00
Rodrigo Damazio 6ff39be4bf Allowing certain data hub operations to work even if not started yet. 2011-03-26 03:26:57 -07:00
Rodrigo Damazio e2548ac9e2 Merging 2011-03-26 03:03:06 -07:00
Rodrigo Damazio 0ce94ada82 Removing unpopulated comment 2011-03-26 01:54:28 -07:00
Chihau Chau 77a4c4be70 This patch fix some spelling and badly-written issues of the Spanish translation 2011-03-25 10:09:29 -03:00
Sandor Dornbush 9616084769 Merge with head. 2011-03-24 23:05:02 -07:00
Sandor Dornbush 163a246c58 New executers. 2011-03-24 23:00:34 -07:00
Chihau Chau 31efcb4a86 Automated merge with http://mytracks.googlecode.com/hg/ 2011-03-24 10:34:14 -03:00
Chihau Chau 1faea596f8 This patch fix some spelling and badly-written issues in the Spanish translation strings file. 2011-03-24 10:19:32 -03:00
Rodrigo Damazio cd5cb9093c Adding first version of My Tracks i18n tool.
Since this is a first proposal, I'm not yet modifying the xml files to pass validation, except for a small example.
Also keep in mind that the annotations in the XML (rev in a string tag, or KEEP_PARENT) would be inserted automatically by the "translate" module.
2011-03-23 22:07:21 -07:00
Matthew Simmons 9f1bd89a0c Add Russian translation 2011-03-23 19:48:59 -04:00
Matthew Simmons 0908053881 merge 2011-03-23 18:47:38 -04:00
Matthew Simmons 910068bcf5 Move file I/O classes into their own package 2011-03-22 19:43:15 -04:00
Chihau Chau d9ae0ff1bf Fixing some error messages strings for the Spanish translation 2011-03-22 10:56:07 -03:00
Matthew Simmons 4bea1a6e70 merge 1.1.4 release 2011-03-21 20:08:16 -04:00
Matthew Simmons e7873b0fa0 Added tag v1.1.4 for changeset b3ade8b2a8cd 2011-03-21 19:10:00 -04:00
Matthew Simmons c892704ee3 update for 1.1.4 2011-03-21 19:09:13 -04:00
Rodrigo Damazio 7cd44c853a Review suggestions. 2011-03-21 13:43:34 -07:00
Rodrigo Damazio 818b42b97e Finishing Sandor's renaming. 2011-03-21 02:19:06 -07:00
Rodrigo Damazio 5870ba98b4 Review suggestions. 2011-03-21 01:54:39 -07:00
Rodrigo Damazio 19939c985a Merging to Sandor's renaming. 2011-03-21 01:10:26 -07:00
Matthew Simmons 7d65a9ef22 merge 2011-03-18 19:35:53 -04:00
Matthew Simmons eb45f7c3bc 1.1.4 RC1 2011-03-18 19:35:14 -04:00
Sandor Dornbush 90a89c9224 Static import TAG. 2011-03-17 22:43:26 -07:00
Sandor Dornbush e59b52dcac Merge with head. 2011-03-17 21:57:27 -07:00
Matthew Simmons 07d4edef4e add script to find messages in strings files 2011-03-17 19:17:39 -04:00
Matthew Simmons b76c2f7b8d Fix German translation for send_track_body_format. While the name implies
that it's a format string, it isn't.  A subsequent change will rename the
string.
2011-03-17 18:26:55 -04:00
Rodrigo Damazio be414510a4 Merging Matthew's change. 2011-03-16 15:11:39 -07:00
Rodrigo Damazio e4b2052231 Merging my maps code to head. 2011-03-16 14:23:19 -07:00
Matthew Simmons 5066b23603 Increment the TCX author minor version number if the MyTracks which generated it
is a development build.
2011-03-16 16:42:51 -04:00
Rodrigo Damazio 86de9830b4 Merging MapsFacadeImpl into MapsFacade 2011-03-16 13:06:53 -07:00
Rodrigo Damazio 758b5e4810 Referencing Waypoint directly again. 2011-03-16 13:00:11 -07:00
Matthew Simmons 79e2c55c34 Code review comments 2011-03-16 15:59:21 -04:00
Rodrigo Damazio 802cf51cf9 Removing many indirections I had introduced. 2011-03-16 12:58:41 -07:00
Rodrigo Damazio 55d4a90041 Getting rid of the authentication refresher (we can now reference AuthManager) 2011-03-16 12:48:37 -07:00
Rodrigo Damazio cf535a2f8f Getting rid of the strings provider (we can now reference string resources again) 2011-03-16 12:42:20 -07:00
Rodrigo Damazio ba38964e8a Bringing My Maps code back. 2011-03-16 12:38:10 -07:00
Matthew Simmons c943e5dd43 Fix TCX export 2011-03-16 14:04:53 -04:00
Matthew Simmons 65f44da4c9 merge with 1.1.3 release 2011-03-15 12:13:19 -04:00
Matthew Simmons 24c51afa40 Added tag v1.1.3 for changeset 62821d45032d 2011-03-14 16:54:16 -04:00
Matthew Simmons e6739adb35 Update version to 1.1.3 2011-03-14 16:53:17 -04:00
Rodrigo Damazio 06fceb07cc Merging to head 2011-03-11 23:55:53 -03:00
Rodrigo Damazio c87029254c Merging to head 2011-03-11 23:54:30 -03:00
Rodrigo Damazio d52aca1d3d Fixing preference keys. 2011-03-11 23:38:31 -03:00
Rodrigo Damazio 26af05cd01 Merging to head. 2011-03-11 23:14:52 -03:00
Rodrigo Damazio f7750f2a2c Minor style clean-up 2011-03-11 22:56:25 -03:00
Rodrigo Damazio 675b4f55c1 First step of data flow refactoring.
This moves all data source connections into the TrackDataHub.

There are still many things to (re)do here:
- Optimizations about when the listeners are registered
- Optimizations about what data each TrackDataListener is interested in
- When activities are restarting, send new data since they were stopped (instead of doing a full reload)
- Proper double-buffering of Location objects (some listeners are interested in double-buffering all points, while others are only interested in double-buffering sampled points)
- etc.
2011-03-11 22:26:05 -03:00
Matthew Simmons a322439a83 Release 1.1.3 RC1 2011-03-11 18:15:29 -05:00
Matthew Simmons f7a1046c67 Make the impossible null location slightly less impossible so Location doesn't throw an
exception anymore.
2011-03-11 17:37:50 -05:00
Matthew Simmons c17593d932 merge 2011-03-11 17:20:13 -05:00
Matthew Simmons 109d2969a5 Fix test failures by removing the need to mock TrackRecordingService. Android mock appears
to have a problem with TRS and Context.  When it tries to mock either class, it ends up trying
(and failing) to mock DatabaseErrorHandler, which for some reason always fails.
2011-03-11 16:55:10 -05:00
Matthew Simmons 2d3c463bf3 Don't mock MockContext. For some reason Android Mock is unable to do it. As it happens, we
don't really need to mock it anyway.
2011-03-11 16:07:34 -05:00
Matthew Simmons 74073b641f Check for null preferences before trying to use them 2011-03-11 16:06:30 -05:00
boiledorange73 426033f835 Some of words are changed. 2011-03-10 00:42:43 +09:00
boiledorange73 a9ad1e22d6 Trans #2 strings.xml 2011-03-09 01:12:49 +09:00
boiledorange73 903aa014e4 Translation 2011-03-09 00:17:33 +09:00
Sandor Dornbush e058854c3f Stripping MyTracks from class names. 2011-03-07 22:12:52 -08:00
Matthew Simmons c16ce866dc code review comments 2011-03-07 13:54:45 -05:00
Matthew Simmons f9eba950e0 code review comments 2011-03-04 19:23:37 -05:00
Matthew Simmons 3eb53d3195 Rework send-to-google result dialog
Fix Fusion Tables success determination
2011-03-04 08:51:52 -05:00
Rodrigo Damazio 2a5921d3d0 Merging Marian's change to German translation. 2011-03-02 14:20:59 -03:00
Rodrigo Damazio 440c711335 Review suggestions:
- Standard style in XML
- Fixing strict mode violation
2011-03-02 14:03:27 -03:00
Rodrigo Damazio 7ea573123b Adding vacuum call for when a track is deleted (helps reclaim storage space). 2011-03-02 13:48:57 -03:00
Rodrigo Damazio 7f5ce45fad "Fixing" translations after adding preference reset option. 2011-03-02 13:35:56 -03:00
Rodrigo Damazio bd16542e25 Adding option to reset to default settings. 2011-03-02 13:35:39 -03:00
Matthew Simmons b95a696a5a Fix NPE in test execution. 2011-02-28 17:17:35 -05:00
Matthew Simmons b8f40e8314 import static MyTracksConstants.TAG 2011-02-28 16:59:52 -05:00
Matthew Simmons 0bbeff0b5b Use locale-insensitive formatting for GPX files 2011-02-27 20:40:14 -05:00
Rodrigo Damazio 5828e16421 Disabling strict mode death for cursors since the Honeycomb emulator system image triggers it in MapView. 2011-02-25 01:13:13 -03:00
Rodrigo Damazio 8497d2efba Making My Tracks honeycomb-compatible. 2011-02-25 00:45:07 -03:00
Rodrigo Damazio b578d2ced0 Merging to head. 2011-02-24 20:48:45 -03:00
Rodrigo Damazio 239b461f75 Added tag v1.1.2 for changeset e3c158b73e59 2011-02-24 20:23:24 -03:00
Sandor Dornbush 7ada8f18fb Fix chart image axis. 2011-02-23 18:56:53 -08:00
Sandor Dornbush ada42ee57d Request audio focus. 2011-02-22 22:10:03 -08:00
marian.steinbach 8bad6c0f54 Changed references to 'Docs' to 'Text & Tabellen'; Added non-translated lines as comments for easier file comparison; Removed trailing white spaces 2011-02-04 00:39:44 +01:00
246 changed files with 17449 additions and 7497 deletions
+2 -1
View File
@@ -5,4 +5,5 @@ syntax:glob
*/proguard/**
.metadata
MyTracksTest/annotations.log
MyTracks/src/com/google/android/apps/mytracks/io/mymaps
**/*.pyc
**/*.pyo
+1 -2
View File
@@ -3,12 +3,11 @@
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry kind="lib" path="libs/googleloginclient-helper.jar"/>
<classpathentry kind="lib" path="libs/google-common.jar"/>
<classpathentry kind="lib" path="libs/accounts.jar"/>
<classpathentry kind="lib" path="libs/google-api-client-1.2.2-alpha.jar"/>
<classpathentry kind="lib" path="libs/libGoogleAnalytics.jar"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry exported="true" kind="lib" path="/MyTracksLib/libs/protobuf-java-2.3.0-lite.jar"/>
<classpathentry kind="src" path="MyTracksLib_src"/>
<classpathentry kind="lib" path="libs/libmymaps.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
+1
View File
@@ -3,6 +3,7 @@
<name>MyTracks</name>
<comment></comment>
<projects>
<project>MyTracksLib</project>
</projects>
<buildSpec>
<buildCommand>
+338 -1
View File
@@ -1,4 +1,4 @@
#Wed Sep 29 18:44:16 BRT 2010
#Thu Jul 21 03:01:59 BRT 2011
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
@@ -7,6 +7,343 @@ org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
org.eclipse.jdt.core.compiler.problem.deadCode=warning
org.eclipse.jdt.core.compiler.problem.deprecation=warning
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning
org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
org.eclipse.jdt.core.compiler.problem.nullReference=warning
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=disabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
org.eclipse.jdt.core.compiler.problem.unusedImport=warning
org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=disabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
org.eclipse.jdt.core.compiler.source=1.6
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=48
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_assignment=0
org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
org.eclipse.jdt.core.formatter.alignment_for_enum_constants=48
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=48
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
org.eclipse.jdt.core.formatter.blank_lines_after_package=1
org.eclipse.jdt.core.formatter.blank_lines_before_field=0
org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
org.eclipse.jdt.core.formatter.blank_lines_before_method=1
org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
org.eclipse.jdt.core.formatter.blank_lines_before_package=0
org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true
org.eclipse.jdt.core.formatter.comment.format_block_comments=true
org.eclipse.jdt.core.formatter.comment.format_header=false
org.eclipse.jdt.core.formatter.comment.format_html=true
org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
org.eclipse.jdt.core.formatter.comment.format_line_comments=true
org.eclipse.jdt.core.formatter.comment.format_source_code=true
org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
org.eclipse.jdt.core.formatter.comment.line_length=80
org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
org.eclipse.jdt.core.formatter.compact_else_if=true
org.eclipse.jdt.core.formatter.continuation_indentation=2
org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=true
org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_empty_lines=false
org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
org.eclipse.jdt.core.formatter.indentation.size=4
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.join_lines_in_comments=true
org.eclipse.jdt.core.formatter.join_wrapped_lines=true
org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=true
org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
org.eclipse.jdt.core.formatter.lineSplit=80
org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
org.eclipse.jdt.core.formatter.tabulation.char=space
org.eclipse.jdt.core.formatter.tabulation.size=2
org.eclipse.jdt.core.formatter.use_on_off_tags=false
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
@@ -0,0 +1,61 @@
#Thu Jul 21 03:04:13 BRT 2011
eclipse.preferences.version=1
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
formatter_profile=_MyTracks
formatter_settings_version=12
org.eclipse.jdt.ui.ignorelowercasenames=true
org.eclipse.jdt.ui.importorder=com;android;java;javax;org;
org.eclipse.jdt.ui.ondemandthreshold=99
org.eclipse.jdt.ui.staticondemandthreshold=99
sp_cleanup.add_default_serial_version_id=true
sp_cleanup.add_generated_serial_version_id=false
sp_cleanup.add_missing_annotations=true
sp_cleanup.add_missing_deprecated_annotations=true
sp_cleanup.add_missing_methods=false
sp_cleanup.add_missing_nls_tags=false
sp_cleanup.add_missing_override_annotations=true
sp_cleanup.add_missing_override_annotations_interface_methods=true
sp_cleanup.add_serial_version_id=false
sp_cleanup.always_use_blocks=true
sp_cleanup.always_use_parentheses_in_expressions=false
sp_cleanup.always_use_this_for_non_static_field_access=false
sp_cleanup.always_use_this_for_non_static_method_access=false
sp_cleanup.convert_to_enhanced_for_loop=false
sp_cleanup.correct_indentation=false
sp_cleanup.format_source_code=false
sp_cleanup.format_source_code_changes_only=false
sp_cleanup.make_local_variable_final=false
sp_cleanup.make_parameters_final=false
sp_cleanup.make_private_fields_final=true
sp_cleanup.make_type_abstract_if_missing_method=false
sp_cleanup.make_variable_declarations_final=true
sp_cleanup.never_use_blocks=false
sp_cleanup.never_use_parentheses_in_expressions=true
sp_cleanup.on_save_use_additional_actions=false
sp_cleanup.organize_imports=true
sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
sp_cleanup.remove_private_constructors=true
sp_cleanup.remove_trailing_whitespaces=false
sp_cleanup.remove_trailing_whitespaces_all=true
sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
sp_cleanup.remove_unnecessary_casts=true
sp_cleanup.remove_unnecessary_nls_tags=false
sp_cleanup.remove_unused_imports=false
sp_cleanup.remove_unused_local_variables=false
sp_cleanup.remove_unused_private_fields=true
sp_cleanup.remove_unused_private_members=false
sp_cleanup.remove_unused_private_methods=true
sp_cleanup.remove_unused_private_types=true
sp_cleanup.sort_members=false
sp_cleanup.sort_members_all=false
sp_cleanup.use_blocks=false
sp_cleanup.use_blocks_only_for_return_and_throw=false
sp_cleanup.use_parentheses_in_expressions=false
sp_cleanup.use_this_for_non_static_field_access=false
sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
sp_cleanup.use_this_for_non_static_method_access=false
sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+123 -45
View File
@@ -17,8 +17,8 @@ limitations under the License.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.maps.mytracks"
android:installLocation="auto"
android:versionCode="25"
android:versionName="1.1.2">
android:versionCode="31"
android:versionName="1.1.8">
<application android:icon="@drawable/arrow_icon"
android:label="@string/app_name"
android:backupAgent="com.google.android.apps.mytracks.io.backup.MyTracksBackupAgent">
@@ -44,6 +44,109 @@ limitations under the License.
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:mimeType="vnd.android.cursor.item/vnd.google.track" />
</intent-filter>
</activity>
<activity android:name="com.google.android.apps.mytracks.MapActivity"
android:label="MyTracks"
android:exported="false">
<intent-filter>
<category android:name="android.intent.category.TAB" />
</intent-filter>
</activity>
<activity android:name="com.google.android.apps.mytracks.MyMapsList"
android:label="@string/map_list_title"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|fontScale"
android:exported="false" />
<!-- TODO: VIEW and PICK for track cursor dir -->
<activity android:name="com.google.android.apps.mytracks.TrackList"
android:label="Recorded Tracks" />
<!-- TODO: VIEW and PICK for waypoint cursor dir -->
<activity android:name="com.google.android.apps.mytracks.WaypointsList"
android:label="Recorded Waypoints" />
<activity android:name="com.google.android.apps.mytracks.TrackDetails"
android:label="@string/trackdetails_title">
<intent-filter>
<action android:name="android.intent.action.EDIT" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:mimeType="vnd.android.cursor.item/vnd.google.track" />
</intent-filter>
</activity>
<activity android:name="com.google.android.apps.mytracks.WaypointDetails"
android:label="@string/waypointdetails_title">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.EDIT" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:mimeType="vnd.android.cursor.item/vnd.google.waypoint" />
</intent-filter>
</activity>
<activity android:name="com.google.android.apps.mytracks.SettingsActivity"
android:label="@string/mytracks_settings" >
<intent-filter>
<category android:name="android.intent.category.PREFERENCE" />
</intent-filter>
</activity>
<activity android:name="com.google.android.apps.mytracks.AggregatedStatsActivity"
android:label="@string/aggregated_stats" />
<activity android:name="com.google.android.apps.mytracks.StatsActivity"
android:label="@string/statistics"
android:exported="false">
<intent-filter>
<category android:name="android.intent.category.TAB" />
</intent-filter>
</activity>
<activity android:name="com.google.android.apps.mytracks.SensorStateActivity"
android:label="@string/sensor_state" />
<activity android:name="com.google.android.apps.mytracks.ChartActivity"
android:label="@string/elevation_label"
android:exported="false">
<intent-filter>
<category android:name="android.intent.category.TAB" />
</intent-filter>
</activity>
<activity android:name="com.google.android.apps.mytracks.io.sendtogoogle.SendActivity"
android:label="@string/sendtogoogle_title"
android:theme="@android:style/Theme.Translucent.NoTitleBar">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<data android:mimeType="vnd.android.cursor.item/vnd.google.track" />
</intent-filter>
</activity>
<activity android:name="com.google.android.apps.mytracks.io.file.SaveActivity"
android:label="@string/tracklist_write_to_sd"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:noHistory="true">
<intent-filter>
<action android:name="android.intent.action.SAVE" />
<data android:mimeType="vnd.android.cursor.item/vnd.google.track" />
</intent-filter>
</activity>
<activity android:name="com.google.android.apps.mytracks.io.file.ImportActivity"
android:label="@string/import_title"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:noHistory="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.ATTACH_DATA" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="file" />
<data android:mimeType="application/gpx+xml" />
<data android:mimeType="application/gpx" />
@@ -52,44 +155,6 @@ limitations under the License.
</intent-filter>
</activity>
<activity android:name="com.google.android.apps.mytracks.MyTracksMap"
android:label="MyTracks"
android:exported="false" />
<activity android:name="com.google.android.apps.mytracks.MyMapsList"
android:label="@string/map_list_title"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|fontScale"
android:exported="false" />
<activity android:name="com.google.android.apps.mytracks.MyTracksList"
android:label="Recorded Tracks" />
<activity android:name="com.google.android.apps.mytracks.MyTracksWaypointsList"
android:label="Recorded Waypoints" />
<activity android:name="com.google.android.apps.mytracks.MyTracksDetails"
android:label="@string/trackdetails_title" />
<activity android:name="com.google.android.apps.mytracks.MyTracksWaypointDetails"
android:label="@string/waypointdetails_title" />
<activity android:name="com.google.android.apps.mytracks.MyTracksSettings"
android:label="@string/mytracks_settings" />
<activity android:name="com.google.android.apps.mytracks.AggregatedStatsActivity"
android:label="@string/aggregated_stats" />
<activity android:name="com.google.android.apps.mytracks.StatsActivity"
android:label="@string/statistics"
android:exported="false" />
<activity android:name="com.google.android.apps.mytracks.SensorStateActivity"
android:label="@string/sensor_state" />
<activity android:name="com.google.android.apps.mytracks.ChartActivity"
android:label="@string/elevation_label"
android:exported="false" />
<activity android:name="com.google.android.apps.mytracks.WelcomeActivity"
android:label="@string/welcome"
android:exported="false" />
@@ -101,19 +166,31 @@ limitations under the License.
android:exported="true"
android:permission="com.google.android.apps.mytracks.WRITE_TRACK_DATA" />
<receiver android:name="com.google.android.apps.mytracks.MyTracksReceiver">
<receiver android:name="com.google.android.apps.mytracks.BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</intent-filter>
</receiver>
<receiver android:name="com.google.android.apps.mytracks.widgets.TrackWidgetProvider">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="com.google.android.apps.mytracks.TRACK_STARTED" />
<action android:name="com.google.android.apps.mytracks.TRACK_STOPPED" />
<action android:name="com.google.android.apps.mytracks.TRACK_UPDATED" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/track_widget_info" />
</receiver>
</application>
<!-- Permissions to initialize service -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- Permissions for recording tracks and showing maps -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.BLUETOOTH" />
@@ -164,14 +241,15 @@ limitations under the License.
<!-- Features required -->
<uses-feature android:name="android.hardware.location" android:required="true"/>
<uses-feature android:name="android.hardware.location.gps" android:required="true"/>
<uses-feature android:name="android.hardware.touchscreen" android:required="true"/>
<!-- Features optional -->
<uses-feature android:name="android.hardware.bluetooth" android:required="false"/>
<uses-feature android:name="android.hardware.faketouch" android:required="false"/>
<uses-feature android:name="android.hardware.location.network" android:required="false"/>
<uses-feature android:name="android.hardware.sensor.compass" android:required="false"/>
<uses-feature android:name="android.hardware.telephony" android:required="false"/>
<uses-feature android:name="android.hardware.telephony.gsm" android:required="false"/>
<uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
<uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false"/>
<uses-sdk android:minSdkVersion="3"/>
+1 -1
View File
@@ -10,7 +10,7 @@
# Indicates whether an apk should be generated for each density.
split.density=false
# Project target.
target=Google Inc.:Google APIs:9
target=Google Inc.:Google APIs:13
android.library.reference.1=../MyTracksLib/
# ProGuard is turned off while we investigate the removal of code that
-3
View File
@@ -5,9 +5,6 @@ licenses or the JAR's authors.
References are provided to the libraries:
accounts.jar (Android accounts library):
http://code.google.com/p/libs-for-android/wiki/AccountsLibrary
google-api-client-*.jar (GData client):
http://code.google.com/p/google-api-java-client/
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!--
This layout is used as the content view for the send-to-Google result dialog.
It is used to summarize the results of uploading track data to one or more
services.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingTop="5dip"
android:paddingBottom="5dip"
android:paddingLeft="14dip"
android:paddingRight="14dip"
android:orientation="vertical">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/status_track_upload_status"
style="?android:attr/textAppearanceLarge"/>
<TableLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal">
<!-- We don't want a divider, so we set its color to transparent. -->
<!-- We do this explicitly, rather than with a color resource, because -->
<!-- an apparent bug causes the divider to be wildly misrendered on -->
<!-- a Mini X10 running 2.1. -->
<ListView
android:id="@+id/send_to_google_result_list"
android:clickable="false"
android:paddingTop="10dip"
android:paddingBottom="10dip"
android:divider="#00000000"/>
</TableLayout>
<TextView
android:id="@+id/send_to_google_result_comment"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/status_mymap_info"
android:visibility="gone"
style="?android:attr/textAppearanceSmall"/>
<TextView
android:id="@+id/send_to_google_result_error"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/error_please_try_again_later"
android:visibility="gone"
style="?android:attr/textAppearanceLarge"/>
</LinearLayout>
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!--
This layout represents the result of sending track data to a single service.
It will be instantiated by a custom ListAdapter - once for each service to
which track data was uploaded.
-->
<TableRow
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/send_to_google_result_icon"
android:src="@drawable/success"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="top"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/send_to_google_result_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Google Docs"
style="?android:attr/textAppearanceMedium"/>
<TextView
android:id="@+id/send_to_google_result_url"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="http://google.com"
style="?android:attr/textAppearanceSmall"/>
</LinearLayout>
</TableRow>
+90
View File
@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingLeft="10px"
android:paddingRight="10px"
android:paddingTop="5px"
android:paddingBottom="5px">
<LinearLayout
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:background="@drawable/appwidget_background">
<ImageButton
android:id="@+id/appwidget_button"
android:layout_height="fill_parent"
android:layout_width="wrap_content"
android:background="@android:color/transparent"
android:paddingLeft="10px"
android:paddingRight="10px"
android:src="@drawable/appwidget_button_disabled" />
<LinearLayout
android:id="@+id/appwidget_track_statistics"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:layout_weight="1"
android:clickable="true"
android:orientation="vertical"
android:paddingLeft="15px">
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:orientation="horizontal">
<TextView
style="@style/WidgetText.Register"
android:id="@+id/appwidget_distance_text" />
<TextView
style="@style/WidgetText"
android:text="@string/total_distance_label" />
</LinearLayout>
<ImageView
android:layout_width="fill_parent"
android:layout_height="1px"
android:background="@color/appwidget_hr" />
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:orientation="horizontal"
android:paddingBottom="2px">
<TextView
style="@style/WidgetText.Register"
android:id="@+id/appwidget_time_text" />
<TextView
style="@style/WidgetText"
android:text="@string/moving_time_label" />
</LinearLayout>
<ImageView
android:layout_width="fill_parent"
android:layout_height="1px"
android:background="@color/appwidget_hr" />
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:orientation="horizontal">
<TextView
style="@style/WidgetText.Register"
android:id="@+id/appwidget_speed_text" />
<TextView
style="@style/WidgetText"
android:text="@string/speed" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
+5 -10
View File
@@ -112,9 +112,9 @@ limitations under the License.
<item>3.1 miles (senyal GPS pobre)</item>
</string-array>
<!-- Split frequency -->
<string-array name="split_frequency_options">
<item>Sense divisió</item>
<!-- Task frequency -->
<string-array name="task_frequency_options">
<item>Inactiu</item>
<item>100 km</item>
<item>50 km</item>
<item>25 km</item>
@@ -130,8 +130,8 @@ limitations under the License.
<item>1 min</item>
</string-array>
<string-array name="split_frequency_options_ft">
<item>No splitting</item>
<string-array name="task_frequency_options_ft">
<item>Inactiu</item>
<item>100 mi</item>
<item>50 mi</item>
<item>25 mi</item>
@@ -284,9 +284,4 @@ limitations under the License.
<item>punt de referència</item>
</array>
<array name="sensor_type_options">
<item>Cap</item>
<item>Zephyr Bluetooth</item>
</array>
</resources>
+2 -1
View File
@@ -225,7 +225,6 @@ limitations under the License.
<string name="settings_backup_to_sd_summary">Escriu una còpia completa de totes les rutes i els paràmetres a la targeta SD</string>
<string name="settings_restore_from_sd">Restaura ara</string>
<string name="settings_restore_from_sd_summary">Restaura totes les rutes i els paràmetres des de la targeta SD.</string>
<string name="settings_no_backup_while_recording">No es poden gestionar les còpies de seguretat mentre s\'enregistra una ruta.</string>
<!-- Backups -->
<string name="restore_overwrites_warning">La restauració d\'una còpia de seguretat des de la targeta SD sobreescriurà totes les rutes i paràmetres. Esteu segur?</string>
@@ -410,4 +409,6 @@ limitations under the License.
<string name="searching">S\'està cercant</string>
<string name="sending">S\'està enviant</string>
<!-- Sensor Type Options -->
<string name="no_sensor_option">Cap</string>
</resources>
+4 -5
View File
@@ -48,7 +48,6 @@ limitations under the License.
<item>328 Fuß</item>
</string-array>
<!-- Maximum recording distance -->
<string-array name="max_recording_distance_options">
<item>50 m</item>
@@ -113,9 +112,9 @@ limitations under the License.
<item>3,1 Meilen (sehr schlechtes GPS-Signal)</item>
</string-array>
<!-- Split frequency -->
<string-array name="split_frequency_options">
<item>Nicht zerteilen</item>
<!-- Task frequency -->
<string-array name="task_frequency_options">
<item>Aus</item>
<item>100 km</item>
<item>50 km</item>
<item>25 km</item>
@@ -132,7 +131,7 @@ limitations under the License.
</string-array>
<string-array name="split_frequency_options_ft">
<item>Nicht zerteilen</item>
<item>Aus</item>
<item>100 Meilen</item>
<item>50 Meilen</item>
<item>25 Meilen</item>
+393 -367
View File
@@ -1,254 +1,259 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2010 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Used by the Menu -->
<string name="start_recording">Track aufzeichnen</string>
<string name="stop_recording">Aufzeichnung anhalten</string>
<string name="switch_to_sat">Satellitenansicht</string>
<string name="switch_to_map">Kartenansicht</string>
<string name="mylocation">Mein Aufenthaltsort</string>
-->
<resources>
<!-- Used by the Menu -->
<string name="start_recording">Track aufzeichnen</string>
<string name="stop_recording">Aufzeichnung anhalten</string>
<string name="switch_to_sat">Satellitenansicht</string>
<string name="switch_to_map">Kartenansicht</string>
<string name="mylocation">Mein Aufenthaltsort</string>
<!--string name="list_tracks">Tracks</string-->
<string name="list_markers">Wegpunkte</string>
<string name="delete_all_tracks">Alle Tracks löschen</string>
<string name="settings">Einstellungen</string>
<string name="elevation">Höhe</string>
<string name="choose_track_message">Bitte wähle einen Track zur Ansicht aus</string>
<string name="current_track">Aktueller Track</string>
<string name="current_segment">Letztes Segment</string>
<string name="sensor_state">Sensorstatus</string>
<string name="aggregated_stats">Aggregierte Statistiken</string>
<!-- Error messages -->
<string name="error_no_location_manager">Es wurde kein Dienst zur Positionsermittlung auf diesem Gerät gefunden.</string>
<string name="error_no_gps_location_provider">Es wurde kein GPS-Empfänger auf diesem Gerät gefunden.</string>
<string name="error_sending_to_fusiontables">Beim Senden des Tracks an Google Fusion Tables ist ein Fehler aufgetreten. Bitte versuche es später noch einmal.</string>
<string name="error_sending_to_docs">Beim Senden des Tracks an Google Docs ist ein Fehler aufgetreten. Bitte versuche es später noch einmal.</string>
<string name="error_unable_to_start_recording">Start der Aufzeichnung fehlgeschlagen. Bitte versuche es noch einmal.</string>
<string name="error_unable_to_stop_recording">Anhalten unmöglich. Bitte versuche es noch einmal.</string>
<string name="error_unable_to_read_file">Konnte Datei nicht lesen.</string>
<string name="error_invalid_gpx_format">Datei ist nicht im GPX-Format.</string>
<string name="error_generic">Ein Fehler ist aufgetreten. Bitte versuche es noch einmal.</string>
<string name="error_track_does_not_exist">Track existiert nicht.</string>
<string name="error_out_of_memory">Die Datei ist zu groß (maximal 500 KB). Operation abgebrochen.</string>
<string name="error_unable_to_insert_marker">Der Wegpunkt kann nicht einfügt werden. Keine Positionsbestimmung möglich.</string>
<!-- Status messages -->
<string name="wait_for_fix">Warte auf ein besseres GPS-Signal. Bitte stelle sicher, dass der Himmel sichtbar ist.</string>
<string name="status_now_recording">Ein neuer Track wird aufgezeichnet.</string>
<string name="status_stopped_recording">Die Aufzeichnung wurde angehalten.</string>
<string name="status_new_fusiontable_has_been_created">Eine neue Tabelle wurde auf google.com/fusiontables erstellt.</string>
<string name="status_tracks_have_been_uploaded">Dein Track wurde auf maps.google.com gespeichert.</string>
<string name="status_tracks_have_been_uploaded_to_new_doc">Dein Track wurde in einer neuen Tabelle bei docs.google.com gespeichert.</string>
<string name="status_tracks_have_been_uploaded_to_docs">Dein Track wurde an docs.google.com gesendet.</string>
<string name="status_enable_gps">Hier berühren, um zu den Sicherheits- und Positionseinstellungen zu gelangen. Aktiviere \'GPS-Satelliten\'. Drücke dann den Zurück-Knopf, um hierher zurückzukehren.</string>
<string name="status_approximate_location">Anmerkung: Eine ungefähre Position wird angezeigt, bestimmt mittels Mobilfunkstationen und WiFi-Netzwerken.</string>
<string name="status_no_location">Die Position kann derzeit nicht bestimmt werden. Aktiviere mehr Positionsquellen (siehe Sicherheits- und Positionseinstellungen) und stelle sicher, dass der Himmel sichtbar ist.</string>
<string name="status_waypoint_inserted">Ein Wegpunkt wurde eingefügt.</string>
<string name="status_statistics_inserted">Ein Statistikwegpunkt wurde eingefügt.</string>
<!-- Progress dialog -->
<string name="progress_title">Bitte warten…</string>
<string name="progress_message">Dein Track wird an Google gesendet...</string>
<string name="progress_message_reading_track">Lese Track...</string>
<string name="progress_message_preparing_track">Bereite Track vor...</string>
<string name="progress_message_authenticating_fusiontables">Anmeldung bei Google Fusion Tables...</string>
<string name="progress_message_authenticating_docs">Anmeldung bei Google Docs...</string>
<string name="progress_message_sending_docs">Track wird an Google Docs gesendet...</string>
<string name="progress_message_sending_fusiontables">Track wird an Google Fusion Tables gesendet...</string>
<string name="progress_message_creating_fusiontable">Neue \'Fusion Tabelle\' wird erstellt...</string>
<string name="import_progress_message">Importiere GPS-Track. Das kann ein wenig dauern.</string>
<string name="write_progress_message">Schreibe Datei auf SD-Karte. Das kann ein wenig dauern.</string>
<string name="progress_message_updating_track">Aktualisiere Trackstatistik...</string>
<!-- Used by DeleteAllDataHandler -->
<string name="are_you_sure_question">Bist Du Dir wirklich sicher?</string>
<string name="all_data_will_be_permanently_deleted">Alle Tracks und Wegpunkte werden endgültig von diesem Gerät gelöscht.</string>
<string name="track_will_be_permanently_deleted">Dieser Track und seine Wegpunkte werden endgültig von diesem Gerät gelöscht.</string>
<string name="marker_will_be_permanently_deleted">Dieser Wegpunkt wird endgültig von diesem Gerät gelöscht.</string>
<!-- Text and links when uploading to Google Fusion Tables -->
<string name="new_map_description">Erstellt von My Tracks für Android.</string>
<string name="delete_all_tracks">Alle Tracks löschen</string>
<string name="settings">Einstellungen</string>
<string name="elevation">Höhe</string>
<string name="choose_track_message">Bitte wähle einen Track zur Ansicht aus</string>
<string name="current_track">Aktueller Track</string>
<string name="current_segment">Letztes Segment</string>
<string name="sensor_state">Sensorstatus</string>
<string name="aggregated_stats">Aggregierte Statistiken</string>
<!-- Error messages -->
<string name="error_no_location_manager">Es wurde kein Dienst zur Positionsermittlung auf diesem Gerät gefunden.</string>
<string name="error_no_gps_location_provider">Es wurde kein GPS-Empfänger auf diesem Gerät gefunden.</string>
<string name="error_sending_to_fusiontables">Beim Senden des Tracks an Google Fusion Tables ist ein Fehler aufgetreten. Bitte versuche es später noch einmal.</string>
<string name="error_sending_to_docs">Beim Senden des Tracks an Google Text &amp; Tabellen ist ein Fehler aufgetreten. Bitte versuche es später noch einmal.</string>
<string name="error_unable_to_start_recording">Start der Aufzeichnung fehlgeschlagen. Bitte versuche es noch einmal.</string>
<string name="error_unable_to_stop_recording">Anhalten unmöglich. Bitte versuche es noch einmal.</string>
<string name="error_unable_to_read_file">Konnte Datei nicht lesen.</string>
<string name="error_invalid_gpx_format">Datei ist nicht im GPX-Format.</string>
<string name="error_generic">Ein Fehler ist aufgetreten. Bitte versuche es noch einmal.</string>
<string name="error_track_does_not_exist">Track existiert nicht.</string>
<string name="error_out_of_memory">Die Datei ist zu groß (maximal 500 KB). Operation abgebrochen.</string>
<string name="error_unable_to_insert_marker">Der Wegpunkt kann nicht einfügt werden. Keine Positionsbestimmung möglich.</string>
<!-- Status messages -->
<string name="wait_for_fix">Warte auf ein besseres GPS-Signal. Bitte stelle sicher, dass der Himmel sichtbar ist.</string>
<string name="status_now_recording">Ein neuer Track wird aufgezeichnet.</string>
<string name="status_stopped_recording">Die Aufzeichnung wurde angehalten.</string>
<string name="status_new_fusiontable_has_been_created">Eine neue Tabelle wurde auf google.com/fusiontables erstellt.</string>
<string name="status_tracks_have_been_uploaded">Dein Track wurde auf maps.google.com gespeichert.</string>
<string name="status_tracks_have_been_uploaded_to_new_doc">Dein Track wurde in einer neuen Tabelle bei docs.google.com gespeichert.</string>
<string name="status_tracks_have_been_uploaded_to_docs">Dein Track wurde an docs.google.com gesendet.</string>
<string name="status_enable_gps">Hier berühren, um zu den Sicherheits- und Positionseinstellungen zu gelangen. Aktiviere \'GPS-Satelliten\'. Drücke dann den Zurück-Knopf, um hierher zurückzukehren.</string>
<string name="status_approximate_location">Anmerkung: Eine ungefähre Position wird angezeigt, bestimmt mittels Mobilfunkstationen und WiFi-Netzwerken.</string>
<string name="status_no_location">Die Position kann derzeit nicht bestimmt werden. Aktiviere mehr Positionsquellen (siehe Sicherheits- und Positionseinstellungen) und stelle sicher, dass der Himmel sichtbar ist.</string>
<string name="status_waypoint_inserted">Ein Wegpunkt wurde eingefügt.</string>
<string name="status_statistics_inserted">Ein Statistikwegpunkt wurde eingefügt.</string>
<!-- Progress dialog -->
<string name="progress_title">Bitte warten…</string>
<string name="progress_message">Dein Track wird an Google gesendet...</string>
<string name="progress_message_reading_track">Lese Track...</string>
<string name="progress_message_preparing_track">Bereite Track vor...</string>
<string name="progress_message_authenticating_fusiontables">Anmeldung bei Google Fusion Tables...</string>
<string name="progress_message_authenticating_docs">Anmeldung bei Google Text &amp; Tabellen...</string>
<string name="progress_message_sending_docs">Track wird an Google Text &amp; Tabellen gesendet...</string>
<string name="progress_message_sending_fusiontables">Track wird an Google Fusion Tables gesendet...</string>
<string name="progress_message_creating_fusiontable">Neue \'Fusion Tabelle\' wird erstellt...</string>
<string name="import_progress_message">Importiere GPS-Track. Das kann ein wenig dauern.</string>
<string name="write_progress_message">Schreibe Datei auf SD-Karte. Das kann ein wenig dauern.</string>
<string name="progress_message_updating_track">Aktualisiere Trackstatistik...</string>
<!-- Used by DeleteAllDataHandler -->
<string name="are_you_sure_question">Bist Du Dir wirklich sicher?</string>
<string name="all_data_will_be_permanently_deleted">Alle Tracks und Wegpunkte werden endgültig von diesem Gerät gelöscht.</string>
<string name="track_will_be_permanently_deleted">Dieser Track und seine Wegpunkte werden endgültig von diesem Gerät gelöscht.</string>
<string name="marker_will_be_permanently_deleted">Dieser Wegpunkt wird endgültig von diesem Gerät gelöscht.</string>
<!-- Text and links when uploading to Google Fusion Tables -->
<string name="new_map_description">Erstellt von My Tracks für Android.</string>
<string name="fusiontable_link">Erstellt von &lt;a href=\'http://mytracks.appspot.com\'&gt;My Tracks&lt;/a&gt; für Android.</string>
<!-- Formatting of track and marker descriptions -->
<string name="points">Punkte</string>
<string name="recorded_date">Aufgezeichnet am</string>
<string name="category">Aktivität</string>
<string name="waypoint_category">Art des Wegpunktes</string>
<string name="part">(Teil %d)</string>
<!-- Used by the track recording service -->
<!-- Formatting of track and marker descriptions -->
<string name="points">Punkte</string>
<string name="recorded_date">Aufgezeichnet am</string>
<string name="category">Aktivität</string>
<string name="waypoint_category">Art des Wegpunktes</string>
<string name="part">(Teil %d)</string>
<!-- Used by the track recording service -->
<string name="recording_your_track">Dein Track wird aufgezeichnet…</string>
<!-- Common -->
<string name="no">Nein</string>
<string name="yes">Ja</string>
<string name="error">Fehler</string>
<string name="success">Erfolgreich</string>
<string name="waypoint">Wegpunkt</string>
<!--string name="new_track">Track %d</string-->
<!-- Common -->
<string name="no">Nein</string>
<string name="yes">Ja</string>
<!--string name="ok">OK</string-->
<string name="error">Fehler</string>
<string name="success">Erfolgreich</string>
<string name="waypoint">Wegpunkt</string>
<string name="license">Lizenz</string>
<string name="cancel">Abbrechen</string>
<string name="close">Schließen</string>
<string name="edit">Bearbeiten</string>
<string name="save">Sichern</string>
<!-- Placemark labels for start and end of track -->
<string name="end">(Ende)</string>
<!-- TrackList -->
<string name="tracklist_show_track">Anzeigen</string>
<!-- Placemark labels for start and end of track -->
<!--string name="start">(Start)</string-->
<string name="end">(Ende)</string>
<!-- TrackList -->
<string name="tracklist_show_track">Anzeigen</string>
<string name="tracklist_send_to_fusiontables">An eine Google Fusion Tables-Karte senden</string>
<string name="tracklist_send_to_new_fusiontable">An eine neue Google Fusion Tables-Karte senden</string>
<string name="tracklist_send_to_docs">An Google Docs senden</string>
<string name="tracklist_send_to_google">An Google senden…</string>
<string name="tracklist_delete_track">Vom Gerät löschen…</string>
<string name="tracklist_edit_track">Bearbeiten</string>
<string name="tracklist_write_to_sd">Auf SD-Karte speichern…</string>
<string name="tracklist_save_as_gpx">GPX-Datei exportieren</string>
<string name="tracklist_save_as_kml">KML-Datei exportieren</string>
<string name="tracklist_save_as_csv">CSV-Datei exportieren</string>
<string name="tracklist_save_as_tcx">TCX-Datei exportieren</string>
<string name="tracklist_btn_send_all_to_fusiontables">An Google Fusion Tables senden</string>
<string name="tracklist_btn_delete_all">Alle Tracks löschen</string>
<string name="tracklist_send_to_new_fusiontable">An eine neue Google Fusion Tables-Karte senden</string>
<string name="tracklist_send_to_docs">An Google Text &amp; Tabellen senden</string>
<string name="tracklist_send_to_google">An Google senden…</string>
<string name="tracklist_delete_track">Vom Gerät löschen…</string>
<string name="tracklist_edit_track">Bearbeiten</string>
<string name="tracklist_write_to_sd">Auf SD-Karte speichern…</string>
<string name="tracklist_save_as_gpx">GPX-Datei exportieren</string>
<string name="tracklist_save_as_kml">KML-Datei exportieren</string>
<string name="tracklist_save_as_csv">CSV-Datei exportieren</string>
<string name="tracklist_save_as_tcx">TCX-Datei exportieren</string>
<string name="tracklist_btn_send_all_to_fusiontables">An Google Fusion Tables senden</string>
<string name="tracklist_btn_delete_all">Alle Tracks löschen</string>
<!-- Export All -->
<string name="tracklist_btn_export_all">Alle Tracks exportieren</string>
<string name="export_done">Exportieren beendet</string>
<string name="tracklist_pick_one">Einen Track auswählen. Lange berühren für mehr Optionen.</string>
<string name="tracklist_all_tracks">Alle Tracks</string>
<string name="tracklist_this_track">Dieser Track</string>
<string name="tracklist_btn_export_all">Alle Tracks exportieren</string>
<string name="export_done">Exportieren beendet</string>
<string name="tracklist_pick_one">Einen Track auswählen. Lange berühren für mehr Optionen.</string>
<string name="tracklist_all_tracks">Alle Tracks</string>
<string name="tracklist_this_track">Dieser Track</string>
<string name="tracklist_share_track">Mit Freunden teilen…</string>
<string name="tracklist_share_gpx_file">Eine GPX-Datei</string>
<string name="tracklist_share_kml_file">Eine KML-Datei</string>
<string name="tracklist_share_csv_file">Eine CSV-Datei</string>
<string name="tracklist_share_tcx_file">Eine TCX-Datei</string>
<string name="tracklist_clear_map">Karte zurücksetzen.</string>
<!-- Waypoints list -->
<string name="waypointslist_btn_delete_all">Alle Wegpunkte löschen</string>
<string name="waypointslist_this_waypoint">Dieser Wegpunkt</string>
<string name="waypointslist_delete_waypoint">Löschen</string>
<string name="waypointslist_edit_waypoint">Details bearbeiten</string>
<string name="waypointslist_show_waypoint">Auf der Karte zeigen</string>
<string name="waypointslist_btn_insert_waypoint">Wegpunkt einfügen</string>
<string name="waypointslist_btn_insert_statistics">Statistik einfügen</string>
<string name="waypointslist_pick_one">Wegpunkt auswählen. Lange berühren für mehr Optionen.</string>
<!-- MyTracks Details -->
<string name="trackdetails_title">Trackdetails</string>
<string name="trackdetails_name">Name</string>
<string name="trackdetails_description">Beschreibung</string>
<string name="trackdetails_category">Aktivität (z. B. Wandern, Fahrradfahren, Laufen, Klettern…)</string>
<!-- MyTracks Waypoint Details -->
<string name="waypointdetails_title">Wegpunktdetails</string>
<string name="waypointdetails_name">Wegpunktname</string>
<string name="waypointdetails_description">Wegpunktbeschreibung</string>
<string name="waypointdetails_category">Art des Wegpunktes (z. B. Gebäude, Schlagloch, Sehenswürdigkeit…)</string>
<!-- MyTracks Settings -->
<string name="mytracks_settings">Einstellungen für My Tracks</string>
<string name="settings_display">Anzeige</string>
<string name="settings_recording">Aufzeichnung</string>
<string name="settings_sharing">Mit Freunden teilen</string>
<string name="settings_not_available_summary">In dieser Android-Version nicht verfügbar</string>
<string name="settings_announcement_frequency">Dauer zwischen Ansagen</string>
<string name="settings_announcement_frequency_summary">Kürzeste Zeit zwischen zwei Ansagen</string>
<string name="settings_min_recording_distance">Kleinste Entfernung zwischen Punkten</string>
<string name="settings_min_recording_distance_summary">Kleinste Entfernung zwischen zwei Positionsaufzeichnungen</string>
<string name="settings_max_recording_distance">Neues Segment, wenn Punkte weiter entfernt als</string>
<string name="settings_max_recording_distance_summary">Der Track wird in zwei geteilt, wenn zwei folgende Punkte weiter entfernt sind als hier angegeben.</string>
<string name="settings_min_recording_interval">Aufzeichnungsfrequenz</string>
<string name="settings_min_recording_interval_summary">Kürzeste Zeit zwischen zwei Positionsaufzeichnungen</string>
<string name="settings_min_required_accuracy">Aufzeichnung pausieren, wenn Genauigkeit kleiner als</string>
<string name="settings_min_required_accuracy_summary">Die Aufzeichnung wird kurzfristig angehalten, wenn Deine Position nicht genauer als hier angegeben ermittelt werden kann.</string>
<string name="settings_metric_units">Entfernungen in metrischen Einheiten anzeigen</string>
<string name="settings_metric_units_summary_on">Alle Entfernungen werden in metrischen Einheiten angezeigt.</string>
<string name="settings_metric_units_summary_off">Alle Entfernungen werden in imperialen Längeneinheiten angezeigt.</string>
<string name="settings_map_public">Karten auf maps.google.com veröffentlichen</string>
<string name="settings_map_public_summary_on">Hochgeladene Karten auf maps.google.com sind für alle sichtbar.</string>
<string name="settings_map_public_summary_off">Hochgeladene Karten auf maps.google.com werden nicht öffentlich sichtbar aufgelistet.</string>
<string name="settings_report_speed_or_pace">Geschwindigkeitsanzeige</string>
<string name="settings_report_speed_or_pace_summary_on">Geschwindigkeit wird angezeigt.</string>
<string name="settings_report_speed_or_pace_summary_off">Pace wird angezeigt.</string>
<string name="settings_share_url_only">Nur URL als Einladung zum Teilen senden</string>
<string name="settings_share_url_only_summary_on">Beim Teilen mit Freunden wird nur die Karten-URL gesendet.</string>
<string name="settings_share_url_only_summary_off">Beim Teilen mit Freunden wird der GPS-Track selbst gesendet.</string>
<string name="settings_split_frequency">Zerteilungsfrequenz</string>
<string name="settings_split_frequency_summary">Längste Dauer oder Entfernung, nach der automatisch ein Marker eingefügt wird.</string>
<string name="settings_auto_resume_track_timeout">Zeitbegrenzung der Auto-Wiederaufnahme</string>
<string name="settings_auto_resume_track_timeout_summary">Maximale Zeit in Minuten, nach der eine abgebrochene Aufzeichnung nach einem Telefonneustart wiederaufgenommen wird.</string>
<string name="settings_timestamp_track_name">Zeitstempel als Trackname</string>
<string name="settings_timestamp_track_name_summary_on">Der Trackname wird aus Datum und Zeit zum Aufzeichnungsbeginn zusammengesetzt.</string>
<string name="settings_timestamp_track_name_summary_off">Tracknamen erhalten eine fortlaufende Nummer.</string>
<string name="pace_label">Pace</string>
<string name="eclair_required">Wird nur unter Android 2.0 oder höher unterstützt</string>
<string name="settings_sensor_type">Sensortyp</string>
<string name="tracklist_share_linkfusion">Ein Link zur Google Fusion Tables-Karte</string>
<string name="tracklist_share_gpx_file">Eine GPX-Datei</string>
<string name="tracklist_share_kml_file">Eine KML-Datei</string>
<string name="tracklist_share_csv_file">Eine CSV-Datei</string>
<string name="tracklist_share_tcx_file">Eine TCX-Datei</string>
<string name="tracklist_clear_map">Karte zurücksetzen.</string>
<!-- Waypoints list -->
<string name="waypointslist_btn_delete_all">Alle Wegpunkte löschen</string>
<string name="waypointslist_this_waypoint">Dieser Wegpunkt</string>
<string name="waypointslist_delete_waypoint">Löschen</string>
<string name="waypointslist_edit_waypoint">Details bearbeiten</string>
<string name="waypointslist_show_waypoint">Auf der Karte zeigen</string>
<string name="waypointslist_btn_insert_waypoint">Wegpunkt einfügen</string>
<string name="waypointslist_btn_insert_statistics">Statistik einfügen</string>
<string name="waypointslist_pick_one">Wegpunkt auswählen. Lange berühren für mehr Optionen.</string>
<!-- MyTracks Details -->
<string name="trackdetails_title">Trackdetails</string>
<string name="trackdetails_name">Name</string>
<string name="trackdetails_description">Beschreibung</string>
<string name="trackdetails_category">Aktivität (z. B. Wandern, Fahrradfahren, Laufen, Klettern…)</string>
<!-- MyTracks Waypoint Details -->
<string name="waypointdetails_title">Wegpunktdetails</string>
<string name="waypointdetails_name">Wegpunktname</string>
<string name="waypointdetails_description">Wegpunktbeschreibung</string>
<string name="waypointdetails_category">Art des Wegpunktes (z. B. Gebäude, Schlagloch, Sehenswürdigkeit…)</string>
<!-- MyTracks Settings -->
<string name="mytracks_settings">Einstellungen für My Tracks</string>
<string name="settings_display">Anzeige</string>
<string name="settings_recording">Aufzeichnung</string>
<string name="settings_sharing">Mit Freunden teilen</string>
<string name="settings_not_available_summary">In dieser Android-Version nicht verfügbar</string>
<string name="settings_announcement_frequency">Dauer zwischen Ansagen</string>
<string name="settings_announcement_frequency_summary">Kürzeste Zeit zwischen zwei Ansagen</string>
<string name="settings_min_recording_distance">Kleinste Entfernung zwischen Punkten</string>
<string name="settings_min_recording_distance_summary">Kleinste Entfernung zwischen zwei Positionsaufzeichnungen</string>
<string name="settings_max_recording_distance">Neues Segment, wenn Punkte weiter entfernt als</string>
<string name="settings_max_recording_distance_summary">Der Track wird in zwei geteilt, wenn zwei folgende Punkte weiter entfernt sind als hier angegeben.</string>
<string name="settings_min_recording_interval">Aufzeichnungsfrequenz</string>
<string name="settings_min_recording_interval_summary">Kürzeste Zeit zwischen zwei Positionsaufzeichnungen</string>
<string name="settings_min_required_accuracy">Aufzeichnung pausieren, wenn Genauigkeit kleiner als</string>
<string name="settings_min_required_accuracy_summary">Die Aufzeichnung wird kurzfristig angehalten, wenn Deine Position nicht genauer als hier angegeben ermittelt werden kann.</string>
<string name="settings_metric_units">Entfernungen in metrischen Einheiten anzeigen</string>
<string name="settings_metric_units_summary_on">Alle Entfernungen werden in metrischen Einheiten angezeigt.</string>
<string name="settings_metric_units_summary_off">Alle Entfernungen werden in imperialen Längeneinheiten angezeigt.</string>
<string name="settings_map_public">Karten auf maps.google.com veröffentlichen</string>
<string name="settings_map_public_summary_on">Hochgeladene Karten auf maps.google.com sind für alle sichtbar.</string>
<string name="settings_map_public_summary_off">Hochgeladene Karten auf maps.google.com werden nicht öffentlich sichtbar aufgelistet.</string>
<string name="settings_report_speed_or_pace">Geschwindigkeitsanzeige</string>
<string name="settings_report_speed_or_pace_summary_on">Geschwindigkeit wird angezeigt.</string>
<string name="settings_report_speed_or_pace_summary_off">Pace wird angezeigt.</string>
<string name="settings_share_url_only">Nur URL als Einladung zum Teilen senden</string>
<string name="settings_share_url_only_summary_on">Beim Teilen mit Freunden wird nur die Karten-URL gesendet.</string>
<string name="settings_share_url_only_summary_off">Beim Teilen mit Freunden wird der GPS-Track selbst gesendet.</string>
<string name="settings_split_frequency">Zerteilungsfrequenz</string>
<string name="settings_split_frequency_summary">Längste Dauer oder Entfernung, nach der automatisch ein Marker eingefügt wird.</string>
<string name="settings_auto_resume_track_timeout">Zeitbegrenzung der Auto-Wiederaufnahme</string>
<string name="settings_auto_resume_track_timeout_summary">Maximale Zeit in Minuten, nach der eine abgebrochene Aufzeichnung nach einem Telefonneustart wiederaufgenommen wird.</string>
<string name="settings_timestamp_track_name">Zeitstempel als Trackname</string>
<string name="settings_timestamp_track_name_summary_on">Der Trackname wird aus Datum und Zeit zum Aufzeichnungsbeginn zusammengesetzt.</string>
<string name="settings_timestamp_track_name_summary_off">Tracknamen erhalten eine fortlaufende Nummer.</string>
<string name="pace_label">Pace</string>
<string name="eclair_required">Wird nur unter Android 2.0 oder höher unterstützt</string>
<string name="settings_sensor_type">Sensortyp</string>
<string name="settings_sensor_type_summary">Der Typ des zu verbindenden Sensors</string>
<string name="settings_heart_rate_ant_sensor_id">Verbindung mit ANT Herzqrequenzmesser aufheben</string>
<string name="settings_power_ant_sensor_id">Verbindung mit ANT Kraftmesser aufheben</string>
<string name="settings_srm_bridge_ant_sensor_id">Verbindung mit ANT srm bridge aufheben</string>
<string name="settings_ant_not_paired">ANT-Sensor nicht verbunden</string>
<string name="settings_ant_paired">ANT-Sensor verbunden mit: %d</string>
<string name="bluetooth_sensor_title">Bluetooth-Sensor</string>
<string name="bluetooth_sensor_summary">Der zu verbindende Bluetoothsensor</string>
<string name="settings_modular_stats_display_title">Art der Datenanzeige</string>
<!-- Backups -->
<string name="settings_backup">Datensicherung (BETA)</string>
<string name="settings_sd_backup">SD-Karten-Sicherung</string>
<string name="settings_backup_to_sd">Jetzt sichern</string>
<string name="settings_backup_to_sd_summary">Eine Kopie aller Deiner Tracks und Einstellungen auf die SD-Karte schreiben</string>
<string name="settings_restore_from_sd">Jetzt wiederherstellen</string>
<string name="settings_restore_from_sd_summary">Alle Tracks und Einstellungen von der SD-Karte holen.</string>
<string name="settings_no_backup_while_recording">Während ein Track aufgezeichnet wird, kann nicht mit der Datensicherung gearbeitet werden.</string>
<string name="restore_overwrites_warning">Eine Wiederherstellung von der SD-Karte ÜBERSCHREIBT alle vorhandenen Tracks und Einstellungen. Willst Du das wirklich?</string>
<string name="select_backup_to_restore">Wähle die wiederherzustellende Datensicherung aus</string>
<string name="no_backups">Keine Datensicherungen gefunden.</string>
<string name="backup_write_progress_message">Schreibe alle Tracks und Einstellungen auf die SD-Karte. Dies kann eine Weile dauern...</string>
<string name="backup_import_progress_message">Lese alle Tracks und Einstellungen von der SD-Karte. Dies kann eine Weile dauern...</string>
<!-- MyTracksSky -->
<string name="mytracks_sky">GPS-Satelliten</string>
<string name="bluetooth_sensor_title">Bluetooth-Sensor</string>
<string name="bluetooth_sensor_summary">Der zu verbindende Bluetoothsensor</string>
<string name="settings_modular_stats_display_title">Art der Datenanzeige</string>
<!-- Sharing -->
<!-- Backups -->
<string name="settings_backup">Datensicherung (BETA)</string>
<string name="settings_sd_backup">SD-Karten-Sicherung</string>
<string name="settings_backup_to_sd">Jetzt sichern</string>
<string name="settings_backup_to_sd_summary">Eine Kopie aller Deiner Tracks und Einstellungen auf die SD-Karte schreiben</string>
<string name="settings_restore_from_sd">Jetzt wiederherstellen</string>
<string name="settings_restore_from_sd_summary">Alle Tracks und Einstellungen von der SD-Karte holen.</string>
<string name="settings_no_backup_while_recording">Während ein Track aufgezeichnet wird, kann nicht mit der Datensicherung gearbeitet werden.</string>
<string name="restore_overwrites_warning">Eine Wiederherstellung von der SD-Karte ÜBERSCHREIBT alle vorhandenen Tracks und Einstellungen. Willst Du das wirklich?</string>
<string name="select_backup_to_restore">Wähle die wiederherzustellende Datensicherung aus</string>
<string name="no_backups">Keine Datensicherungen gefunden.</string>
<string name="backup_write_progress_message">Schreibe alle Tracks und Einstellungen auf die SD-Karte. Dies kann eine Weile dauern...</string>
<string name="backup_import_progress_message">Lese alle Tracks und Einstellungen von der SD-Karte. Dies kann eine Weile dauern...</string>
<!-- MyTracksSky -->
<string name="mytracks_sky">GPS-Satelliten</string>
<!-- Sharing -->
<string name="share_map">Karte mit Freunden teilen</string>
<string name="share_map_subject">Ich möchte gerne eine Karte mit Dir teilen.</string>
<string name="share_map_subject">Ich möchte gerne eine Karte mit Dir teilen.</string>
<string name="share_map_body_format">Vielleicht interessierst Du Dich für diese Karte:
%s</string>
<string name="send_track_subject">Ich möchte einen GPS-Track mit Dir teilen</string>
%s</string>
<string name="send_track_subject">Ich möchte einen GPS-Track mit Dir teilen</string>
<string name="send_track_body_format">Vielleicht interessierst Du Dich für diese Track:
%s.</string>
Der Track kann mit Google Earth oder anderer Karten-Software visualisiert werden.</string>
<string name="share_track">Track mit Freunden teilen</string>
<!-- Visibility -->
@@ -256,126 +261,145 @@ limitations under the License.
<string name="unlisted_map">Nicht in Suchergebnissen enthalten.</string>
<string name="mapslist_no_maps_available">Du hast noch keine Karten.</string>
<!-- Statistics View -->
<!-- Average Moving -->
<string name="average_moving_speed_label">Durchschnitt in Bew.</string>
<string name="average_moving_pace_label">Pace in Bew.</string>
<!-- Average -->
<string name="average_speed_label">Durchschnittsgeschw.</string>
<string name="average_pace_label">Durchschnitts-Pace</string>
<string name="elevation_chart_name">Höhenprofil</string>
<string name="elevation_gain_label">Höhengewinn</string>
<string name="elevation_label">Höhe</string>
<string name="latitude_label">Breitengrad</string>
<string name="longitude_label">Längengrad</string>
<!-- Min -->
<string name="min_elevation_label">Niedrigste Höhenlage</string>
<string name="min_grade_label">Minimale Steigung</string>
<string name="min_pace_label">Minimaler Pace</string>
<!-- Max -->
<string name="max_elevation_label">Höchste Höhenlage</string>
<string name="max_grade_label">Maximale Steigung</string>
<string name="max_speed_label">Max. Geschwindigkeit</string>
<string name="loading_track">Lade Track…</string>
<!-- Chart Settings -->
<string name="chart_settings">Diagramm-Einstellungen</string>
<!-- X Axis -->
<string name="x_axis">X-Achse</string>
<string name="by_distance">Nach Entfernung</string>
<string name="by_time">Nach Zeit</string>
<!-- Y Axis -->
<string name="y_axis">Y-Achse</string>
<!-- Units -->
<!-- Time -->
<string name="hour">Stunde</string>
<string name="hours">Stunden</string>
<string name="hr">Std</string>
<string name="minute">Minute</string>
<string name="minutes">Minuten</string>
<string name="second">Sekunde</string>
<string name="seconds">Sekunden</string>
<!-- Distance -->
<!-- Statistics View -->
<!-- Average Moving -->
<string name="average_moving_speed_label">Durchschnitt in Bew.</string>
<string name="average_moving_pace_label">Pace in Bew.</string>
<!-- Average -->
<string name="average_speed_label">Durchschnittsgeschw.</string>
<string name="average_pace_label">Durchschnitts-Pace</string>
<string name="elevation_chart_name">Höhenprofil</string>
<string name="elevation_gain_label">Höhengewinn</string>
<string name="elevation_label">Höhe</string>
<string name="latitude_label">Breitengrad</string>
<string name="longitude_label">Längengrad</string>
<!-- Min -->
<string name="min_elevation_label">Niedrigste Höhenlage</string>
<string name="min_grade_label">Minimale Steigung</string>
<string name="min_pace_label">Minimaler Pace</string>
<!-- Max -->
<string name="max_elevation_label">Höchste Höhenlage</string>
<string name="max_grade_label">Maximale Steigung</string>
<string name="max_speed_label">Max. Geschwindigkeit</string>
<string name="loading_track">Lade Track…</string>
<!-- Chart Settings -->
<string name="chart_settings">Diagramm-Einstellungen</string>
<!-- X Axis -->
<string name="x_axis">X-Achse</string>
<string name="by_distance">Nach Entfernung</string>
<string name="by_time">Nach Zeit</string>
<!-- Y Axis -->
<string name="y_axis">Y-Achse</string>
<!-- Units -->
<!-- Time -->
<string name="hour">Stunde</string>
<string name="hours">Stunden</string>
<string name="hr">Std</string>
<string name="min">Min</string>
<string name="minute">Minute</string>
<string name="minutes">Minuten</string>
<string name="second">Sekunde</string>
<string name="seconds">Sekunden</string>
<!--string name="milliseconds">ms</string-->
<!-- Distance -->
<!--string name="meter">m</string-->
<!--string name="kilometer">km</string-->
<string name="kilometers_long">Kilometer</string>
<string name="feet">Fuß</string>
<string name="miles_long">Meilen</string>
<!-- Speed and Pace -->
<string name="kilometer_per_hour_long">Kilometer pro Stunde</string>
<string name="per_kilometer">pro Kilometer</string>
<string name="mile_per_hour_long">Meilen pro Stunde</string>
<string name="per_mile">pro Meile</string>
<!--string name="mile">mi</string-->
<string name="miles_long">Meilen</string>
<!-- Stats Labels -->
<string name="moving_time_label">Zeit in Bewegung</string>
<string name="total_time_label">Gesamtzeit</string>
<string name="time_label">Zeit</string>
<string name="sd_unavail">SD-Karte nicht verfügbar</string>
<string name="speed">Geschwindigkeit</string>
<string name="start_trip">Du musst erst eine Aufzeichnung beginnen.</string>
<string name="statistics">Statistik</string>
<string name="total_distance_label">Gesamtentfernung</string>
<string name="distance_label">Entfernung</string>
<string name="power">Kraft</string>
<string name="cadence">Kadenz</string>
<string name="heart_rate">Herzfrequenz</string>
<string name="max_heart_rate">Höchste Herzfrequenz</string>
<string name="waiting">Bitte warten…</string>
<!-- End User License Agreement -->
<string name="eula_title">Lizenzvereinbarung für Endverbraucher</string>
<string name="accept">Akzeptieren</string>
<string name="decline">Ablehnen</string>
<!-- About -->
<string name="about">Über</string>
<string name="help">Hilfe</string>
<!-- Speed and Pace -->
<!--string name="kilometer_per_hour">km/h</string-->
<string name="kilometer_per_hour_long">Kilometer pro Stunde</string>
<!--string name="min_per_kilometer">min/km</string-->
<string name="per_kilometer">pro Kilometer</string>
<!--string name="mile_per_hour">mi/h</string-->
<string name="mile_per_hour_long">Meilen pro Stunde</string>
<!--string name="min_per_mile">min/mi</string-->
<string name="per_mile">pro Meile</string>
<!-- Sensors -->
<!--string name="watts">W</string-->
<!--string name="revolutions_per_minute">rpm</string-->
<!--string name="bpm">bpm</string-->
<!-- Stats Labels -->
<string name="moving_time_label">Zeit in Bewegung</string>
<string name="total_time_label">Gesamtzeit</string>
<string name="time_label">Zeit</string>
<string name="sd_unavail">SD-Karte nicht verfügbar</string>
<string name="speed">Geschwindigkeit</string>
<string name="start_trip">Du musst erst eine Aufzeichnung beginnen.</string>
<string name="statistics">Statistik</string>
<string name="total_distance_label">Gesamtentfernung</string>
<string name="distance_label">Entfernung</string>
<string name="power">Kraft</string>
<string name="cadence">Kadenz</string>
<string name="heart_rate">Herzfrequenz</string>
<string name="max_heart_rate">Höchste Herzfrequenz</string>
<!--string name="unknown">-</string-->
<string name="waiting">Bitte warten…</string>
<!-- End User License Agreement -->
<string name="eula_title">Lizenzvereinbarung für Endverbraucher</string>
<string name="accept">Akzeptieren</string>
<string name="decline">Ablehnen</string>
<!-- About -->
<string name="about">Über</string>
<string name="help">Hilfe</string>
<!--string name="about_team">Team:</string-->
<!--string name="about_version">Version:</string-->
<string name="about_support">Unterstützung:</string>
<string name="about_privacy">Datenschutz:</string>
<!-- Send to Google -->
<string name="sendtogoogle_title">Senden an…</string>
<!--string name="sendtogoogle_google_fusiontables">Google Fusion Tables</string-->
<string name="sendtogoogle_google_docs">Google Text &amp; Tabellen</string>
<string name="sendtogoogle_send_now">Jetzt senden</string>
<string name="sendtogoogle_send_stats">Trackstatistik senden</string>
<string name="sendtogoogle_send_stats_and_points">Statistik und Punkte senden</string>
<!-- Getting the account to upload to. -->
<string name="no_account_found_title">Kein Konto vorhanden</string>
<string name="no_account_found">Kein Konto gefunden, um Tracks zu versenden.</string>
<string name="choose_account_title">Wähle ein Konto</string>
<!-- SD card -->
<string name="io_no_external_storage_found">Keine externes Speichermedium verfügbar. Stelle sicher, dass eine SD-Karte vorhanden ist und nicht bereits von einem Computer darauf zugegriffen wird.</string>
<string name="io_write_failed">Die Datei kann nicht geschrieben werden.</string>
<string name="io_read_failed">Die Datei konnte nicht gelesen werden.</string>
<string name="io_create_dir_failed">Das Verzeichnis auf der SD-Karte kann nicht erstellt werden.</string>
<string name="io_write_finished">Der Track wurde auf die SD-Karte geschrieben.</string>
<string name="io_read_finished">Lesen von der SD-Karte beendet.</string>
<!-- VersionChecker -->
<string name="version_check_title">Suche nach neuer Version</string>
<string name="version_check_upgrade_button">Jetzt aktualisieren</string>
<string name="version_check_continue_button">Fortfahren, ohne zu aktualisieren</string>
<string name="upgrade_required">Deine Version von %1$s funktioniert möglicherweise nicht mehr richtig und wird nicht mehr unterstützt. Bitte aktualisiere %1$s.</string>
<string name="upgrade_recommended">Deine Version von %1$s funktioniert möglicherweise nicht mehr richtig. Du kannst sie jetzt aktualisieren, oder auf sie auf eigene Gefahr weiterverwenden. Einige Funktionen wie Datenaustausch mit Google-Diensten werden möglicherweise nicht mehr funktionieren, solange Du die Software nicht aktualisierst.</string>
<string name="upgrade_available">Eine neue Version von %1$s ist jetzt verfügbar. Du kannst Deine installierte Version ohne Probleme weiterverwenden, aber um die neuesten Funktionen in Anspruch nehmen zu können, musst Du die Software aktualisieren.</string>
<!-- Welcome -->
<string name="welcome">Willkommen</string>
<string name="sendtogoogle_send_now">Jetzt senden</string>
<string name="sendtogoogle_send_stats">Trackstatistik senden</string>
<string name="sendtogoogle_send_stats_and_points">Statistik und Punkte senden</string>
<!-- Getting the account to upload to. -->
<string name="no_account_found_title">Kein Konto vorhanden</string>
<string name="no_account_found">Kein Konto gefunden, um Tracks zu versenden.</string>
<string name="choose_account_title">Wähle ein Konto</string>
<!-- SD card -->
<string name="io_no_external_storage_found">Keine externes Speichermedium verfügbar. Stelle sicher, dass eine SD-Karte vorhanden ist und nicht bereits von einem Computer darauf zugegriffen wird.</string>
<string name="io_write_failed">Die Datei kann nicht geschrieben werden.</string>
<string name="io_read_failed">Die Datei konnte nicht gelesen werden.</string>
<string name="io_create_dir_failed">Das Verzeichnis auf der SD-Karte kann nicht erstellt werden.</string>
<string name="io_write_finished">Der Track wurde auf die SD-Karte geschrieben.</string>
<string name="io_read_finished">Lesen von der SD-Karte beendet.</string>
<!-- VersionChecker -->
<string name="version_check_title">Suche nach neuer Version</string>
<string name="version_check_upgrade_button">Jetzt aktualisieren</string>
<string name="version_check_continue_button">Fortfahren, ohne zu aktualisieren</string>
<string name="upgrade_required">Deine Version von %1$s funktioniert möglicherweise nicht mehr richtig und wird nicht mehr unterstützt. Bitte aktualisiere %1$s.</string>
<string name="upgrade_recommended">Deine Version von %1$s funktioniert möglicherweise nicht mehr richtig. Du kannst sie jetzt aktualisieren, oder auf sie auf eigene Gefahr weiterverwenden. Einige Funktionen wie Datenaustausch mit Google-Diensten werden möglicherweise nicht mehr funktionieren, solange Du die Software nicht aktualisierst.</string>
<string name="upgrade_available">Eine neue Version von %1$s ist jetzt verfügbar. Du kannst Deine installierte Version ohne Probleme weiterverwenden, aber um die neuesten Funktionen in Anspruch nehmen zu können, musst Du die Software aktualisieren.</string>
<!-- Welcome -->
<string name="welcome">Willkommen</string>
<string name="welcome_read_later">OK</string>
<string name="welcome_about">Über My Tracks</string>
<!-- Announcement -->
<string name="announce_no_distance">My Tracks keine Entfernung</string>
<string name="welcome_about">Über My Tracks</string>
<!-- Announcement -->
<string name="announce_no_distance">My Tracks keine Entfernung</string>
<!-- Format:
$1 : Distance label
$2 : Distance value (5)
@@ -383,42 +407,44 @@ limitations under the License.
$4 : Time description (10 minutes 5 seconds)
$5 : Speed value (5.6) : Pace value (5 minutes 6 seconds)
$6 : Speed units (mph) : Pace units (per mile)
-->
<string name="announce_template">My Tracks %1$s %2$.2f %3$s in %4$s mit %5$s %6$s</string>
<!-- Check Units -->
<string name="check_units_title">Einheitenbenachrichtigung</string>
<string name="check_units_message">Voreingestellt sind metrische Einheiten. Willst Du diese Einstellung ändern?</string>
-->
<string name="announce_template">My Tracks %1$s %2$.2f %3$s in %4$s mit %5$s %6$s</string>
<!-- Check Units -->
<string name="check_units_title">Einheitenbenachrichtigung</string>
<string name="check_units_message">Voreingestellt sind metrische Einheiten. Willst Du diese Einstellung ändern?</string>
<!-- Fake preference keys - never saved, but show options in the preferences screen -->
<string name="bluetooth_options">Bluetooth-Einstellungen</string>
<string name="bluetooth_pairing">Geräteverbindung</string>
<string name="bluetooth_pairing_summary">Öffnet Androids Bluetooth-Einstellungen, um Geräte zu verbinden.</string>
<string name="sensor_options">Sensor-Einstellungen</string>
<!-- Bluetooth Sensor -->
<string name="bluetooth_connected">Verbunden mit %s</string>
<string name="bluetooth_connecting">Verbinde mit Bluetooth-Sensor ...</string>
<string name="bluetooth_not_connected">Bluetooth-Sensor nicht verbunden.</string>
<!-- Sensor State -->
<string name="sensor_data_time">Uhrzeit</string>
<string name="power_meter_enabled">Kraftmesser aktiviert</string>
<string name="heart_rate_monitor_enabled">Herzfrequenzmessung aktiviert</string>
<string name="no_sensor_manager">Keine Sensoren verfügbar</string>
<string name="enabled">Aktiviert</string>
<string name="connecting">Verbinde...</string>
<string name="connected">Verbunden</string>
<string name="disconnected">Getrennt</string>
<string name="no_sensor_service">Kein Sensor-Dienst</string>
<string name="searching">Suche...</string>
<string name="sending">Sende...</string>
<!-- Manifest description (not seen inside the app) -->
<string name="notification_permission_label">Track-Aufzeichnungs-Benachrichtigungen empfangen</string>
<string name="read_tracks_permission_label">Aufgezeichnete Trackdaten lesen</string>
<string name="write_tracks_permission_label">Aufgezeichnete Trackdaten schreiben, Starten/Anhalten des Aufzeichnens von Tracks</string>
<string name="notification_permission_description">Werde benachrichtigt, wenn die Aufzeichnung eines Tracks beginnt oder anhält.</string>
<string name="read_tracks_permission_description">Ermöglicht das Lesen von Trackdaten wie Messpunkten oder Wegpunkten.</string>
<string name="write_tracks_permission_description">Ermöglicht das Schreiben von Trackdaten wie beim Starten der Aufzeichnung oder beim Hinzufügen von Wegpunkten.</string>
</resources>
<string name="method_bluetooth">Bluetooth</string>
<string name="bluetooth_options">Bluetooth-Einstellungen</string>
<string name="bluetooth_pairing">Geräteverbindung</string>
<string name="bluetooth_pairing_summary">Öffnet Androids Bluetooth-Einstellungen, um Geräte zu verbinden.</string>
<!--string name="sensor_bluetooth_options_key">bluetoothSensorsEnabled</string-->
<string name="sensor_options">Sensor-Einstellungen</string>
<!-- Bluetooth Sensor -->
<string name="bluetooth_connected">Verbunden mit %s</string>
<string name="bluetooth_connecting">Verbinde mit Bluetooth-Sensor ...</string>
<string name="bluetooth_not_connected">Bluetooth-Sensor nicht verbunden.</string>
<!-- Sensor State -->
<string name="sensor_data_time">Uhrzeit</string>
<string name="power_meter_enabled">Kraftmesser aktiviert</string>
<string name="heart_rate_monitor_enabled">Herzfrequenzmessung aktiviert</string>
<string name="no_sensor_manager">Keine Sensoren verfügbar</string>
<string name="enabled">Aktiviert</string>
<string name="connecting">Verbinde...</string>
<string name="connected">Verbunden</string>
<string name="disconnected">Getrennt</string>
<string name="no_sensor_service">Kein Sensor-Dienst</string>
<string name="searching">Suche...</string>
<string name="sending">Sende...</string>
<!-- Manifest description (not seen inside the app) -->
<string name="notification_permission_label">Track-Aufzeichnungs-Benachrichtigungen empfangen</string>
<string name="read_tracks_permission_label">Aufgezeichnete Trackdaten lesen</string>
<string name="write_tracks_permission_label">Aufgezeichnete Trackdaten schreiben, Starten/Anhalten des Aufzeichnens von Tracks</string>
<string name="notification_permission_description">Werde benachrichtigt, wenn die Aufzeichnung eines Tracks beginnt oder anhält.</string>
<string name="read_tracks_permission_description">Ermöglicht das Lesen von Trackdaten wie Messpunkten oder Wegpunkten.</string>
<string name="write_tracks_permission_description">Ermöglicht das Schreiben von Trackdaten wie beim Starten der Aufzeichnung oder beim Hinzufügen von Wegpunkten.</string>
</resources>
-7
View File
@@ -143,11 +143,4 @@ limitations under the License.
<item>camino</item>
</array>
<array name="sensor_type_options">
<item>Ninguna</item>
<item>ANT+ Sensores</item>
<item>SRM ANT+ Puente</item>
<item>Zephyr Bluetooth</item>
</array>
</resources>
+4
View File
@@ -128,4 +128,8 @@ limitations under the License.
$6 : Speed units (mph) : Pace units (per mile)
-->
<!-- Sensor Type Options -->
<string name="no_sensor_option">Ninguna</string>
<string name="ant_sensor_option">ANT+ Sensores</string>
<string name="ant_bridge_sensor_option">SRM ANT+ Puente</string>
</resources>
+5 -17
View File
@@ -15,18 +15,6 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Task frequency -->
<string-array name="task_frequency_options">
<item>Apagado</item>
<item>1 min</item>
<item>2 min</item>
<item>5 min</item>
<item>10 min</item>
<item>15 min</item>
<item>30 min</item>
<item>60 min</item>
</string-array>
<!-- Minimum recording distance -->
<string-array name="min_recording_distance_options">
<item>1 m</item>
@@ -112,9 +100,9 @@ limitations under the License.
<item>3.1 miles (señal GPS débil)</item>
</string-array>
<!-- Split frequency -->
<string-array name="split_frequency_options">
<item>No dividir</item>
<!-- Task frequency -->
<string-array name="task_frequency_options">
<item>Apagado</item>
<item>100 km</item>
<item>50 km</item>
<item>25 km</item>
@@ -130,8 +118,8 @@ limitations under the License.
<item>1 min</item>
</string-array>
<string-array name="split_frequency_options_ft">
<item>No dividir</item>
<string-array name="task_frequency_options_ft">
<item>Apagado</item>
<item>100 mi</item>
<item>50 mi</item>
<item>25 mi</item>
+17 -18
View File
@@ -25,37 +25,37 @@ limitations under the License.
<string name="delete_all_tracks">Borrar todos los recorridos</string>
<string name="settings">Configuraciones</string>
<string name="elevation">Elevación</string>
<string name="choose_track_message">Por favor seleccione el recorrido que desea ver</string>
<string name="choose_track_message">Por favor, seleccione el recorrido que desea ver</string>
<string name="current_track">Recorrido actual</string>
<string name="current_segment">Último segmento</string>
<!-- Error messages -->
<string name="error_no_location_manager">Ningún administrador de ubicación fue hallado en este aparato! </string>
<string name="error_no_gps_location_provider">Ningún proveedor GPS de ubicación fue hallado en este aparato.</string>
<string name="error_sending_to_fusiontables">Hubo un error al mandar su recorrido a Google Fusion Tables. Por favor inténtelo de nuevo más tarde.</string>
<string name="error_sending_to_docs">Hubo un error al mandar su recorrido a Google Docs. Por favor inténtelo de nuevo más tarde.</string>
<string name="error_unable_to_start_recording">No pude empezar a grabar. Por favor inténtelo de nuevo. </string>
<string name="error_unable_to_stop_recording">No pude dejar de grabar. Por favor inténtelo de nuevo.</string>
<string name="error_no_location_manager">Ningún administrador de ubicación fue hallado en este dispositivo! </string>
<string name="error_no_gps_location_provider">Ningún proveedor de ubicación GPS fue hallado en este dispositivo.</string>
<string name="error_sending_to_fusiontables">Se produjo un error al enviar su recorrido a Google Fusion Tables.</string>
<string name="error_sending_to_docs">Se produjo un error al enviar su recorrido a Google Docs.</string>
<string name="error_unable_to_start_recording">No se puede iniciar la grabación. Inténtelo de nuevo. </string>
<string name="error_unable_to_stop_recording">No se puede detener la grabación. Inténtelo de nuevo.</string>
<string name="error_unable_to_read_file">No pude leer del archivo.</string>
<string name="error_invalid_gpx_format">El archivo no tiene un format GPX válido.</string>
<string name="error_generic">Error. Por favor inténtelo de nuevo.</string>
<string name="error_generic">A ocurrido un error. Por favor, inténtelo de nuevo.</string>
<string name="error_track_does_not_exist">El recorrido no existe.</string>
<string name="error_out_of_memory">El archivo es demasiado grande (tiene que ser menor a 500 KB). Abortando.</string>
<string name="error_unable_to_insert_marker">No pude insertar la señal. La ubicación no esta disponible.</string>
<string name="error_unable_to_insert_marker">No se puede insertar el marcador. La ubicación no está disponible.</string>
<!-- Status messages -->
<string name="wait_for_fix">Esperando una ubicación mas exacta del GPS. Asegúrese que el cielo sea visible.</string>
<string name="status_now_recording">Grabando un nuevo recorrido.</string>
<string name="status_stopped_recording">Grabacíon interrumpida.</string>
<string name="status_new_fusiontable_has_been_created">Un mapa Google Fusion Tables nuevo has sido creado en google.com/fusiontables.</string>
<string name="status_stopped_recording">Grabación interrumpida.</string>
<string name="status_new_fusiontable_has_been_created">Una nueva tabla de Google Fusion ha sido creada en google.com/fusiontables.</string>
<string name="status_tracks_have_been_uploaded">Su recorrido ha sido enviado a maps.google.com.</string>
<string name="status_tracks_have_been_uploaded_to_new_doc">Su recorrido ha sido enviado a una nueva hoja de cálculo en docs.google.com.</string>
<string name="status_tracks_have_been_uploaded_to_new_doc">Su recorrido ha sido enviado a una nueva hoja de cálculo de docs.google.com.</string>
<string name="status_tracks_have_been_uploaded_to_docs">Su recorrido ha sido enviado a docs.google.com.</string>
<string name="status_enable_gps">Por favor presione aquí para ir al menú de Seguridad y Ubicación y asegúrese que el GPS esté habilitado. Presione el botón de regreso para regresar.</string>
<string name="status_approximate_location">Nota: Una ubicación aproximada es mostrada, basada en informacion de torres de telefonía celular y red WIFI.</string>
<string name="status_no_location">La ubicación actual no puede ser determinada. Habilite más fuentes de datos (vea configuraciones de Seguridad y Ubicación) y asegúrese que el cielo sea visible. Inténtelo mas tarde.</string>
<string name="status_waypoint_inserted">Una señal de recorrido fue insertada.</string>
<string name="status_statistics_inserted">Una señal con estadísticas fue insertada.</string>
<string name="status_enable_gps">Por favor, presione aquí para ir al menú de Seguridad y Ubicación, y asegúrese que el GPS esté habilitado. Presione el botón "atrás" para regresar.</string>
<string name="status_approximate_location">Nota: Una ubicación aproximada es determinada a partir de torres de telefonía celular y redes WIFI.</string>
<string name="status_no_location">No puede ser determinada la ubicación actual. Habilite más fuentes de datos (vea las configuraciones de Seguridad y Ubicación) y asegúrese que el cielo sea visible. Inténtelo mas tarde.</string>
<string name="status_waypoint_inserted">Un marcador de recorrido fue insertado.</string>
<string name="status_statistics_inserted">Un marcador de estadísticas fue insertado.</string>
<!-- Progress dialog -->
<string name="progress_title">Por favor espere...</string>
@@ -212,7 +212,6 @@ limitations under the License.
<string name="settings_backup_to_sd_summary">Hacer una copia total de sus recorridos y configuraciones a la tarjeta SD</string>
<string name="settings_restore_from_sd">Restaurar</string>
<string name="settings_restore_from_sd_summary">Restaurar todos los recorridos y configuraciones desde la tarjeta SD</string>
<string name="settings_no_backup_while_recording">No se pueden manejar backups mientras se está registrando un recorrido.</string>
<string name="restore_overwrites_warning">Restaurar un backup desde la tarjeta SD SOBREESCRIBIRÁ todos sus recorridos y configuraciones actuales. ¿Está usted seguro?</string>
<string name="select_backup_to_restore">Seleccionar el backup para restaurar</string>
+271
View File
@@ -0,0 +1,271 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2010 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Minimum recording distance -->
<string-array name="min_recording_distance_options">
<item>1 m</item>
<item>2 m</item>
<item>3 m</item>
<item>4 m</item>
<item>5 m (suositeltu)</item>
<item>10 m</item>
<item>100 m</item>
</string-array>
<string-array name="min_recording_distance_options_ft">
<item>3 ft</item>
<item>6 ft</item>
<item>10 ft</item>
<item>13 ft</item>
<item>16 ft (suositeltu)</item>
<item>33 ft</item>
<item>328 ft</item>
</string-array>
<!-- Maximum recording distance -->
<string-array name="max_recording_distance_options">
<item>50 m</item>
<item>100 m</item>
<item>200 m (suositeltu)</item>
<item>500 m</item>
<item>1000 m</item>
<item>5000 m</item>
</string-array>
<string-array name="max_recording_distance_options_ft">
<item>164 ft</item>
<item>328 ft</item>
<item>656 ft (suositeltu)</item>
<item>1640 ft</item>
<item>0.6 mailia</item>
<item>3.1 mailia</item>
</string-array>
<!-- Minimum recording interval -->
<string-array name="min_recording_interval_options">
<item>virransäästö (mukautuva)</item>
<item>paras tarkkuus (mukautuva)</item>
<item>nopein (suositeltu)</item>
<item>2 s</item>
<item>3 s</item>
<item>4 s</item>
<item>5 s</item>
<item>10 s</item>
<item>20 s</item>
<item>30 s</item>
<item>1 min</item>
<item>2 min</item>
<item>5 min</item>
<item>10 min</item>
<item>15 min</item>
<item>30 min</item>
</string-array>
<!-- Minimum required accuracy -->
<string-array name="min_required_accuracy_options">
<item>10 m (erinomainen GPS-signaali)</item>
<item>20 m</item>
<item>50 m</item>
<item>100 m</item>
<item>200 m (suositeltu)</item>
<item>500 m</item>
<item>1000 m</item>
<item>2000 m</item>
<item>5000 m (heikko GPS-signaali)</item>
</string-array>
<string-array name="min_required_accuracy_options_ft">
<item>33 ft (erinomainen GPS-signaali)</item>
<item>66 ft</item>
<item>165 ft</item>
<item>328 ft</item>
<item>656 ft (suositeltu)</item>
<item>1640 ft</item>
<item>0.6 mailia</item>
<item>1.2 mailia</item>
<item>3.1 mailia (heikko GPS-signaali)</item>
</string-array>
<!-- Task frequency -->
<string-array name="task_frequency_options">
<item>Pois päältä</item>
<item>100 km</item>
<item>50 km</item>
<item>25 km</item>
<item>10 km</item>
<item>5 km</item>
<item>1 km</item>
<item>60 min</item>
<item>30 min</item>
<item>15 min</item>
<item>10 min</item>
<item>5 min</item>
<item>2 min</item>
<item>1 min</item>
</string-array>
<string-array name="task_frequency_options_ft">
<item>Pois päältä</item>
<item>100 mi</item>
<item>50 mi</item>
<item>25 mi</item>
<item>10 mi</item>
<item>5 mi</item>
<item>1 mi</item>
<item>60 min</item>
<item>30 min</item>
<item>15 min</item>
<item>10 min</item>
<item>5 min</item>
<item>2 min</item>
<item>1 min</item>
</string-array>
<!-- Auto-resume track timeout -->
<string-array name="auto_resume_track_timeout_options">
<item>Ei koskaan</item>
<item>5 min</item>
<item>10 min</item>
<item>15 min</item>
<item>Aina</item>
</string-array>
<!-- Other non-preference arrays -->
<array name="activity_types">
<item>tuntematon</item>
<item>sekoitus</item>
<item>muu</item>
<item>juoksu</item>
<item>katujuoksu</item>
<item>ratajuoksu</item>
<item>maastojuoksu</item>
<item>kävely</item>
<item>hölkkä</item>
<item>patikointi</item>
<item>patikointi metsässä</item>
<item>suokävely</item>
<item>kiipeily</item>
<item>pyöräily</item>
<item>maantiepyöräily</item>
<item>maastopyöräily</item>
<item>ratapyöräily</item>
<item>luistelu</item>
<item>rullaluistelu</item>
<item>rullalautailu</item>
<item>rullahiihto (classic)</item>
<item>rullahiihto (skate)</item>
<item>maastohiihto (classic)</item>
<item>maastohiihto (skate)</item>
<item>lumikävely</item>
<item>hiihto</item>
<item>lumilautailu</item>
<item>kelkkailu</item>
<item>jääpurjehdus</item>
<item>purjehdus</item>
<item>melonta</item>
<item>soutu</item>
<item>moottoriveneily</item>
<item>lautta</item>
<item>RC-veneily</item>
<item>surffaus</item>
<item>purjelautailu</item>
<item>vesihiito</item>
<item>wake boarding</item>
<item>lentokone</item>
<item>katamaraani</item>
<item>liikennelentokone</item>
<item>helikopteri</item>
<item>kuumailmapallo</item>
<item>ilmalaiva</item>
<item>RC-lennokki</item>
<item>RC-helikopteri</item>
<item>laskuvarjohyppy</item>
<item>liitovarjo</item>
<item>ratsastus</item>
<item>autolla ajo</item>
<item>bussimatka</item>
<item>juna</item>
<item>moottoripyörä</item>
<item>maastopyörä</item>
<item>ATV</item>
<item>maapurjehdus</item>
<item>frisbee</item>
<item>ultimate frisbee</item>
</array>
<array name="waypoint_types">
<item>baari</item>
<item>bussipysäkki</item>
<item>cafe</item>
<item>golfrata</item>
<item>grilli</item>
<item>hotelli</item>
<item>huoltoasema</item>
<item>information</item>
<item>juomavesi</item>
<item>kahvila</item>
<item>kalastus</item>
<item>kampaamo</item>
<item>kauppa</item>
<item>kirkko</item>
<item>kohtaamispaikka</item>
<item>kuoppa</item>
<item>lautta</item>
<item>marketti</item>
<item>nuotio</item>
<item>nähtävyys</item>
<item>putoavia kiviä</item>
<item>paloasema</item>
<item>postilaatikko</item>
<item>ooppera</item>
<item>ostokset</item>
<item>pankkiautomaatti</item>
<item>pankki</item>
<item>poliisiasema</item>
<item>pysäköinti</item>
<item>posti</item>
<item>puhelin</item>
<item>puu</item>
<item>rakennus</item>
<item>ravintola</item>
<item>reittipiste</item>
<item>retkeilyreitti</item>
<item>risteys</item>
<item>ruokakauppa</item>
<item>satama</item>
<item>talo</item>
<item>tasoristeys</item>
<item>teatteri</item>
<item>tulentekopaikka</item>
<item>tunneli</item>
<item>turisti-info</item>
<item>uima-allas</item>
<item>vesiputous</item>
<item>WC</item>
</array>
</resources>
+510
View File
@@ -0,0 +1,510 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2010 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Used by the Menu -->
<string name="start_recording">Aloita reitti</string>
<string name="stop_recording">Lopeta</string>
<string name="switch_to_sat">Satelliitti</string>
<string name="switch_to_map">Kartta</string>
<string name="mylocation">Oma sijainti</string>
<string name="list_tracks">Reitit</string>
<string name="list_markers">Merkinnät</string>
<string name="delete_all_tracks">Poista kaikki reitit</string>
<string name="settings">Asetukset</string>
<string name="elevation">Korkeus</string>
<string name="choose_track_message">Valitse näytettävä reitti</string>
<string name="current_track">Valittu reitti</string>
<string name="current_segment">Nykyinen segmentti</string>
<string name="sensor_state">Sensorien tila</string>
<string name="aggregated_stats">Yhteenlasketut tilastot</string>
<!-- Error messages -->
<string name="error_no_location_manager">Paikkatietoja ei löytynyt!</string>
<string name="error_no_gps_location_provider">GPS-palvelua ei löytynyt.</string>
<string name="error_sending_to_mymap">Virhe lähetettäessä reittiä Google My Maps-palveluun.</string>
<string name="error_sending_to_fusiontables">Virhe lähetettäessä reittiä Google Fusion Tables-palveluun.</string>
<string name="error_sending_to_docs">Virhe lähetettäessä reittiä Google Docs-palveluun..</string>
<string name="error_please_try_again_later">Yritä myöhemmin uudelleen.</string>
<string name="error_unable_to_start_recording">Tallennusta ei voitu aloittaa. Yritä uudelleen.</string>
<string name="error_unable_to_stop_recording">Tallennusta ei voitu pysäyttää. Yritä uudelleen.</string>
<string name="error_unable_to_read_file">Tiedostovirhe.</string>
<string name="error_invalid_gpx_format">Virheellinen GPX-formaatti.</string>
<string name="error_generic">Tapahtui virhe. Yritä uudelleen.</string>
<string name="error_track_does_not_exist">Reittiä ei ole olemassa.</string>
<string name="error_operation_cancelled">Tapahtuma keskeytettiin.</string>
<string name="error_out_of_memory">Liian suuri tiedosto (maksimi 500 KB). Keskeytetään.</string>
<string name="error_unable_to_insert_marker">Merkintää ei voitu lisätä. Paikkatietoa ei saatavilla.</string>
<!-- Status messages -->
<string name="wait_for_fix">Odotetaan parempaa GPS-yhteyttä. Varmista että taivas on näkyvissä.</string>
<string name="status_now_recording">Tallennetaan uutta reittiä.</string>
<string name="status_stopped_recording">Reitin tallentaminen lopetettiin.</string>
<string name="status_new_mymap_has_been_created">Uusi Google My Map on luotu osoitteeseen maps.google.com.</string>
<string name="status_new_fusiontable_has_been_created">Uusi Google Fusion taulukko on luotu osoitteeseen google.com/fusiontables.</string>
<string name="status_tracks_have_been_uploaded">Reittisi on lähetetty osoitteeseen maps.google.com.</string>
<string name="status_tracks_have_been_uploaded_to_new_doc">Reittisi on luotu taulukoksi osoitteeseen docs.google.com.</string>
<string name="status_tracks_have_been_uploaded_to_docs">Reittisi on lähetetty osoitteeseen docs.google.com.</string>
<string name="status_mymap_info">Reitin näkyminen saattaa kestää muutaman minuutin.</string>
<string name="status_enable_gps">Avaa tästä Sijainti ja suojaus -asetukset ja valitse \'Käytä GPS-satelliitteja\'. Palaa ohjelmaan painamalla Takaisin-näppäintä.</string>
<string name="status_approximate_location">Huomio: Näkyvä sijainti perustuu kännykkämastoista ja WLAN-verkoista arvioituun paikkatietoon.</string>
<string name="status_no_location">Paikkatietoa ei löydy. Aktivoi lisää paikannusmenetelmiä (katso Asetukset) ja varmista että taivas on näkyvissä. Yritä myöhemmin uudelleen.</string>
<string name="status_waypoint_inserted">Reittimerkintä lisätty.</string>
<string name="status_statistics_inserted">Tilastomerkintä lisätty.</string>
<string name="status_track_upload_status">Lähetyksen tila:</string>
<!-- Progress dialog -->
<string name="progress_title">Odota...</string>
<string name="progress_message">Lähetetään reittiä Google:n palvelimelle.</string>
<string name="progress_message_reading_track">Luetaan reittiä...</string>
<string name="progress_message_preparing_track">Valmistellaan reittiä...</string>
<string name="progress_message_authenticating_fusiontables">Todennetaan Google Fusion Tables -tiliä...</string>
<string name="progress_message_authenticating_mymaps">Todennetaan Google Maps -tiliä...</string>
<string name="progress_message_authenticating_docs">Todennetaan Google Docs -tiliä...</string>
<string name="progress_message_sending_docs">Lähetetään reittiä Google Docsiin...</string>
<string name="progress_message_sending_mymaps">Lähetetään reittiä Google Mapsiin...</string>
<string name="progress_message_creating_map">Luodaan uutta My Mapsia...</string>
<string name="progress_message_sending_fusiontables">Lähetetään reittiä Fusion Tablesiin...</string>
<string name="progress_message_creating_fusiontable">Luodaan uutta Fusion tablea...</string>
<string name="import_progress_message">Tuodaan uutta GPS-reittiä. Odota.</string>
<string name="write_progress_message">Kirjoitetaan tiedostoa SD-kortille. Odota.</string>
<string name="progress_message_updating_track">Päivitetään reitin tilastoja...</string>
<!-- Used by DeleteAllDataHandler -->
<string name="are_you_sure_question">Oletko varma?</string>
<string name="all_data_will_be_permanently_deleted">Kaikki reitit ja merkinnät poistetaan puhelimesta.</string>
<string name="track_will_be_permanently_deleted">Reitti ja se merkinnät poistetaan pysyvästi puhelimesta.</string>
<string name="marker_will_be_permanently_deleted">Merkintä poistetaan puhelimesta.</string>
<!-- Text and links when uploading to Google Fusion Tables -->
<string name="new_map_description">Created by My Tracks on Android.</string>
<string name="fusiontable_link">Created by &lt;a href=\'http://mytracks.appspot.com\'&gt;My Tracks&lt;/a&gt; on Android.</string>
<!-- Text and links when uploading to Google My Maps -->
<string name="my_map_link">Created by &lt;a href=\'http://mytracks.appspot.com\'&gt;My Tracks&lt;/a&gt; on Android.</string>
<string name="new_map_title">Uusi kartta</string>
<!-- Formatting of track and marker descriptions -->
<string name="points">Pisteet</string>
<string name="recorded_date">Tallennettu</string>
<string name="category">Liikunnan muoto</string>
<string name="waypoint_category">Merkinnän tyyppi</string>
<string name="part">(Osa %d)</string>
<!-- Used by the track recording service -->
<string name="recording_your_track">Tallennetaan reittiä...</string>
<string name="new_track">Reitti %d</string>
<!-- Common -->
<string name="no">Ei</string>
<string name="yes">Kyllä</string>
<string name="ok">OK</string>
<string name="error">Virhe</string>
<string name="success">Valmis</string>
<string name="waypoint">Reittipiste</string>
<string name="license">Lisenssi</string>
<string name="cancel">Peruuta</string>
<string name="close">Sulje</string>
<string name="edit">Muokkaa</string>
<string name="save">Tallenna</string>
<!-- Placemark labels for start and end of track -->
<string name="start">(Lähtö)</string>
<string name="end">(Maali)</string>
<!-- TrackList -->
<string name="tracklist_show_track">Näytä</string>
<string name="tracklist_send_to_mymaps">Lähetä Google My Mapsiin</string>
<string name="tracklist_send_to_new_mymap">Lähetä New Google My Mapiin</string>
<string name="tracklist_send_to_fusiontables">Lähetä Google Fusion Tablesiin</string>
<string name="tracklist_send_to_new_fusiontable">Lähetä New Google Fusion Tablesiin</string>
<string name="tracklist_send_to_docs">Lähetä Google Docsiin</string>
<string name="tracklist_send_to_google">Lähetä Googleen...</string>
<string name="tracklist_delete_track">Poista puhelimesta...</string>
<string name="tracklist_edit_track">Muokkaa tietoja...</string>
<string name="tracklist_write_to_sd">Kirjoita SD-kortille...</string>
<string name="tracklist_save_as_gpx">Tallenna GPX-tiedosto</string>
<string name="tracklist_save_as_kml">Tallenna KML-tiedosto</string>
<string name="tracklist_save_as_csv">Tallenna CSV-tiedosto</string>
<string name="tracklist_save_as_tcx">Tallenna TCX-tiedosto</string>
<string name="tracklist_btn_send_all_to_fusiontables">Lähetä Google Fusion Tablesiin</string>
<string name="tracklist_btn_send_all_to_mymaps">Lähetä Google My Mapsiin</string>
<string name="tracklist_btn_delete_all">Poista kaikki</string>
<!-- Export All -->
<string name="tracklist_btn_export_all">Vie kaikki</string>
<string name="export_done">Vienti tehty</string>
<string name="tracklist_pick_one">Valitse reitti. Pitkällä painalluksella lisää vaihtoehtoja.</string>
<string name="tracklist_all_tracks">Kaikki reitit:</string>
<string name="tracklist_this_track">Tämä reitti</string>
<string name="tracklist_share_track">Jaa...</string>
<string name="tracklist_share_link">Linkki karttaan</string>
<string name="tracklist_share_gpx_file">GPX-tiedosto</string>
<string name="tracklist_share_kml_file">KML-tiedosto</string>
<string name="tracklist_share_csv_file">CSV-tiedosto</string>
<string name="tracklist_share_tcx_file">TCX-tiedosto</string>
<string name="tracklist_clear_map">Tyhjennä kartta</string>
<!-- Import All -->
<string name="tracklist_btn_import_all">Tuo kaikki</string>
<!-- Format:
$1 : Successful imports
$2 : Attempted imports
$3 : MyTracks gpx path
-->
<string name="import_multi_done">Tuotu %1$d GPX-tiedostoa %2$d:sta lähteestä %3$s</string>
<string name="import_multi_empty">Lähteestä %s ei löytynyt GPX-tiedostoja. SD-kortti saattaa olla lukukelvoton tai hakemistossa ei ole GPX-tiedostoja.</string>
<string name="import_error">Virhe tuotaessa tiedostoa %s</string>
<string name="import_title">Tuo My Tracksiin</string>
<string name="import_success">%1$d reittiä tuotu.</string>
<string name="import_show_track">Näytä reitti</string>
<!-- Waypoints list -->
<string name="waypointslist_btn_delete_all">Poista kaikki merkinnät</string>
<string name="waypointslist_this_waypoint">Tämä merkintä</string>
<string name="waypointslist_delete_waypoint">Poista</string>
<string name="waypointslist_edit_waypoint">Muokkaa tietoja</string>
<string name="waypointslist_show_waypoint">Näytä kartalla</string>
<string name="waypointslist_btn_insert_waypoint">Lisää reittipiste</string>
<string name="waypointslist_btn_insert_statistics">Lisää tilastot</string>
<string name="waypointslist_pick_one">Valitse merkintä. Pitkä painallus tuo esiin lisää vaihtoehtoja.</string>
<!-- MyTracks Details -->
<string name="trackdetails_title">Reitin tiedot</string>
<string name="trackdetails_name">Reitin nimi</string>
<string name="trackdetails_description">Reitin kuvaus</string>
<string name="trackdetails_category">Liikunnan muoto (esim. hölkkä, pyöräily, juoksu...)</string>
<!-- MyTracks Waypoint Details -->
<string name="waypointdetails_title">Merkinnän tiedot</string>
<string name="waypointdetails_name">Merkinnän nimi</string>
<string name="waypointdetails_description">Merkinnän kuvaus</string>
<string name="waypointdetails_category">Merkinnän tyyppi (esim. rakennus, kuoppa, nähtävyys...)</string>
<!-- MyTracks Settings -->
<string name="mytracks_settings">My Tracks Asetukset</string>
<string name="settings_display">Näyttö</string>
<string name="settings_recording">Tallennus</string>
<string name="settings_sharing">Jakaminen</string>
<string name="settings_not_available_summary">Ei tuettu tässä Android-versiossa</string>
<string name="settings_not_while_recording">Ei saatavilla reittiä tallennettaessa.</string>
<string name="settings_announcement_frequency">Äänimerkki</string>
<string name="settings_announcement_frequency_summary">Äänimerkkien aikaväli</string>
<string name="settings_min_recording_distance">Lyhyin piste-etäisyys</string>
<string name="settings_min_recording_distance_summary">Lyhyin sallittu reitintallennuksessa käytetty etäisyys kahden pisteen välillä</string>
<string name="settings_max_recording_distance">Pisin piste-etäisyys</string>
<string name="settings_max_recording_distance_summary">Jos edeltävä piste on valittua etäisyyttä pidemmällä reitti jaetaan</string>
<string name="settings_min_recording_interval">Lyhyin aika</string>
<string name="settings_min_recording_interval_summary">Lyhyin aikaintervalli kahden tallennetun pisteen välillä</string>
<string name="settings_min_required_accuracy">Sallittu tarkkuus</string>
<string name="settings_min_required_accuracy_summary">Reitin tallennus pysäytetään, jos tarkkuus on tätä pienempi</string>
<string name="settings_metric_units">Käytä metrijärjestelmää</string>
<string name="settings_metric_units_summary_on">Kaikki etäisyydet näytetään metrijärjestelmässä</string>
<string name="settings_metric_units_summary_off">Kaikki etäisyydet näytetään U.S yksiköitä käyttäen</string>
<string name="settings_map_public">Aseta kartat julkisiksi</string>
<string name="settings_map_public_summary_on">Lähetetyt kartat näkyvät kaikille osoitteessa maps.google.com</string>
<string name="settings_map_public_summary_off">Lähetettyjä karttoja ei näytetä julkisesti osoitteessa maps.google.com</string>
<string name="settings_report_speed_or_pace">Näytä nopeus</string>
<string name="settings_report_speed_or_pace_summary_on">Nopeus näytetään</string>
<string name="settings_report_speed_or_pace_summary_off">Tahti näytetään</string>
<string name="settings_share_url_only">Jaa vain URL</string>
<string name="settings_share_url_only_summary_on">Ainoastaan kartan URL jaetaan</string>
<string name="settings_share_url_only_summary_off">Myös reitin sisältö ja tiedot jaetaan</string>
<string name="settings_split_frequency">Reitin jaotus</string>
<string name="settings_split_frequency_summary">Etäisyys tai aika jolloin reitti jaetaan osiin</string>
<string name="settings_auto_resume_track_timeout">Reitin jatkaminen</string>
<string name="settings_auto_resume_track_timeout_summary">Aika jonka sisällä tallennettavaa reittiä jatketaan, jos puhelin käynnitetään uudelleen.</string>
<string name="settings_timestamp_track_name">Aikamerkintä nimenä</string>
<string name="settings_timestamp_track_name_summary_on">Oletusnimenä reitille käytetään aloituspäivämäärää ja aikaa</string>
<string name="settings_timestamp_track_name_summary_off">Oletusnimenä käytetään kasvavaa numerointia.</string>
<string name="settings_reset">Palauta oletusasetukset</string>
<string name="settings_reset_summary">Palauta kaikki oletusasetukset</string>
<string name="settings_reset_dialog_message">Kaikki asetuksesi poistetaan ja palautetaan oletusarvoisiksi. Tallennetut reitit säilytetään. Oletko varma?</string>
<string name="settings_reset_done">Oletusasetukset palautettu.</string>
<string name="pace_label">Tahti</string>
<string name="eclair_required">Tuettuna vain Android 2.0 tai uudemmassa</string>
<string name="settings_sensor_type">Sensorin tyyppi</string>
<string name="settings_sensor_type_summary">Sensorin tyyppi johon yhdistetään</string>
<string name="settings_heart_rate_ant_sensor_id">Resetoi ANT sykemittarin paritus</string>
<string name="settings_power_ant_sensor_id">Resetoi ANT tehomittarin paritus</string>
<string name="settings_srm_bridge_ant_sensor_id">Resetoi ANT SRM sillan paritus</string>
<string name="settings_ant_not_paired">ANT sensori ei paritettu</string>
<string name="settings_ant_paired">ANT sensori paritettu: %d</string>
<string name="bluetooth_sensor_title">Bluetooth sensori</string>
<string name="bluetooth_sensor_summary">Bluetooth-sensori johon yhdistetään</string>
<string name="settings_modular_stats_display_title">Modular Stats Display</string>
<!-- Backups -->
<string name="settings_backup">Varmuuskopioi (BETA)</string>
<string name="settings_sd_backup">Varmuuskopioi SD-kortille</string>
<string name="settings_backup_to_sd">Varmuuskopioi</string>
<string name="settings_backup_to_sd_summary">Tallenna täydellinen kopio reiteistä ja asetuksista SD-kortille</string>
<string name="settings_restore_from_sd">Palauta</string>
<string name="settings_restore_from_sd_summary">Palauta kaikki reitit ja asetukset SD-kortilta</string>
<string name="restore_overwrites_warning">Palautus SD-kortilta ylikirjoittaa kaikki nykyiset reitit ja asetukset. Jatketaanko?</string>
<string name="select_backup_to_restore">Valitse palautettava varmuuskopio</string>
<string name="no_backups">Varmuuskopioita ei löytynyt.</string>
<string name="backup_write_progress_message">Luodaan varmuuskopiota. Odota...</string>
<string name="backup_import_progress_message">Luetaan varmuuskopiota SD-kortilta. Odota...</string>
<!-- MyTracksSky -->
<string name="mytracks_sky">GPS-satelliitit</string>
<!-- My Maps -->
<string name="select_map_message">Valitse kartta tililtäsi:</string>
<string name="create_new_map">Luo uusi kartta...</string>
<string name="map_list_title">Lähetä Google My Mapsiin</string>
<string name="maps_list_loading">Ladataan karttoja...</string>
<string name="maps_list_failed">Karttoja ei voitu ladata!</string>
<string name="open_map">Valitse tämä kartta</string>
<string name="edit_map_details">Muokkaa kartan tietoja</string>
<string name="share_track">Jaa reitti</string>
<string name="delete_map">Poista kartta tililtä</string>
<string name="map_title">Kartan otsikko:</string>
<string name="map_description">Kartan kuvaus:</string>
<string name="map_searchable_edit">Näytä kartta ja sen sisältö hakutuloksissa</string>
<string name="map_not_searchable_edit">Älä näytä karttaa tai sen sisältöä hakutuloksissa. Tiedot näkyvät suoralla URL-linkillä</string>
<string name="map_searchable">Tämä kartta ja sen sisältö näkyy hakutuloksissa</string>
<string name="map_not_searchable">Kartta tai sen sisältö ei näy hakutuloksissa. Tiedot näkyvät muille kuitenkin suoralla URL-linkillä</string>
<!-- Sharing -->
<string name="share_map">Jaa kartta</string>
<string name="share_map_subject">Haluaisin jakaa kartan kanssasi</string>
<string name="share_map_body_format">Saattaisit olla kiinnostunut tästä reitistä:
%s</string>
<string name="send_track_subject">Haluaisin jakaa reitin kanssasi</string>
<string name="send_track_body_format">Saattaisit olla kiinnostunut tästä reitistä.
Käytä Google Earthia tai jotain muuta karttaohjelmistoa kartan katsomiseen.</string>
<!-- Visibility -->
<string name="public_map">Julkinen</string>
<string name="unlisted_map">Ei listattu</string>
<string name="mapslist_no_maps_available">Ei karttoja saatavilla.</string>
<!-- Statistics View -->
<!-- Average Moving -->
<string name="average_moving_speed_label">Keskinopeus (liikuttaessa)</string>
<string name="average_moving_pace_label">Tahti (liikuttaessa)</string>
<!-- Average -->
<string name="average_speed_label">Keskinopeus</string>
<string name="average_pace_label">Tahti</string>
<string name="elevation_chart_name">Korkeuskaavio</string>
<string name="elevation_gain_label">Nousu</string>
<string name="elevation_label">Korkeus</string>
<string name="latitude_label">Leveysaste</string>
<string name="longitude_label">Pituuspiiri</string>
<!-- Min -->
<string name="min_elevation_label">Min Korkeus</string>
<string name="min_grade_label">Min Kaltevuus</string>
<string name="min_pace_label">Min Tahti</string>
<!-- Max -->
<string name="max_elevation_label">Max Korkeus</string>
<string name="max_grade_label">Max Kaltevuus</string>
<string name="max_speed_label">Max Nopeus</string>
<string name="loading_track">Ladataan reittiä...</string>
<!-- Chart Settings -->
<string name="chart_settings">Kaavion asetukset</string>
<!-- X Axis -->
<string name="x_axis">X-akseli</string>
<string name="by_distance">Etäisyyden mukaan</string>
<string name="by_time">Ajan mukaan</string>
<!-- Y Axis -->
<string name="y_axis">Y-akseli</string>
<!-- Units -->
<!-- Time -->
<string name="hour">tunti</string>
<string name="hours">tuntia</string>
<string name="hr">h</string>
<string name="min">min</string>
<string name="minute">minuutti</string>
<string name="minutes">minuuttia</string>
<string name="second">sekunti</string>
<string name="seconds">sekuntia</string>
<string name="milliseconds">ms</string>
<!-- Distance -->
<string name="meter">m</string>
<string name="kilometer">km</string>
<string name="kilometers_long">kilometriä</string>
<string name="feet">ft</string>
<string name="mile">mi</string>
<string name="miles_long">mailia</string>
<!-- Speed and Pace -->
<string name="kilometer_per_hour">km/h</string>
<string name="kilometer_per_hour_long">kilometriä tunnissa</string>
<string name="min_per_kilometer">min/km</string>
<string name="per_kilometer">per kilometri</string>
<string name="mile_per_hour">mi/h</string>
<string name="mile_per_hour_long">mailia tunnissa</string>
<string name="min_per_mile">min/mi</string>
<string name="per_mile">per maili</string>
<!-- Sensors -->
<string name="watts">W</string>
<string name="revolutions_per_minute">rpm</string>
<string name="bpm">bpm</string>
<!-- Stats Labels -->
<string name="moving_time_label">Liikkumisaika</string>
<string name="total_time_label">Kokonaisaika</string>
<string name="time_label">Aika</string>
<string name="sd_unavail">Muistikortti ei ole käytettävissä</string>
<string name="speed">Nopeus</string>
<string name="start_trip">Sinun pitää ensin aloittaa matka.</string>
<string name="statistics">Tilastot</string>
<string name="total_distance_label">Kokonaismatka</string>
<string name="distance_label">Matka</string>
<string name="power">Teho</string>
<string name="cadence">Kadenssi</string>
<string name="heart_rate">Syke</string>
<string name="max_heart_rate">Maksimisyke</string>
<string name="unknown">-</string>
<string name="waiting">Odotetaan...</string>
<!-- End User License Agreement -->
<string name="eula_title">End User License Agreement</string>
<string name="accept">Hyväksy</string>
<string name="decline">Hylkää</string>
<!-- About -->
<string name="about">Tietoja</string>
<string name="help">Apua</string>
<string name="about_team">Tiimi:</string>
<string name="about_version">Version:</string>
<string name="about_support">Tuki:</string>
<string name="about_privacy">Yksityisyys:</string>
<!-- Send to Google -->
<string name="sendtogoogle_title">Lähetä...</string>
<string name="sendtogoogle_google_fusiontables">Google Fusion Tables</string>
<string name="sendtogoogle_google_mymaps">Google My Maps</string>
<string name="sendtogoogle_google_docs">Google Docs</string>
<string name="sendtogoogle_send_now">Lähetä</string>
<string name="sendtogoogle_create_new_map">Luo uusi kartta</string>
<string name="sendtogoogle_pick_existing_map">Valitse kartta</string>
<string name="sendtogoogle_send_stats">Lähetä reitin statistiikka</string>
<string name="sendtogoogle_send_stats_and_points">Lähetä reitin statistiikka ja pisteet</string>
<!-- Getting the account to upload to. -->
<string name="no_account_found_title">Tiliä ei löytynyt</string>
<string name="no_account_found">Tiliä johon reitin voisi lähettää ei löytynyt.</string>
<string name="choose_account_title">Valitse tili</string>
<!-- SD card -->
<string name="io_no_external_storage_found">Ulkoista tallennusmediaa ei löytynyt. Varmista että SD-kortti on kytketty eikä puhelinta ole liitetty tietokoneeseen.</string>
<string name="io_write_failed">Kirjoitusvirhe.</string>
<string name="io_read_failed">Lukuvirhe.</string>
<string name="io_create_dir_failed">Hakemistoa ei voitu luoda SD-kortille.</string>
<string name="io_write_finished">SD-kortille kirjoitus valmis.</string>
<string name="io_read_finished">SD-kortin luku valmis.</string>
<!-- VersionChecker -->
<string name="version_check_title">Tarkista päivitykset</string>
<string name="version_check_upgrade_button">Päivitä</string>
<string name="version_check_continue_button">Ohita päivitys</string>
<string name="upgrade_required">Käytössäsi oleva versio ohjelmasta %1$s saattaa lakata toimimasta eikä ole enää tuettu. Päivitä jatkaaksesi %1$s käyttöä.</string>
<string name="upgrade_recommended">Käytössäsi oleva versio ohjelmasta %1$s saattaa lakata toimimasta. Voit päivittää sen nyt tai jatkaa käyttöä omalla riskillä. Tietyt ominaisuudet, kuten synkronointi serverin kanssa, ei välttämättä toimi ennen päivitystä.</string>
<string name="upgrade_available">%1$s uusi versio saatavilla. Voit jatkaa nykyisen version käyttöä tai päivitää uuteen versioon.</string>
<!-- Welcome -->
<string name="welcome">Tervetuloa</string>
<string name="welcome_read_later">Ok</string>
<string name="welcome_about">Tietoa My Tracksista</string>
<!-- Announcement -->
<string name="announce_no_distance">My Tracks ei etäisyyttä</string>
<!-- Format:
$1 : Distance label
$2 : Distance value (5)
$3 : Distance units (mi, km)
$4 : Time description (10 minutes 5 seconds)
$5 : Speed value (5.6) : Pace value (5 minutes 6 seconds)
$6 : Speed units (mph) : Pace units (per mile)
-->
<string name="announce_template">My Tracks %1$s %2$.2f %3$s ajassa %4$s nopeudella %5$s %6$s</string>
<!-- Check Units -->
<string name="check_units_title">Huomautus mittayksiköistä</string>
<string name="check_units_message">Oletuksena käytössä on metrijärjestelmä. Haluatko muuttaa asetuksen?</string>
<!-- Fake preference keys - never saved, but show options in the preferences screen -->
<string name="method_bluetooth">Bluetooth</string>
<string name="bluetooth_options">Bluetooth asetukset</string>
<string name="bluetooth_pairing">Laiteparit</string>
<string name="bluetooth_pairing_summary">Avaa Androidin bluetooth-asetukset luodaksesi laitepareja</string>
<string name="sensor_bluetooth_options_key">bluetoothSensorsEnabled</string>
<string name="ant_options">ANT asetukset</string>
<string name="sensor_options">Sensorien asetukset</string>
<!-- Bluetooth Sensor -->
<string name="bluetooth_connected">Yhdistetty %s</string>
<string name="bluetooth_connecting">Yhdistetään bluetooth sensoria ...</string>
<string name="bluetooth_not_connected">Bluetooth sensoria ei ole yhdistetty</string>
<!-- Sensor State -->
<string name="sensor_data_time">Sensorin data-aika</string>
<string name="power_meter_enabled">Tehomittari käytössä</string>
<string name="heart_rate_monitor_enabled">Sykemittari käytössä</string>
<string name="no_sensor_manager">Ei sensorihallintaa</string>
<string name="enabled">Käytössä</string>
<string name="connecting">Yhdistetään</string>
<string name="connected">Yhdistetty</string>
<string name="disconnected">Katkaistu</string>
<string name="no_sensor_service">Ei sensoripalvelua</string>
<string name="searching">Etsitään</string>
<string name="sending">Lähetetään</string>
<string name="no_sensor_option">Ei sensoria</string>
<string name="ant_sensor_option">ANT+ -sensori</string>
<string name="ant_bridge_sensor_option">SRM ANT+ -silta</string>
<string name="polar_bt_sensor_option">Polar bluetooth</string>
<string name="zephyr_bt_sensor_option">Zephyr bluetooth</string>
<!-- Manifest description (not seen inside the app) -->
<string name="notification_permission_label">vastaanota huomautuksia reitin tallentamisesta</string>
<string name="read_tracks_permission_label">lue tallennettua reittidataa</string>
<string name="write_tracks_permission_label">kirjoita tallennettua reittidataa, aloita/pysäytä reitin tallennus</string>
<string name="notification_permission_description">Huomauta kun reitin tallennus aloitetaan tai pysäytetään..</string>
<string name="read_tracks_permission_description">Mahdollista reittidatan lukeminen, kuten reittipisteet, merkinnät jne.</string>
<string name="write_tracks_permission_description">Mahdollista reittidatan kirjoittaminen, kuten tallennuksen aloittaminen, merkintöjen lisääminen jne.</string>
</resources>
+5 -25
View File
@@ -15,18 +15,6 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Task frequency -->
<string-array name="task_frequency_options">
<item>Absent</item>
<item>1 min</item>
<item>2 min</item>
<item>5 min</item>
<item>10 min</item>
<item>15 min</item>
<item>30 min</item>
<item>60 min</item>
</string-array>
<!-- Minimum recording distance -->
<string-array name="min_recording_distance_options">
<item>1 m</item>
@@ -112,10 +100,9 @@ limitations under the License.
<item>3.1 miles (mauvais signal GPS)</item>
</string-array>
<!-- Split frequency -->
<string-array name="split_frequency_options">
<item>Pas de séparation</item>
<!-- Task frequency -->
<string-array name="task_frequency_options">
<item>Absent</item>
<item>100 km</item>
<item>50 km</item>
<item>25 km</item>
@@ -131,8 +118,8 @@ limitations under the License.
<item>1 min</item>
</string-array>
<string-array name="split_frequency_options_ft">
<item>Pas de séparation</item>
<string-array name="task_frequency_options_ft">
<item>Absent</item>
<item>100 mi</item>
<item>50 mi</item>
<item>25 mi</item>
@@ -304,11 +291,4 @@ limitations under the License.
<item>point de passage</item>
</array>
<array name="sensor_type_options">
<item>Aucun</item>
<item>Capteur ANT+</item>
<item>Pont SRM ANT+</item>
<item>Bluetooth Zephyr</item>
</array>
</resources>
+8 -3
View File
@@ -160,7 +160,7 @@ limitations under the License.
<string name="settings_sharing">Partage</string>
<string name="settings_announcement_frequency">Fréquence des annonces</string>
<string name="settings_announcement_frequency_summary">Temps minimum entre eux annonces vocales</string>
<string name="settings_announcement_frequency_summary">Temps minimum entre deux annonces vocales</string>
<string name="settings_min_recording_distance">Distance min. entre 2 points</string>
<string name="settings_min_recording_distance_summary">Plus petite distance entre deux enregistrements de votre position</string>
@@ -213,8 +213,6 @@ limitations under the License.
<string name="settings_backup_to_sd_summary">Copier tous vos parcours et paramètres sur la carte SD</string>
<string name="settings_restore_from_sd">Restaurer</string>
<string name="settings_restore_from_sd_summary">Restaurer tous les parcours et paramètres depuis la carte SD</string>
<string name="settings_no_backup_while_recording">Sauvegarde impossible lors de l\'enregistrement d\'un parcours.</string>
<string name="restore_overwrites_warning">Restaurer une sauvegarde depuis la carte SD écrasera tous vos parcours et paramètres actuels.</string>
<string name="select_backup_to_restore">Choisissez la sauvegarde à restaurer</string>
@@ -399,6 +397,13 @@ limitations under the License.
<string name="searching">Recherche</string>
<string name="sending">Envoi</string>
<!-- Sensor Type Options -->
<string name="no_sensor_option">Aucun</string>
<string name="ant_sensor_option">Capteur ANT+</string>
<string name="ant_bridge_sensor_option">Pont SRM ANT+</string>
<string name="polar_bt_sensor_option">Bluetooth Polar</string>
<string name="zephyr_bt_sensor_option">Bluetooth Zephyr</string>
<!-- Manifest description (not seen inside the app) -->
<string name="notification_permission_label">notifications lors de l\'enregistrement de parcours</string>
<string name="read_tracks_permission_label">lecture des parcours enregistrés</string>
+5 -17
View File
@@ -15,18 +15,6 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Task frequency -->
<string-array name="task_frequency_options">
<item>Disattivato</item>
<item>1 min</item>
<item>2 min</item>
<item>5 min</item>
<item>10 min</item>
<item>15 min</item>
<item>30 min</item>
<item>60 min</item>
</string-array>
<!-- Minimum recording distance -->
<string-array name="min_recording_distance_options">
<item>1 m</item>
@@ -112,9 +100,9 @@ limitations under the License.
<item>3.1 mi (segnale GPS debole)</item>
</string-array>
<!-- Split frequency -->
<string-array name="split_frequency_options">
<item>Non dividere</item>
<!-- Task frequency -->
<string-array name="task_frequency_options">
<item>Disattivato</item>
<item>100 km</item>
<item>50 km</item>
<item>25 km</item>
@@ -130,8 +118,8 @@ limitations under the License.
<item>1 min</item>
</string-array>
<string-array name="split_frequency_options_ft">
<item>Non dividere</item>
<string-array name="task_frequency_options_ft">
<item>Disattivato</item>
<item>100 mi</item>
<item>50 mi</item>
<item>25 mi</item>
+7 -22
View File
@@ -15,19 +15,7 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Task frequency -->
<string-array name="task_frequency_options">
<item>不使用</item>
<item>1 分</item>
<item>2 分</item>
<item>5 分</item>
<item>10 分</item>
<item>15 分</item>
<item>30 分</item>
<item>60 分</item>
</string-array>
<!-- Minimum recording distance -->
<!-- Minimum recording distance -->
<string-array name="min_recording_distance_options">
<item>1 m</item>
<item>2 m</item>
@@ -48,7 +36,6 @@ limitations under the License.
<item>328 ft</item>
</string-array>
<!-- Maximum recording distance -->
<string-array name="max_recording_distance_options">
<item>50 m</item>
@@ -68,7 +55,6 @@ limitations under the License.
<item>3.1 mi</item>
</string-array>
<!-- Minimum recording interval -->
<string-array name="min_recording_interval_options">
<item>電源節約 (動的制御)</item>
@@ -89,7 +75,6 @@ limitations under the License.
<item>30 分</item>
</string-array>
<!-- Minimum required accuracy -->
<string-array name="min_required_accuracy_options">
<item>10 m (GPS信号強度良好)</item>
@@ -115,10 +100,9 @@ limitations under the License.
<item>3.1 mi (GPS信号強度不良)</item>
</string-array>
<!-- Split frequency -->
<string-array name="split_frequency_options">
<item>分割なし</item>
<!-- Task frequency -->
<string-array name="task_frequency_options">
<item>不使用</item>
<item>100 km</item>
<item>50 km</item>
<item>25 km</item>
@@ -134,8 +118,8 @@ limitations under the License.
<item>1 分</item>
</string-array>
<string-array name="split_frequency_options_ft">
<item>分割なし</item>
<string-array name="task_frequency_options_ft">
<item>不使用</item>
<item>100 mi</item>
<item>50 mi</item>
<item>25 mi</item>
@@ -287,4 +271,5 @@ limitations under the License.
<item>噴水</item>
<item>ウェイポイント</item>
</array>
</resources>
+65 -19
View File
@@ -35,6 +35,7 @@ limitations under the License.
<!-- Error messages -->
<string name="error_no_location_manager">この端末でロケーションマネージャを発見できませんでした.</string>
<string name="error_no_gps_location_provider">この端末でGPSロケーションプロバイダを発見できました.</string>
<string name="error_sending_to_mymap">Googleマイマップへのトラック送信でエラーが発生しました.しばらく待って試して下さい.</string>
<string name="error_sending_to_fusiontables">Google Fusion Tablesへのトラック送信でエラーが発生しました.しばらく待って試して下さい.</string>
<string name="error_sending_to_docs">Google Docsへのトラック送信でエラーが発生しました.しばらく待って試して下さい.</string>
<string name="error_unable_to_start_recording">記録作成開始できません.もう一度試して下さい.</string>
@@ -50,11 +51,13 @@ limitations under the License.
<string name="wait_for_fix">GPS位置精度がよくなるまで待機しています.空が見えるところにいて下さい.</string>
<string name="status_now_recording">新しいトラックを記録中です.</string>
<string name="status_stopped_recording">トラック記録を停止しました.</string>
<string name="status_new_mymap_has_been_created">新しいマイマップをmap.google.comに作成しました.</string>
<string name="status_new_fusiontable_has_been_created">新しいGoogle Fusion Tableをgoogle.com/fusiontablesに作成しました.</string>
<string name="status_tracks_have_been_uploaded">トラックをmaps.google.comに送信しました.</string>
<string name="status_tracks_have_been_uploaded_to_new_doc">トラックをdocs.google.comの新しいスプレッドシートに送信しました.</string>
<string name="status_tracks_have_been_uploaded_to_docs">トラックをdocs.google.comに送信しました.</string>
<string name="status_enable_gps">ここをタップして「位置情報とセキュリティの設定」を開いて「GPS機能を使用」にチェックして下さい.バックボタンで戻ってください.</string>
<string name="status_mymap_info">新しいトラックが表示されるまでに数分かかることがあります.</string>
<string name="status_enable_gps">ここをタップして「位置情報とセキュリティの設定」を開いて「GPS機能を使用」にチェックを入れて下さい.バックボタンで戻ってください.</string>
<string name="status_approximate_location">ご注意: 携帯電話中継局とWi-Fiネットワークから大まかな位置を特定します.</string>
<string name="status_no_location">現在位置決定ができません.位置取得源を増やし(位置情報とセキュリティの設定 をご覧ください)、空が見えるようにして下さい.もう一度試して下さい.</string>
<string name="status_waypoint_inserted">ウェイポイントマーカーを挿入しました.</string>
@@ -62,14 +65,17 @@ limitations under the License.
<!-- Progress dialog -->
<string name="progress_title">お待ちください...</string>
<string name="progress_message">トラックをGoogleに送信しました.</string>
<string name="progress_message">トラックをGoogleに送信しています.</string>
<string name="progress_message_reading_track">トラックを読んでいます...</string>
<string name="progress_message_preparing_track">トラックを準備しています...</string>
<string name="progress_message_authenticating_fusiontables">Google Fusion Tablesへの認証を行っています...</string>
<string name="progress_message_authenticating_mymaps">Googleマップへの認証を行っています...</string>
<string name="progress_message_authenticating_docs">Google Docsへの認証を行っています...</string>
<string name="progress_message_sending_docs">トラックをGoogle Docsに送信しています...</string>
<string name="progress_message_sending_mymaps">トラックをGoogleマップに送信しています...</string>
<string name="progress_message_creating_map">新しいマイマップを作成しています...</string>
<string name="progress_message_sending_fusiontables">トラックをFusion Tablesに送信しています...</string>
<string name="progress_message_creating_fusiontable">新しいFusion Tablesを生成しています...</string>
<string name="progress_message_creating_fusiontable">新しいFusionテーブルを生成しています...</string>
<string name="import_progress_message">GPSトラックをインポートしています.若干時間がかかります.</string>
<string name="write_progress_message">SDカードにデータを書き込んでいます.若干時間がかかります.</string>
<string name="progress_message_updating_track">トラック統計情報を更新しています...</string>
@@ -84,6 +90,10 @@ limitations under the License.
<string name="new_map_description">Android用My Tracksで作成</string>
<string name="fusiontable_link">Android用&lt;a href=\'http://mytracks.appspot.com\'&gt;My Tracks&lt;/a&gt;で作成しました.</string>
<!-- Text and links when uploading to Google My Maps -->
<string name="my_map_link">Android用&lt;a href=\'http://mytracks.appspot.com\'&gt;My Tracks&lt;/a&gt;で作成しました.</string>
<string name="new_map_title">新規マップ</string>
<!-- Formatting of track and marker descriptions -->
<string name="points">ポイント</string>
<string name="recorded_date">記録日</string>
@@ -113,10 +123,12 @@ limitations under the License.
<!-- TrackList -->
<string name="tracklist_show_track">表示</string>
<string name="tracklist_send_to_fusiontables">Google Fusion Tablesへ送信</string>
<string name="tracklist_send_to_new_fusiontable">新規Google Fusion Tableへ送信</string>
<string name="tracklist_send_to_docs">Google Docsへ送信</string>
<string name="tracklist_send_to_google">Googleへ送信...</string>
<string name="tracklist_send_to_mymaps">Googleマイマップに送信</string>
<string name="tracklist_send_to_new_mymap">新規Googleマイマップに送信</string>
<string name="tracklist_send_to_fusiontables">Google Fusion Tablesに送信</string>
<string name="tracklist_send_to_new_fusiontable">新規Google Fusion Tableに送信</string>
<string name="tracklist_send_to_docs">Google Docsに送信</string>
<string name="tracklist_send_to_google">Googleに送信...</string>
<string name="tracklist_delete_track">端末から削除...</string>
<string name="tracklist_edit_track">詳細編集</string>
<string name="tracklist_write_to_sd">SDへの書き込み...</string>
@@ -124,20 +136,32 @@ limitations under the License.
<string name="tracklist_save_as_kml">KMLファイルの保存</string>
<string name="tracklist_save_as_csv">CVSファイルの保存</string>
<string name="tracklist_save_as_tcx">TCXファイルの保存</string>
<string name="tracklist_btn_send_all_to_fusiontables">Google Fusion Tablesへの送信</string>
<string name="tracklist_btn_delete_all">全トラックの削除</string>
<string name="tracklist_btn_send_all_to_fusiontables">Google Fusion Tablesに送信</string>
<string name="tracklist_btn_send_all_to_mymaps">Googleマイマップに送信</string>
<string name="tracklist_btn_delete_all">全て削除</string>
<!-- Export All -->
<string name="tracklist_btn_export_all">全トラックの出力</string>
<string name="tracklist_btn_export_all">全て出力</string>
<string name="export_done">出力終了</string>
<string name="tracklist_pick_one">トラックを選択します.オプションを表示するには長押しして下さい.</string>
<string name="tracklist_all_tracks">全てのトラック:</string>
<string name="tracklist_all_tracks">全トラック:</string>
<string name="tracklist_this_track">このトラック</string>
<string name="tracklist_share_track">共有...</string>
<string name="tracklist_share_link">マップへのリンク</string>
<string name="tracklist_share_gpx_file">GPXファイル</string>
<string name="tracklist_share_kml_file">KMLファイル</string>
<string name="tracklist_share_csv_file">CSVファイル</string>
<string name="tracklist_share_tcx_file">TCXファイル</string>
<string name="tracklist_clear_map">マップの消去</string>
<string name="tracklist_clear_map">マップのクリア</string>
<!-- Import All -->
<string name="tracklist_btn_import_all">全てインポート</string>
<!-- Format:
$1 : Successful imports
$2 : Attempted imports
$3 : MyTracks gpx path
-->
<string name="import_multi_done">%3$s からGPXファイル %2$d件のうち %1$d件をインポートしました</string>
<string name="import_multi_empty">%s ではGPXファイルがありません.SDカードを読み込めないかディレクトリにGPXファイルが無いかも知れません.</string>
<string name="import_error">ファイル %s のインポートエラー</string>
<!-- Waypoints list -->
<string name="waypointslist_btn_delete_all">全てのマーカーの削除</string>
@@ -190,7 +214,7 @@ limitations under the License.
<string name="settings_map_public">マップの公開</string>
<string name="settings_map_public_summary_on">アップロードされたマップはmaps.google.comで誰でも閲覧できます</string>
<string name="settings_map_public_summary_off">アップロードされたマップはmaps.google.comのリストに公開されません.</string>
<string name="settings_map_public_summary_off">アップロードされたマップはmaps.google.comのリストに公開されません</string>
<string name="settings_report_speed_or_pace">速度表示</string>
<string name="settings_report_speed_or_pace_summary_on">速度が表示されます</string>
@@ -231,7 +255,6 @@ limitations under the License.
<string name="settings_backup_to_sd_summary">SDカードに全てのトラックと設定をバックアップします</string>
<string name="settings_restore_from_sd">今すぐ復元</string>
<string name="settings_restore_from_sd_summary">SDカードから全てのトラックと設定を復元します</string>
<string name="settings_no_backup_while_recording">トラック記録中はバックアップ操作はできません.</string>
<string name="restore_overwrites_warning">SDカードからの復元を実行すると、現在のトラックと設定は *全て上書き* されてしまいます.よろしいですか?</string>
<string name="select_backup_to_restore">復元するバックアップの選択</string>
@@ -242,6 +265,23 @@ limitations under the License.
<!-- MyTracksSky -->
<string name="mytracks_sky">GPS衛星</string>
<!-- My Maps -->
<string name="select_map_message">アカウントからのマップ選択:</string>
<string name="create_new_map">新規マップ作成...</string>
<string name="map_list_title">Googleマイマップに送信</string>
<string name="maps_list_loading">マップをロード中...</string>
<string name="maps_list_failed">今回はマップをロードできませんでした!</string>
<string name="open_map">このマップを選択</string>
<string name="edit_map_details">マップ詳細編集</string>
<string name="share_track">トラック共有</string>
<string name="delete_map">アカウントからマップを削除</string>
<string name="map_title">マップタイトル:</string>
<string name="map_description">マップ説明:</string>
<string name="map_searchable_edit">このマップまたはコンテンツを検索結果に表示</string>
<string name="map_not_searchable_edit">このマップまたはコンテンツを検索結果に表示しない(直接URLで見られる可能性があります)</string>
<string name="map_searchable">このマップまたはコンテンツは検索結果に表示されます</string>
<string name="map_not_searchable">このマップもコンテンツも検索結果に表示されませんが、直接リンクで見られる可能性があります</string>
<!-- Sharing -->
<string name="share_map">マップ共有</string>
<string name="share_map_subject">マップを共有したいと思います</string>
@@ -332,7 +372,6 @@ limitations under the License.
<string name="cadence">ケイデンス</string>
<string name="heart_rate">心拍数</string>
<string name="max_heart_rate">最大心拍数</string>
<string name="unknown">-</string>
<string name="waiting">待機中...</string>
<!-- End User License Agreement -->
@@ -350,8 +389,10 @@ limitations under the License.
<!-- Send to Google -->
<string name="sendtogoogle_title">送信...</string>
<string name="sendtogoogle_google_fusiontables">Googleマイマップ</string>
<string name="sendtogoogle_google_mymaps">Googleマイマップ</string>
<string name="sendtogoogle_send_now">今すぐ送信</string>
<string name="sendtogoogle_create_new_map">新規マップ作成</string>
<string name="sendtogoogle_pick_existing_map">既存マップ選択</string>
<string name="sendtogoogle_send_stats">トラック統計情報送信</string>
<string name="sendtogoogle_send_stats_and_points">統計情報とポイント送信</string>
@@ -364,7 +405,7 @@ limitations under the License.
<string name="io_no_external_storage_found">外部ストレージを発見できませんでした.SDカードが刺さっているか、端末がコンピュータにマウントされていないか確認してください.</string>
<string name="io_write_failed">ファイルへの書き込みができません.</string>
<string name="io_read_failed">ファイルからの読み込みができません.</string>
<string name="io_create_dir_failed">SDカードにディレクトリを作成できません.</string>
<string name="io_create_dir_failed">SDカード上でディレクトリを作成できません.</string>
<string name="io_write_finished">SDカードへの書き込み終了.</string>
<string name="io_read_finished">SDカードからの読み込み終了.</string>
@@ -397,11 +438,11 @@ limitations under the License.
<string name="check_units_message">デフォルトの単位はメートルです.設定を変更しますか?</string>
<!-- Fake preference keys - never saved, but show options in the preferences screen -->
<!-- string name="method_bluetooth">Bluetooth</string --> <!-- duplicate -->
<string name="bluetooth_options">Bluetoothオプション</string>
<string name="bluetooth_pairing">ペアリング</string>
<string name="bluetooth_pairing_summary">ペアリングを行うには「Bluetooth設定」を開いて下さい</string>
<string name="sensor_bluetooth_options_key">bluetoothSensorsEnabled</string>
<string name="ant_options">ANTオプション</string>
<string name="sensor_options">センサーオプション</string>
<!-- Bluetooth Sensor -->
@@ -422,10 +463,15 @@ limitations under the License.
<string name="searching">検索中</string>
<string name="sending">送信中</string>
<!-- Sensor Type Options -->
<string name="no_sensor_option">なし</string>
<string name="ant_sensor_option">ANT+ センサー</string>
<string name="ant_bridge_sensor_option">SRM ANT+ ブリッジ</string>
<!-- Manifest description (not seen inside the app) -->
<string name="notification_permission_label">トラック記録通知受信</string>
<string name="read_tracks_permission_label">トラック読み込み</string>
<string name="write_tracks_permission_label">トラック書き込み トラック記録の開始・終了</string>
<string name="write_tracks_permission_label">トラック書き込みとトラック記録の開始・終了</string>
<string name="notification_permission_description">トラック記録の開始・終了時に通知されます.</string>
<string name="read_tracks_permission_description">ポイントやウェイポイントといったトラックの読み込みを可能にします.</string>
<string name="write_tracks_permission_description">記録開始やウェイポイント追加といったトラック記録を可能にします.</string>
+10 -22
View File
@@ -15,18 +15,6 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Task frequency -->
<string-array name="task_frequency_options">
<item>Brak</item>
<item>1 min</item>
<item>2 min</item>
<item>5 min</item>
<item>10 min</item>
<item>15 min</item>
<item>30 min</item>
<item>60 min</item>
</string-array>
<!-- Minimum recording distance -->
<string-array name="min_recording_distance_options">
<item>1 m</item>
@@ -112,9 +100,9 @@ limitations under the License.
<item>3.1 mili (słaby sygnał GPS)</item>
</string-array>
<!-- Split frequency -->
<string-array name="split_frequency_options">
<item>Brak dzielenia</item>
<!-- Task frequency -->
<string-array name="task_frequency_options">
<item>Brak</item>
<item>100 km</item>
<item>50 km</item>
<item>25 km</item>
@@ -130,8 +118,8 @@ limitations under the License.
<item>1 min</item>
</string-array>
<string-array name="split_frequency_options_ft">
<item>Brak dzielenia</item>
<string-array name="task_frequency_options_ft">
<item>Brak</item>
<item>100 mi</item>
<item>50 mi</item>
<item>25 mi</item>
@@ -146,7 +134,7 @@ limitations under the License.
<item>2 min</item>
<item>1 min</item>
</string-array>
<!-- Auto-resume track timeout -->
<string-array name="auto_resume_track_timeout_options">
<item>Nigdy</item>
@@ -162,7 +150,7 @@ limitations under the License.
<item>typ mieszany</item>
<item>inny</item>
<item>bieanie</item>
<item>bieganie</item>
<item>bieganie uliczne</item>
<item>bieganie na torze</item>
<item>bieganie terenowe</item>
@@ -182,10 +170,10 @@ limitations under the License.
<item>łyżwiarstwo torowe</item>
<item>deskorolka</item>
<item>wędrówka po sniegu</item>
<item>wędrówka po śniegu</item>
<item>narciarstwo</item>
<item>snowboard</item>
<item>saneczkastwo</item>
<item>saneczkarstwo</item>
<item>żeglarstwo lodowe</item>
<item>żeglowanie</item>
@@ -249,7 +237,7 @@ limitations under the License.
<item>kominek</item>
<item>remiza strażacka</item>
<item>baza wędkarska</item>
<item>stcja paliw</item>
<item>stacja paliw</item>
<item>pole golfowe</item>
<item>sklep spożywczy</item>
<item>fryzjer</item>
+28 -3
View File
@@ -42,7 +42,7 @@ limitations under the License.
<string name="error_invalid_gpx_format">Plik nie jest poprawnym plikiem GPX.</string>
<string name="error_generic">Wystąpił błąd. Spróbuj ponownie.</string>
<string name="error_track_does_not_exist">Trasa nie istnieje.</string>
<string name="error_out_of_memory">Plik jest za duży (musi być mniejszy nić 500 KB). Przerywam.</string>
<string name="error_out_of_memory">Plik jest za duży (musi być mniejszy niż 500 KB). Przerywam.</string>
<string name="error_unable_to_insert_marker">Nie można wstawić markera. Brak poprawnych danych o lokalizacji.</string>
<!-- Status messages -->
@@ -217,7 +217,6 @@ limitations under the License.
<string name="settings_backup_to_sd_summary">Tworzy kopię zapasową wszystkich tras i ustawień i zapisuje je na karcie SD</string>
<string name="settings_restore_from_sd">Odtwórz z kopii</string>
<string name="settings_restore_from_sd_summary">Odtwarza wszystkie trasy i ustawienia z kopii zapasowej z karty SD</string>
<string name="settings_no_backup_while_recording">Nie można tworzyć/odtwarzać kopii zapasowej podczas rejestrowania trasy.</string>
<!-- Backups -->
<string name="restore_overwrites_warning">Odtworzenie z kopii zapasowej z karty SD zastąpi wszystkie bieżące trasy i ustawienia. Jesteś tego pewien?</string>
@@ -335,7 +334,6 @@ limitations under the License.
<string name="about_team">Zespół:</string>
<string name="about_version">Wersja:</string>
<string name="about_support">Wsparcie:</string>
<string name="about_bart">Bartłomiej Niechwiej</string>
<!-- Send to Google -->
<string name="sendtogoogle_title">Wyślij do...</string>
@@ -386,4 +384,31 @@ limitations under the License.
<!-- Check Units -->
<string name="check_units_title">Jednostki miary</string>
<string name="check_units_message">Domyślnie używane są jednostki metryczne. Chcesz to zmienić?</string>
<!-- Fake preference keys - never saved, but show options in the preferences screen -->
<string name="method_bluetooth">Bluetooth</string>
<string name="bluetooth_options">Opcje Bluetooth</string>
<string name="bluetooth_pairing">Parowanie urządzenia</string>
<string name="bluetooth_pairing_summary">Przejdź do ustawień Bluetooth Androida aby sparować urządzenie</string>
<string name="sensor_bluetooth_options_key">bluetoothSensorsEnabled</string>
<string name="ant_options">Opce ANT</string>
<string name="sensor_options">Opcje Czujników</string>
<!-- Bluetooth Sensor -->
<string name="bluetooth_connected">Połączony z %s</string>
<string name="bluetooth_connecting">Łączenie urządzenia Bluetooth w toku...</string>
<string name="bluetooth_not_connected">Urządzenie Bluetooth niepołączone</string>
<!-- Sensor State -->
<string name="sensor_data_time">Czas Danych Czujnika</string>
<string name="power_meter_enabled">Miernik mocy aktywny</string>
<string name="heart_rate_monitor_enabled">Pulsometr aktywny</string>
<string name="no_sensor_manager">Brak Ustawień Czujników</string>
<string name="enabled">Aktywny</string>
<string name="connecting">Łączenie</string>
<string name="connected">Podłączony</string>
<string name="disconnected">Rozłączony</string>
<string name="no_sensor_service">Brak Serwisu Czujników</string>
<string name="searching">Wykrywanie</string>
<string name="sending">Przesyłanie</string>
</resources>
+19 -36
View File
@@ -15,21 +15,8 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Task frequency -->
<array name="task_frequency_options">
<item>Desligado</item>
<item>1 min</item>
<item>2 min</item>
<item>5 min</item>
<item>10 min</item>
<item>15 min</item>
<item>30 min</item>
<item>60 min</item>
</array>
<!-- Minimum recording distance -->
<array name="min_recording_distance_options">
<string-array name="min_recording_distance_options">
<item>1 m</item>
<item>2 m</item>
<item>3 m</item>
@@ -37,9 +24,9 @@ limitations under the License.
<item>5 m (recomendada)</item>
<item>10 m</item>
<item>100 m</item>
</array>
</string-array>
<array name="min_recording_distance_options_ft">
<string-array name="min_recording_distance_options_ft">
<item>3 pés</item>
<item>6 pés</item>
<item>10 pés</item>
@@ -47,31 +34,29 @@ limitations under the License.
<item>16 pés (recomendado)</item>
<item>33 pés</item>
<item>328 pés</item>
</array>
</string-array>
<!-- Maximum recording distance -->
<array name="max_recording_distance_options">
<string-array name="max_recording_distance_options">
<item>50 m</item>
<item>100 m</item>
<item>200 m (recomendado)</item>
<item>500 m</item>
<item>1000 m</item>
<item>5000 m</item>
</array>
</string-array>
<array name="max_recording_distance_options_ft">
<string-array name="max_recording_distance_options_ft">
<item>164 pés</item>
<item>328 pés</item>
<item>656 pés (recomendado)</item>
<item>1640 pés</item>
<item>0.6 milhas</item>
<item>3.1 milhas</item>
</array>
</string-array>
<!-- Minimum recording interval -->
<array name="min_recording_interval_options">
<string-array name="min_recording_interval_options">
<item>economia de bateria (adaptativo)</item>
<item>alta precisão (adaptativo)</item>
<item>máxima (recomendada)</item>
@@ -88,11 +73,10 @@ limitations under the License.
<item>10 min</item>
<item>15 min</item>
<item>30 min</item>
</array>
</string-array>
<!-- Minimum required accuracy -->
<array name="min_required_accuracy_options">
<string-array name="min_required_accuracy_options">
<item>10 m (sinal de GPS excelente)</item>
<item>20 m</item>
<item>50 m</item>
@@ -102,9 +86,9 @@ limitations under the License.
<item>1000 m</item>
<item>2000 m</item>
<item>5000 m (sinal de GPS ruim)</item>
</array>
</string-array>
<array name="min_required_accuracy_options_ft">
<string-array name="min_required_accuracy_options_ft">
<item>33 pés (sinal de GPS excelente)</item>
<item>66 pés</item>
<item>165 pés</item>
@@ -114,12 +98,11 @@ limitations under the License.
<item>0.6 milhas</item>
<item>1.2 milhas</item>
<item>3.1 milhas (sinal de GPS ruim)</item>
</array>
</string-array>
<!-- Split frequency -->
<string-array name="split_frequency_options">
<item>Sem divisões</item>
<!-- Task frequency -->
<string-array name="task_frequency_options">
<item>Desligado</item>
<item>100 km</item>
<item>50 km</item>
<item>25 km</item>
@@ -135,8 +118,8 @@ limitations under the License.
<item>1 min</item>
</string-array>
<string-array name="split_frequency_options_ft">
<item>Sem divisões</item>
<string-array name="task_frequency_options_ft">
<item>Desligado</item>
<item>100 mi</item>
<item>50 mi</item>
<item>25 mi</item>
+3
View File
@@ -96,6 +96,7 @@ limitations under the License.
<!-- Common -->
<string name="no">Não</string>
<string name="yes">Sim</string>
<!-- KEEP_PARENT name="ok" rev="7cbb95c69f35" -->
<string name="error">Erro</string>
<string name="success">Successo</string>
<string name="waypoint">Ponto de passagem</string>
@@ -157,6 +158,8 @@ limitations under the License.
<string name="settings_display">Exibição</string>
<string name="settings_recording">Gravação</string>
<string name="settings_sharing">Compartilhamento</string>
<string name="settings_not_available_summary">Não disponível na sua versão do Android</string>
<string name="settings_not_while_recording">Não disponível durante a gravação de uma trilha</string>
<string name="settings_announcement_frequency">Tempo entre anúncios</string>
<string name="settings_announcement_frequency_summary">Tempo mínimo entre dois anúncios de voz</string>
<string name="settings_min_recording_distance">Dist. mín. entre pontos</string>
+275
View File
@@ -0,0 +1,275 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2010 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Minimum recording distance -->
<string-array name="min_recording_distance_options">
<item>1 м</item>
<item>2 м</item>
<item>3 м</item>
<item>4 м</item>
<item>5 м (рекомендуется)</item>
<item>10 м</item>
<item>100 м</item>
</string-array>
<string-array name="min_recording_distance_options_ft">
<item>3 фута</item>
<item>6 футов</item>
<item>10 футов</item>
<item>13 футов</item>
<item>16 футов (рекомендуется)</item>
<item>33 фута</item>
<item>328 футов</item>
</string-array>
<!-- Maximum recording distance -->
<string-array name="max_recording_distance_options">
<item>50 м</item>
<item>100 м</item>
<item>200 м (рекомендуется)</item>
<item>500 м</item>
<item>1000 м</item>
<item>5000 м</item>
</string-array>
<string-array name="max_recording_distance_options_ft">
<item>164 фута</item>
<item>328 футов</item>
<item>656 фута (рекомендуется)</item>
<item>1640 футов</item>
<item>0,6 мили</item>
<item>3,1 мили</item>
</string-array>
<!-- Minimum recording interval -->
<string-array name="min_recording_interval_options">
<item>экономия батареи (адаптивная)</item>
<item>высокая точность (адаптивная)</item>
<item>высочайшая точность (рекомендуется)</item>
<item>2 с</item>
<item>3 с</item>
<item>4 с</item>
<item>5 с</item>
<item>10 с</item>
<item>20 с</item>
<item>30 с</item>
<item>1 мин</item>
<item>2 мин</item>
<item>5 мин</item>
<item>10 мин</item>
<item>15 мин</item>
<item>30 мин</item>
</string-array>
<!-- Minimum required accuracy -->
<string-array name="min_required_accuracy_options">
<item>10 м (отличный сигнал GPS)</item>
<item>20 м</item>
<item>50 м</item>
<item>100 м</item>
<item>200 м (рекомендуется)</item>
<item>500 м</item>
<item>1000 м</item>
<item>2000 м</item>
<item>5000 м (плохой сигнал GPS)</item>
</string-array>
<string-array name="min_required_accuracy_options_ft">
<item>33 фута (отличный сигнал GPS)</item>
<item>66 футов</item>
<item>165 футов</item>
<item>328 футов</item>
<item>656 футов (рекомендуется)</item>
<item>1640 футов</item>
<item>0,6 мили</item>
<item>1,2 мили</item>
<item>3,1 мили (плохой сигнал GPS)</item>
</string-array>
<!-- Task frequency -->
<string-array name="task_frequency_options">
<item>Выкл.</item>
<item>100 км</item>
<item>50 км</item>
<item>25 км</item>
<item>10 км</item>
<item>5 км</item>
<item>1 км</item>
<item>60 мин</item>
<item>30 мин</item>
<item>15 мин</item>
<item>10 мин</item>
<item>5 мин</item>
<item>2 мин</item>
<item>1 мин</item>
</string-array>
<string-array name="task_frequency_options_ft">
<item>Выкл.</item>
<item>100 миль</item>
<item>50 миль</item>
<item>25 миль</item>
<item>10 миль</item>
<item>5 миль</item>
<item>1 миля</item>
<item>60 мин</item>
<item>30 мин</item>
<item>15 мин</item>
<item>10 мин</item>
<item>5 мин</item>
<item>2 мин</item>
<item>1 мин</item>
</string-array>
<!-- Auto-resume track timeout -->
<string-array name="auto_resume_track_timeout_options">
<item>Никогда</item>
<item>5 мин</item>
<item>10 мин</item>
<item>15 мин</item>
<item>Всегда</item>
</string-array>
<!-- Other non-preference arrays -->
<array name="activity_types">
<item>не определен</item>
<item>смешанного типа</item>
<item>другое</item>
<item>бег</item>
<item>бег по улице</item>
<item>бег по треку</item>
<item>бег по тропе</item>
<item>ходьба</item>
<item>быстрая ходьба</item>
<item>пешая прогулка</item>
<item>прогулка по туристической тропе</item>
<item>прогулка по бездорожью</item>
<item>восхождение</item>
<item>велосипедная прогулка</item>
<item>шоссейный велосипед</item>
<item>горный велосипед</item>
<item>велотрек</item>
<item>катание на коньках</item>
<item>катания на роликовых коньках</item>
<item>катания на роликовых коньках</item>
<item>прогулка на снегоступах</item>
<item>лыжи</item>
<item>сноубординг</item>
<item>сани</item>
<item>ледяной парусный спорт</item>
<item>парусный спорт</item>
<item>гребля</item>
<item>каякинг</item>
<item>академическая гребля</item>
<item>моторная лодка</item>
<item>паром</item>
<item>RC лодка</item>
<item>серфинг</item>
<item>виндсерфинг</item>
<item>кайтсерфинг</item>
<item>водные лыжи</item>
<item>вейкбординг</item>
<item>самолет</item>
<item>гидроплан</item>
<item>коммерческий самолет</item>
<item>вертолет</item>
<item>воздушный шар</item>
<item>дирижабль</item>
<item>RC самолет</item>
<item>RC вертолет</item>
<item>прыжки</item>
<item>планеризм</item>
<item>дельтаплан</item>
<item>парный планеризм</item>
<item>верховая езда</item>
<item>катание на лошадях</item>
<item>прогулка на осле</item>
<item>вождение автомобиля</item>
<item>вождение автобуса</item>
<item>поезд</item>
<item>мотоцикл</item>
<item>Байк</item>
<item>ATV</item>
<item>парусный спорт на земле</item>
<item>фрисби</item>
<item>алтимат фризби</item>
</array>
<array name="waypoint_types">
<item>банкомат</item>
<item>банк</item>
<item>бар</item>
<item>барбекю</item>
<item>здание</item>
<item>автобусная остановка</item>
<item>кафе</item>
<item>костер</item>
<item>лагерь</item>
<item>церковь</item>
<item>кофейня</item>
<item>удобный магазин</item>
<item>питьевая вода</item>
<item>оползень</item>
<item>паром</item>
<item>камин</item>
<item>пожарная станция</item>
<item>рыболовство</item>
<item>автозаправочная станция</item>
<item>поле для гольфа</item>
<item>продуктовый магазин</item>
<item>парикмахерская</item>
<item>гавань</item>
<item>тропа</item>
<item>отель</item>
<item>дом</item>
<item>информация</item>
<item>пересечение</item>
<item>почтовый ящик</item>
<item>рынок</item>
<item>место встречи</item>
<item>опера</item>
<item>парковка</item>
<item>почтовое отделение</item>
<item>выбоина</item>
<item>полицейский участок</item>
<item>железнодорожный переезд</item>
<item>ресторан</item>
<item>покупки</item>
<item>вид</item>
<item>магазин</item>
<item>бассейн</item>
<item>телефон</item>
<item>театр</item>
<item>туалет</item>
<item>туристическая информация</item>
<item>туннель</item>
<item>дерево</item>
<item>водопад</item>
<item>фонтан</item>
<item>путевая точка</item>
</array>
</resources>
+505
View File
@@ -0,0 +1,505 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2010 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Used by the Menu -->
<string name="start_recording">Запись трека</string>
<string name="stop_recording">Остановить запись</string>
<string name="switch_to_sat">Режим спутника</string>
<string name="switch_to_map">Режим карты</string>
<string name="mylocation">Мое местоположение</string>
<string name="list_tracks">Треки</string>
<string name="list_markers">Маркеры</string>
<string name="delete_all_tracks">Удалить все треки</string>
<string name="settings">Настройки</string>
<string name="elevation">Высота</string>
<string name="choose_track_message">Пожалуйста, выберите трек для просмотра</string>
<string name="current_track">Текущий трек</string>
<string name="current_segment">Последний сегмент</string>
<string name="sensor_state">Состояние датчика</string>
<string name="aggregated_stats">Совокупная статистика</string>
<!-- Error messages -->
<string name="error_no_location_manager">На этом устройстве не был обнаружен диспетчер местоположения!</string>
<string name="error_no_gps_location_provider">На этом устройстве не был обнаружен поставщик GPS местоположения.</string>
<string name="error_sending_to_mymap">Ошибка при отправке вашего трека в Google \"Мои карты\".</string>
<string name="error_sending_to_fusiontables">Ошибка при отправке вашего трека в Google Fusion Tables.</string>
<string name="error_sending_to_docs">Ошибка при отправке вашего трека в Google Документы.</string>
<string name="error_please_try_again_later">Пожалуйста, повторите попытку позже.</string>
<string name="error_unable_to_start_recording">Не удалось начать запись. Попробуйте еще раз.</string>
<string name="error_unable_to_stop_recording">Не удалось остановить запись. Попробуйте еще раз.</string>
<string name="error_unable_to_read_file">Не удалось прочитать из файла.</string>
<string name="error_invalid_gpx_format">Неверный формат GPX файла.</string>
<string name="error_generic">Произошла ошибка. Пожалуйста, попробуйте еще раз.</string>
<string name="error_track_does_not_exist">Трек не существует.</string>
<string name="error_out_of_memory">Этот файл слишком большой (должен быть меньше, чем 500 КБ). Прервано.</string>
<string name="error_unable_to_insert_marker">Невозможно вставить маркер. Местоположение неизвестно.</string>
<!-- Status messages -->
<string name="wait_for_fix">Ожидание сигнала GPS. Убедитесь в том, что вы находитесь под открытым небом.</string>
<string name="status_now_recording">Записывается новый трек.</string>
<string name="status_stopped_recording">Запись вашего трека остановлена.</string>
<string name="status_new_mymap_has_been_created">Новая Google \"Мои карты\" была создана на maps.google.com.</string>
<string name="status_new_fusiontable_has_been_created">Новая таблица Google Fusion была создана на google.com/fusiontables.</string>
<string name="status_tracks_have_been_uploaded">Твой трек был отправлен на maps.google.com.</string>
<string name="status_tracks_have_been_uploaded_to_new_doc">Ваш трек был отправлен в новую электронную таблицу на docs.google.com.</string>
<string name="status_tracks_have_been_uploaded_to_docs">Ваш трек был отправлен в docs.google.com.</string>
<string name="status_mymap_info">Это может занять несколько минут, прежде чем появятся новые треки.</string>
<string name="status_enable_gps">Пожалуйста, нажмите здесь для перехода к разделу настроек Координаты и отметьте пункт \"Спутники GPS\". Для возвращения нажмите кнопку Назад.</string>
<string name="status_approximate_location">Примечание: приблизительное местоположение определено относительно вышек сотовой связи и беспроводных сетей.</string>
<string name="status_no_location">В настоящее время местоположение не может быть определено. Включите больше источников местоположение (см. раздел настроек Координаты) и убедитесь в том, что находитесь под открытым небом. Повторите попытку позднее.</string>
<string name="status_waypoint_inserted">Маркер путевой точки был вставлен.</string>
<string name="status_statistics_inserted">Маркер статистики был вставлен.</string>
<string name="status_track_upload_status">Статус загрузки:</string>
<!-- Progress dialog -->
<string name="progress_title">Пожалуйста, подождите...</string>
<string name="progress_message">Отправка вашего трека в Google.</string>
<string name="progress_message_reading_track">Чтение трека...</string>
<string name="progress_message_preparing_track">Подготовка трека...</string>
<string name="progress_message_authenticating_fusiontables">Аутентификация на Google Fusion Tables...</string>
<string name="progress_message_authenticating_mymaps">Аутентификация на Google Карты...</string>
<string name="progress_message_authenticating_docs">Аутентификация в Google Документы...</string>
<string name="progress_message_sending_docs">Отправка трека в Google Документы...</string>
<string name="progress_message_sending_mymaps">Отправка трека в Google Карты...</string>
<string name="progress_message_creating_map">Создание новой \"Моей карты\" ...</string>
<string name="progress_message_sending_fusiontables">Отправка трека в Fusion Tables...</string>
<string name="progress_message_creating_fusiontable">Создание новой Fusion table...</string>
<string name="import_progress_message">Импорт GPS трека. Это может занять некоторое время.</string>
<string name="write_progress_message">Запись файла на SD карту. Это может занять некоторое время.</string>
<string name="progress_message_updating_track">Обновление статистики трека...</string>
<!-- Used by DeleteAllDataHandler -->
<string name="are_you_sure_question">Вы уверены?</string>
<string name="all_data_will_be_permanently_deleted">Все треки и маркеры будут удалены с этого телефона.</string>
<string name="track_will_be_permanently_deleted">Трек и его маркеры будут удалены из этого телефона.</string>
<string name="marker_will_be_permanently_deleted">Маркер будет удален с этого телефона.</string>
<!-- Text and links when uploading to Google Fusion Tables -->
<string name="new_map_description">Создано My Tracks на Android.</string>
<string name="fusiontable_link">Создано &lt;a href=\'http://mytracks.appspot.com\'&gt;My Tracks&lt;/a&gt; на Android.</string>
<!-- Text and links when uploading to Google My Maps -->
<string name="my_map_link">Создано &lt;a href=\'http://mytracks.appspot.com\'&gt;My Tracks&lt;/a&gt; на Android.</string>
<string name="new_map_title">Новая карта</string>
<!-- Formatting of track and marker descriptions -->
<string name="points">Точки</string>
<string name="recorded_date">Записан</string>
<string name="category">Тип деятельности</string>
<string name="waypoint_category">Тип маркера</string>
<string name="part">(Часть %d)</string>
<!-- Used by the track recording service -->
<string name="recording_your_track">Запись трека...</string>
<string name="new_track">Трек %d</string>
<!-- Common -->
<string name="no">Нет</string>
<string name="yes">Да</string>
<string name="ok">ОК</string>
<string name="error">Ошибка</string>
<string name="success">Готово</string>
<string name="waypoint">Путевая точка</string>
<string name="license">Лицензия</string>
<string name="cancel">Отмена</string>
<string name="close">Закрыть</string>
<string name="edit">Правка</string>
<string name="save">Сохранить</string>
<!-- Placemark labels for start and end of track -->
<string name="start">(Старт)</string>
<string name="end">(Конец)</string>
<!-- TrackList -->
<string name="tracklist_show_track">Показать</string>
<string name="tracklist_send_to_mymaps">Отправить в Google \"Мои карты\"</string>
<string name="tracklist_send_to_new_mymap">Отправить в новый Google \"Мои карты\"</string>
<string name="tracklist_send_to_fusiontables">Отправить в Google Fusion Tables</string>
<string name="tracklist_send_to_new_fusiontable">Отправить в новую Google Fusion Table</string>
<string name="tracklist_send_to_docs">Отправить в Google Документы</string>
<string name="tracklist_send_to_google">Отправить в Google ...</string>
<string name="tracklist_delete_track">Удалить из телефона...</string>
<string name="tracklist_edit_track">Править детали</string>
<string name="tracklist_write_to_sd">Записать на SD карту...</string>
<string name="tracklist_save_as_gpx">Сохранить файл GPX</string>
<string name="tracklist_save_as_kml">Сохранить файл KML</string>
<string name="tracklist_save_as_csv">Сохранить файл CSV</string>
<string name="tracklist_save_as_tcx">Сохранить файл TCX</string>
<string name="tracklist_btn_send_all_to_fusiontables">Отправить в Google Fusion Tables</string>
<string name="tracklist_btn_send_all_to_mymaps">Отправить в Google \"Мои карты\"</string>
<string name="tracklist_btn_delete_all">Удалить все</string>
<!-- Export All -->
<string name="tracklist_btn_export_all">Экспорт всех</string>
<string name="export_done">Экспорт закончен</string>
<string name="tracklist_pick_one">Выберите трек. Нажмите и удерживайте для получения дополнительных возможностей.</string>
<string name="tracklist_all_tracks">Все треки:</string>
<string name="tracklist_this_track">Этот трек</string>
<string name="tracklist_share_track">Поделиться с друзьями...</string>
<string name="tracklist_share_link">Ссылка на карту</string>
<string name="tracklist_share_gpx_file">Файл GPX</string>
<string name="tracklist_share_kml_file">Файл KML</string>
<string name="tracklist_share_csv_file">Файла CSV</string>
<string name="tracklist_share_tcx_file">Файл TCX</string>
<string name="tracklist_clear_map">Очистить карту</string>
<!-- Import All -->
<string name="tracklist_btn_import_all">Импорт всех</string>
<!-- Format:
$1 : Successful imports
$2 : Attempted imports
$3 : MyTracks gpx path
-->
<string name="import_multi_done">Импортировано %1$d из %2$d GPX файлов с %3$s</string>
<string name="import_multi_empty">GPX файлы не найденны в %s. Возможно не читается SD-карта или каталог не содержит GPX файлы.</string>
<string name="import_error">Ошибка импорта файла %s</string>
<!-- Waypoints list -->
<string name="waypointslist_btn_delete_all">Удалить все маркеры</string>
<string name="waypointslist_this_waypoint">Этот маркер</string>
<string name="waypointslist_delete_waypoint">Удалить</string>
<string name="waypointslist_edit_waypoint">Править детали</string>
<string name="waypointslist_show_waypoint">Показать на карте</string>
<string name="waypointslist_btn_insert_waypoint">Вставить путевую точку</string>
<string name="waypointslist_btn_insert_statistics">Вставить статистику</string>
<string name="waypointslist_pick_one">Выберите маркер. Нажмите и удерживайте для получения дополнительных возможностей.</string>
<!-- MyTracks Details -->
<string name="trackdetails_title">Трек детали</string>
<string name="trackdetails_name">Название трека</string>
<string name="trackdetails_description">Описание трека</string>
<string name="trackdetails_category">Тип деятельности (например: пешая прогулка, велосипедная прогулка, бег, восхождение...)</string>
<!-- MyTracks Waypoint Details -->
<string name="waypointdetails_title">Маркер детали</string>
<string name="waypointdetails_name">Имя маркера</string>
<string name="waypointdetails_description">Описание маркера</string>
<string name="waypointdetails_category">Тип маркера (например: здание, выбоина, достопримечательность...)</string>
<!-- MyTracks Settings -->
<string name="mytracks_settings">Настройки My Tracks</string>
<string name="settings_display">Отображение</string>
<string name="settings_recording">Запись</string>
<string name="settings_sharing">Обмен</string>
<string name="settings_not_available_summary">Не доступен в вашем версии Android</string>
<string name="settings_not_while_recording">Не доступно во время записи трека</string>
<string name="settings_announcement_frequency">Частота объявлений</string>
<string name="settings_announcement_frequency_summary">Минимальное время между двумя голосовыми объявлениями</string>
<string name="settings_min_recording_distance">Минимальное расстояние между точками</string>
<string name="settings_min_recording_distance_summary">Наименьшее расстояние между двумя записями вашей позиции</string>
<string name="settings_max_recording_distance">Максимальное расстояние между точками</string>
<string name="settings_max_recording_distance_summary">Если два пункта находятся дальше, чем указано, то трек будет разделен</string>
<string name="settings_min_recording_interval">Минимальное время между точками</string>
<string name="settings_min_recording_interval_summary">Наименьший интервал времени между двумя записями вашей позиции</string>
<string name="settings_min_required_accuracy">Минимальная точность</string>
<string name="settings_min_required_accuracy_summary">Запись будет приостановлена, если ваша позиция не является достаточно точной</string>
<string name="settings_metric_units">Использовать метрические единицы</string>
<string name="settings_metric_units_summary_on">Все расстояния будут отображаться в метрических единицах</string>
<string name="settings_metric_units_summary_off">Все расстояния будут отображаться в имперских единицах</string>
<string name="settings_map_public">Обнародовать карты</string>
<string name="settings_map_public_summary_on">Загруженные карты будут общедоступны на maps.google.com</string>
<string name="settings_map_public_summary_off">Загруженные карты не будут перечислены публично на maps.google.com</string>
<string name="settings_report_speed_or_pace">Отображать скорость</string>
<string name="settings_report_speed_or_pace_summary_on">Скорость будет отображаться</string>
<string name="settings_report_speed_or_pace_summary_off">Темп будет отображаться</string>
<string name="settings_share_url_only">Поделиться только URL</string>
<string name="settings_share_url_only_summary_on">При обмене будет отправлен только URL-адрес</string>
<string name="settings_share_url_only_summary_off">Содержимое трека будет также включено при обмене</string>
<string name="settings_split_frequency">Частота деления</string>
<string name="settings_split_frequency_summary">Максимальное время или расстояние, после которого будет вставлен новый маркер деления</string>
<string name="settings_auto_resume_track_timeout">Автоматическое возобновление трек тайм-аут</string>
<string name="settings_auto_resume_track_timeout_summary">Максимальное время в минутах, после которого предыдущая запись трека не будет возобновлена на перезагруженном телефоне</string>
<string name="settings_timestamp_track_name">Штамп времени как название дорожки</string>
<string name="settings_timestamp_track_name_summary_on">По умолчанию имя трека будет складываться из даты и времени старта трека</string>
<string name="settings_timestamp_track_name_summary_off">Названия треков будут иметь прирост чисел для каждого нового трека.</string>
<string name="settings_reset">Восстановить значения по умолчанию</string>
<string name="settings_reset_summary">Восстановить значения по умолчанию во всех настройках</string>
<string name="settings_reset_dialog_message">Все ваши настройки будут стерты и восстановлены значения по умолчанию. Записанные треки будут сохранены. Вы уверены?</string>
<string name="settings_reset_done">Все настройки были возвращены к значениям по умолчанию.</string>
<string name="pace_label">Темп</string>
<string name="eclair_required">Поддерживается только в Android 2.0 или выше</string>
<string name="settings_sensor_type">Тип датчика</string>
<string name="settings_sensor_type_summary">Тип подключенного датчика</string>
<string name="settings_heart_rate_ant_sensor_id">Очистить ANT подсоединенного датчика пульса</string>
<string name="settings_power_ant_sensor_id">Очистить ANT подсоединенного датчика мощности</string>
<string name="settings_srm_bridge_ant_sensor_id">Очистить ANT подсоединенного датчика SRM</string>
<string name="settings_ant_not_paired">ANT датчик не подсоединен</string>
<string name="settings_ant_paired">ANT датчик подсоединен с: %d</string>
<string name="bluetooth_sensor_title">Bluetooth датчик</string>
<string name="bluetooth_sensor_summary">Подключенный bluetooth датчик</string>
<string name="settings_modular_stats_display_title">Отображение модульной статистики</string>
<!-- Backups -->
<string name="settings_backup">Резервное копирование (BETA)</string>
<string name="settings_sd_backup">Резервное копирование SD карты</string>
<string name="settings_backup_to_sd">Резервировать</string>
<string name="settings_backup_to_sd_summary">Создать полную копию всех ваших треков и настроек на SD карту</string>
<string name="settings_restore_from_sd">Восстановить</string>
<string name="settings_restore_from_sd_summary">Восстановить все треки и параметры с SD карты</string>
<string name="restore_overwrites_warning">Восстановление резервной копии с SD карты ПЕРЕЗАПИШЕТ все текущие треки и настройки. Вы уверены?</string>
<string name="select_backup_to_restore">Выберите резервную копию для восстановления</string>
<string name="no_backups">Резервные копии не найдены.</string>
<string name="backup_write_progress_message">Запись на SD-карту всех треков и настроек. Это может занять некоторое время...</string>
<string name="backup_import_progress_message">Чтение всех треков и настроек с SD-карты. Это может занять некоторое время...</string>
<!-- MyTracksSky -->
<string name="mytracks_sky">Спутники GPS</string>
<!-- My Maps -->
<string name="select_map_message">Выберите карту из вашей учетной записи:</string>
<string name="create_new_map">Создать новую карту...</string>
<string name="map_list_title">Отправить в Google \"Мои карты\"</string>
<string name="maps_list_loading">Загрузка карты ...</string>
<string name="maps_list_failed">Ваши карты не могут быть загружены в данный момент!</string>
<string name="open_map">Выберите эту карту</string>
<string name="edit_map_details">Править детали карты</string>
<string name="share_track">Поделиться треком</string>
<string name="delete_map">Удалить Карту из вашей учетной записи</string>
<string name="map_title">Название карты:</string>
<string name="map_description">Описание карты:</string>
<string name="map_searchable_edit">Сделать чтобы карта и ее содержимое отображались в результатах поиска</string>
<string name="map_not_searchable_edit">Не позволить этой карте или ее содержимому отображаться в результатах поиска, хотя они все еще могут просматриваться другими через прямой URL-адрес</string>
<string name="map_searchable">Эта карта и ее содержимое будут отображаться в результатах поиска</string>
<string name="map_not_searchable">Ни эта карта, ни ее содержимое не будут отображаться в результатах поиска, но их могут по-прежнему просматривать другие через прямую ссылку</string>
<!-- Sharing -->
<string name="share_map">Поделиться картой с друзьями</string>
<string name="share_map_subject">Я хотел бы поделиться с вами треком</string>
<string name="share_map_body_format">Я думаю, вы можете быть заинтересованы в этом треке:
%s</string>
<string name="send_track_subject">Я хотел бы поделиться с вами треком</string>
<string name="send_track_body_format">Я думаю, вы можете быть заинтересованы в этом треке.
Просмотреть трек можно с помощью Google Планета Земля или другого программного обоспечения для карт.</string>
<!-- Visibility -->
<string name="public_map">Общественные</string>
<string name="unlisted_map">Частные</string>
<string name="mapslist_no_maps_available">У вас пока еще нет карт.</string>
<!-- Statistics View -->
<!-- Average Moving -->
<string name="average_moving_speed_label">Средняя скорость движения</string>
<string name="average_moving_pace_label">Средний темп движения</string>
<!-- Average -->
<string name="average_speed_label">Средняя скорость</string>
<string name="average_pace_label">Средний темп</string>
<string name="elevation_chart_name">Диаграмма высоты</string>
<string name="elevation_gain_label">Набор высоты</string>
<string name="elevation_label">Высота</string>
<string name="latitude_label">Широта</string>
<string name="longitude_label">Долгота</string>
<!-- Min -->
<string name="min_elevation_label">Минимальная высота</string>
<string name="min_grade_label">Минимальный уклон</string>
<string name="min_pace_label">Минимальный темп</string>
<!-- Max -->
<string name="max_elevation_label">Максимальная высота</string>
<string name="max_grade_label">Максимальный уклон</string>
<string name="max_speed_label">Максимальная скорость</string>
<string name="loading_track">Загрузка трека...</string>
<!-- Chart Settings -->
<string name="chart_settings">Настройки диаграммы</string>
<!-- X Axis -->
<string name="x_axis">Ось X</string>
<string name="by_distance">По расстоянию</string>
<string name="by_time">По времени</string>
<!-- Y Axis -->
<string name="y_axis">Ось Y</string>
<!-- Units -->
<!-- Time -->
<string name="hour">час</string>
<string name="hours">часов</string>
<string name="hr">ч</string>
<string name="min">мин</string>
<string name="minute">минута</string>
<string name="minutes">минут</string>
<string name="second">секунда</string>
<string name="seconds">секунд</string>
<string name="milliseconds">мс</string>
<!-- Distance -->
<string name="meter">м</string>
<string name="kilometer">км</string>
<string name="kilometers_long">километров</string>
<string name="feet">футов</string>
<string name="mile">миль</string>
<string name="miles_long">мили</string>
<!-- Speed and Pace -->
<string name="kilometer_per_hour">км/ч</string>
<string name="kilometer_per_hour_long">километров в час</string>
<string name="min_per_kilometer">мин/км</string>
<string name="per_kilometer">за километр</string>
<string name="mile_per_hour">миль/ч</string>
<string name="mile_per_hour_long">миль в час</string>
<string name="min_per_mile">мин/миля</string>
<string name="per_mile">за милю</string>
<!-- Sensors -->
<string name="watts">Вт</string>
<string name="revolutions_per_minute">об/мин</string>
<string name="bpm">bpm</string>
<!-- Stats Labels -->
<string name="moving_time_label">Время движения</string>
<string name="total_time_label">Общее время</string>
<string name="time_label">Время</string>
<string name="sd_unavail">SD карта недоступна</string>
<string name="speed">Скорость</string>
<string name="start_trip">Вы должны начать путешествие.</string>
<string name="statistics">Статистика</string>
<string name="total_distance_label">Общее расстояние</string>
<string name="distance_label">Расстояние</string>
<string name="power">Мощность</string>
<string name="cadence">Каденс</string>
<string name="heart_rate">Пульс</string>
<string name="max_heart_rate">Максимальный пульс</string>
<string name="unknown">-</string>
<string name="waiting">Ожидание...</string>
<!-- End User License Agreement -->
<string name="eula_title">Лицензионное соглашение</string>
<string name="accept">Принять</string>
<string name="decline">Отклонить</string>
<!-- About -->
<string name="about">О программе</string>
<string name="help">Справка</string>
<string name="about_team">Команда:</string>
<string name="about_version">Версия:</string>
<string name="about_support">Поддержка:</string>
<string name="about_privacy">Приватность:</string>
<!-- Send to Google -->
<string name="sendtogoogle_title">Отправить...</string>
<string name="sendtogoogle_google_fusiontables">Google Fusion Tables</string>
<string name="sendtogoogle_google_mymaps">Google \"Мои карты\"</string>
<string name="sendtogoogle_google_docs">Google Документы</string>
<string name="sendtogoogle_send_now">Отправить</string>
<string name="sendtogoogle_create_new_map">Создать новую карту</string>
<string name="sendtogoogle_pick_existing_map">Выбрать существующую карту</string>
<string name="sendtogoogle_send_stats">Отправить статистику трека</string>
<string name="sendtogoogle_send_stats_and_points">Отправить статистику и точки</string>
<!-- Getting the account to upload to. -->
<string name="no_account_found_title">Учетная запись не найдена</string>
<string name="no_account_found">Не найдена учетная запись для загрузки треков.</string>
<string name="choose_account_title">Выбор учетной записи</string>
<!-- SD card -->
<string name="io_no_external_storage_found">Не обнаружено внешнее устройство хранения данных. Убедитесь, что SD карта вставлена, и что ваш телефон не подключен к компьютеру.</string>
<string name="io_write_failed">Невозможно записать файл.</string>
<string name="io_read_failed">Невозможно прочитать из файла.</string>
<string name="io_create_dir_failed">Невозможно создать папку на SD карте.</string>
<string name="io_write_finished">Запись на SD карту закончена.</string>
<string name="io_read_finished">Чтение с SD карты закончено.</string>
<!-- VersionChecker -->
<string name="version_check_title">Проверить обновления</string>
<string name="version_check_upgrade_button">Обновить сейчас</string>
<string name="version_check_continue_button">Продолжить без обновления</string>
<string name="upgrade_required">Ваша версия %1$S больше не может работать должным образом, и больше не поддерживается. Обновите %1$s для продолжения использования.</string>
<string name="upgrade_recommended">Ваша версия %1$S больше не может работать должным образом. Вы можете обновить ее сейчас, либо продолжать использовать ее на свой страх и риск. Некоторые функции, такие как синхронизация с сервером может не функционировать до обновления.</string>
<string name="upgrade_available">Доступна новая версия %1$s. Вы можете продолжать использовать текущую версию без проблем, но вы не получите новейшие функции, до тех пор, пока не обновитесь.</string>
<!-- Welcome -->
<string name="welcome">Добро пожаловать</string>
<string name="welcome_read_later">Ок</string>
<string name="welcome_about">О My Tracks</string>
<!-- Announcement -->
<string name="announce_no_distance">My Tracks нет расстояния</string>
<!-- Format:
$1 : Distance label
$2 : Distance value (5)
$3 : Distance units (mi, km)
$4 : Time description (10 minutes 5 seconds)
$5 : Speed value (5.6) : Pace value (5 minutes 6 seconds)
$6 : Speed units (mph) : Pace units (per mile)
-->
<string name="announce_template">Мои треки %1$s %2$.2f %3$s в %4$s на %5$s %6$s</string>
<!-- Check Units -->
<string name="check_units_title">Единицы измерения обратите внимание</string>
<string name="check_units_message">По умолчанию используются метрические единицы. Вы хотели бы изменить этот параметр?</string>
<!-- Fake preference keys - never saved, but show options in the preferences screen -->
<string name="method_bluetooth">Bluetooth</string>
<string name="bluetooth_options">Параметры Bluetooth</string>
<string name="bluetooth_pairing">Подключение устройства</string>
<string name="bluetooth_pairing_summary">Открыть настройки Android по bluetooth для подключения устройства</string>
<string name="sensor_bluetooth_options_key">bluetoothSensorsEnabled</string>
<string name="ant_options">Параметры ANT</string>
<string name="sensor_options">Параметры датчика</string>
<!-- Bluetooth Sensor -->
<string name="bluetooth_connected">Подключен к %s</string>
<string name="bluetooth_connecting">Подключение Bluetooth датчика...</string>
<string name="bluetooth_not_connected">Bluetooth датчик не подключен</string>
<!-- Sensor State -->
<string name="sensor_data_time">Датчик времени</string>
<string name="power_meter_enabled">Измеритель мощности включен</string>
<string name="heart_rate_monitor_enabled">Монитор пульса включен</string>
<string name="no_sensor_manager">Нет диспетчера датчиков</string>
<string name="enabled">Включено</string>
<string name="connecting">Подключение</string>
<string name="connected">Подключено</string>
<string name="disconnected">Отключено</string>
<string name="no_sensor_service">Нет службы датчиков</string>
<string name="searching">Поиск</string>
<string name="sending">Отправка</string>
<!-- Sensor Type Options -->
<string name="no_sensor_option">Нет</string>
<string name="ant_sensor_option">ANT+ Датчик</string>
<string name="ant_bridge_sensor_option">SRM ANT+ Bridge</string>
<!-- Manifest description (not seen inside the app) -->
<string name="notification_permission_label">получать уведомления о записи трека</string>
<string name="read_tracks_permission_label">чтение записанных данных трека</string>
<string name="write_tracks_permission_label">запись данных трека, старт/стоп записи треков</string>
<string name="notification_permission_description">Получать уведомления, при старте или останове записи трека.</string>
<string name="read_tracks_permission_description">Иметь возможность читать данные трека, такие как точки и путевые точки.</string>
<string name="write_tracks_permission_description">Иметь возможность записать данные трека, такие как начало записи или добавление путевых точек.</string>
</resources>
+5 -18
View File
@@ -15,18 +15,6 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Task frequency -->
<string-array name="task_frequency_options">
<item>Av</item>
<item>1 min</item>
<item>2 min</item>
<item>5 min</item>
<item>10 min</item>
<item>15 min</item>
<item>30 min</item>
<item>60 min</item>
</string-array>
<!-- Minimum recording distance -->
<string-array name="min_recording_distance_options">
<item>1 m</item>
@@ -67,7 +55,6 @@ limitations under the License.
<item>3.1 miles</item>
</string-array>
<!-- Minimum recording interval -->
<string-array name="min_recording_interval_options">
<item>batterioptimerad (anpassningsbar)</item>
@@ -113,9 +100,9 @@ limitations under the License.
<item>3.1 miles (dålig GPS-signal)</item>
</string-array>
<!-- Split frequency -->
<string-array name="split_frequency_options">
<item>Ingen delning</item>
<!-- Task frequency -->
<string-array name="task_frequency_options">
<item>Av</item>
<item>100 km</item>
<item>50 km</item>
<item>25 km</item>
@@ -131,8 +118,8 @@ limitations under the License.
<item>1 min</item>
</string-array>
<string-array name="split_frequency_options_ft">
<item>Ingen delning</item>
<string-array name="task_frequency_options_ft">
<item>Av</item>
<item>100 mi</item>
<item>50 mi</item>
<item>25 mi</item>
+11 -17
View File
@@ -15,18 +15,6 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Task frequency -->
<string-array name="task_frequency_options">
<item>关闭</item>
<item>1 分钟</item>
<item>2 分钟</item>
<item>5 分钟</item>
<item>10 分钟</item>
<item>15 分钟</item>
<item>30 分钟</item>
<item>60 分钟</item>
</string-array>
<!-- Minimum recording distance -->
<string-array name="min_recording_distance_options">
<item>1 米</item>
@@ -112,9 +100,9 @@ limitations under the License.
<item>3.1 英里 (糟糕的 GPS 信号)</item>
</string-array>
<!-- Split frequency -->
<string-array name="split_frequency_options">
<item>不分割</item>
<!-- Task frequency -->
<string-array name="task_frequency_options">
<item>关闭</item>
<item>100 千米</item>
<item>50 千米</item>
<item>25 千米</item>
@@ -130,8 +118,8 @@ limitations under the License.
<item>1 分钟</item>
</string-array>
<string-array name="split_frequency_options_ft">
<item>不分割</item>
<string-array name="task_frequency_options_ft">
<item>关闭</item>
<item>100 英里</item>
<item>50 英里</item>
<item>25 英里</item>
@@ -155,6 +143,7 @@ limitations under the License.
<item>15 分钟</item>
<item>总是</item>
</string-array>
<!-- Other non-preference arrays -->
<array name="activity_types">
<item>未知</item>
@@ -181,6 +170,11 @@ limitations under the License.
<item>轮滑</item>
<item>滑板</item>
<item>滚轮滑雪 (传统)</item>
<item>滚轮滑雪 (滑板)</item>
<item>越野滑雪 (传统)</item>
<item>越野滑雪 (滑板)</item>
<item>雪攀</item>
<item>滑雪</item>
<item>雪板</item>
+96 -15
View File
@@ -29,19 +29,23 @@ limitations under the License.
<string name="choose_track_message">请选择要查看的轨迹</string>
<string name="current_track">当前轨迹</string>
<string name="current_segment">上一段轨迹</string>
<string name="sensor_state">感应器状态</string>
<string name="aggregated_stats">累积统计</string>
<!-- Error messages -->
<string name="error_no_location_manager">此设备上没有位置管理器!</string>
<string name="error_no_gps_location_provider">此设备上没有 GPS 定位装置.</string>
<string name="error_sending_to_fusiontables">发送你的轨迹到 Google Fusion Tables 时发生错误. 请稍后重试.</string>
<string name="error_sending_to_docs">发送你的轨迹到 Google Docs 时发生错误. 请稍后重试.</string>
<string name="error_sending_to_mymap">发送轨迹到 Google My Map 时发生错误.</string>
<string name="error_sending_to_fusiontables">发送轨迹到 Google Fusion Tables 时发生错误. 请稍后重试.</string>
<string name="error_sending_to_docs">发送轨迹到 Google Docs 时发生错误. 请稍后重试.</string>
<string name="error_please_try_again_later">请稍后再试.</string>
<string name="error_unable_to_start_recording">无法开始记录. 请重试.</string>
<string name="error_unable_to_stop_recording">无法停止记录. 请重试.</string>
<string name="error_unable_to_read_file">无法读取文件.</string>
<string name="error_invalid_gpx_format">文件不是有效的 GPX 格式.</string>
<string name="error_generic">发生错误. 请重试.</string>
<string name="error_track_does_not_exist">轨迹不存在.</string>
<string name="error_operation_cancelled">操作已被取消.</string>
<string name="error_out_of_memory">文件太大 (必须小于 500 KB). 中止操作.</string>
<string name="error_unable_to_insert_marker">无法插入标记. 定位尚未完成.</string>
@@ -49,15 +53,18 @@ limitations under the License.
<string name="wait_for_fix">等待更准确的 GPS 定位. 请确定可以看见天空.</string>
<string name="status_now_recording">现在开始记录新的轨迹.</string>
<string name="status_stopped_recording">停止记录你的轨迹.</string>
<string name="status_new_mymap_has_been_created">已在 maps.google.com 创建了新的 Google My Map.</string>
<string name="status_new_fusiontable_has_been_created">已在 google.com/fusiontables 创建新 Google Fusion Table.</string>
<string name="status_tracks_have_been_uploaded">你的轨迹已经发送到 maps.google.com.</string>
<string name="status_tracks_have_been_uploaded_to_new_doc">你的轨迹已经作为新的电子表格发送到 docs.google.com.</string>
<string name="status_tracks_have_been_uploaded_to_docs">你的轨迹已经发送到 docs.google.com.</string>
<string name="status_mymap_info">可能需要等待几分钟才能看见新的轨迹.</string>
<string name="status_enable_gps">请点击这里进入\'安全和位置设置\'并勾选上\'启用 GPS 卫星\'. 然后用后退键返回.</string>
<string name="status_approximate_location">注意: 当前显示的位置是根据无线信号和无线网络计算的近似位置.</string>
<string name="status_no_location">目前无法定位. 请启用更多的位置来源 (在\'安全和位置设置\'中) 并确认天空是可见的. 再重试.</string>
<string name="status_waypoint_inserted">插入了一个路点标记.</string>
<string name="status_statistics_inserted">插入了一个统计标记.</string>
<string name="status_track_upload_status">上传状态:</string>
<!-- Progress dialog -->
<string name="progress_title">请稍候...</string>
@@ -69,6 +76,9 @@ limitations under the License.
<string name="progress_message_sending_docs">发送轨迹到 Google Docs 中...</string>
<string name="progress_message_sending_fusiontables">发送轨迹到 Google Fusion Tables 中...</string>
<string name="progress_message_creating_fusiontable">创建新的 Fusion Table 中...</string>
<string name="progress_message_creating_map">创建新的 My Map...</string>
<string name="progress_message_sending_fusiontables">发送轨迹到 Fusion Tables...</string>
<string name="progress_message_creating_fusiontable">创建新的 Fusion table...</string>
<string name="import_progress_message">导入 GPS 轨迹中. 请稍候.</string>
<string name="write_progress_message">写入文件到 SD 卡中. 请稍候.</string>
<string name="progress_message_updating_track">更新轨迹统计信息中...</string>
@@ -79,12 +89,16 @@ limitations under the License.
<string name="track_will_be_permanently_deleted">选定轨迹和它相关的标记都将被从本机彻底删除.</string>
<string name="marker_will_be_permanently_deleted">选定标记将被从本机删除.</string>
<!-- Text and links when uploading to Google Fusion Tables -->
<string name="new_map_description">由 Android 平台的 My Tracks 创建.</string>
<string name="fusiontable_link">由 Android 平台的 &lt;a href=\'http://mytracks.appspot.com\'&gt;My Tracks&lt;/a&gt; 创建.</string>
<!-- Text and links when uploading to Google My Maps -->
<string name="new_map_description">由 Android 上的 My Tracks 生成.</string>
<string name="fusiontable_link">由 Android 上的 &lt;a href=\'http://mytracks.appspot.com\'&gt;My Tracks&lt;/a&gt; 生成.</string>
<string name="fusiontable_link">由 Android 上的 &lt;a href=\'http://mytracks.appspot.com\'&gt;My Tracks&lt;/a&gt; 创建.</string>
<string name="new_map_title">新地图</string>
<!-- Formatting of track and marker descriptions -->
<string name="points">点数</string>
<string name="points">路点</string>
<string name="recorded_date">记录日期</string>
<string name="category">活动类型</string>
<string name="waypoint_category">标记类型</string>
@@ -101,6 +115,7 @@ limitations under the License.
<string name="error">错误</string>
<string name="success">成功</string>
<string name="waypoint">路点</string>
<string name="license">授权</string>
<string name="cancel">取消</string>
<string name="close">关闭</string>
<string name="edit">编辑</string>
@@ -112,8 +127,10 @@ limitations under the License.
<!-- TrackList -->
<string name="tracklist_show_track">显示</string>
<string name="tracklist_send_to_mymaps">发送到 Google My Maps</string>
<string name="tracklist_send_to_new_mymap">发送到新建的 Google My Map</string>
<string name="tracklist_send_to_fusiontables">发送到 Google Fusion Table</string>
<string name="tracklist_send_to_new_fusiontable">发送到新建 Google Fusion Table</string>
<string name="tracklist_send_to_new_fusiontable">发送到新建的 Google Fusion Table</string>
<string name="tracklist_send_to_docs">发送到 Google Docs</string>
<string name="tracklist_send_to_google">发送到 Google...</string>
<string name="tracklist_delete_track">从手机上删除...</string>
@@ -124,6 +141,7 @@ limitations under the License.
<string name="tracklist_save_as_csv">保存为 CSV 文件</string>
<string name="tracklist_save_as_tcx">保存为 TCX 文件</string>
<string name="tracklist_btn_send_all_to_fusiontables">发送到 Google Fusion Tables</string>
<string name="tracklist_btn_send_all_to_mymaps">发送到 Google My Maps</string>
<string name="tracklist_btn_delete_all">删除所有轨迹</string>
<!-- Export All -->
<string name="tracklist_btn_export_all">导出所有轨迹</string>
@@ -132,11 +150,22 @@ limitations under the License.
<string name="tracklist_all_tracks">全部轨迹:</string>
<string name="tracklist_this_track">此轨迹</string>
<string name="tracklist_share_track">与朋友分享...</string>
<string name="tracklist_share_link">访问地图的超链接</string>
<string name="tracklist_share_gpx_file">GPX 文件</string>
<string name="tracklist_share_kml_file">KML 文件</string>
<string name="tracklist_share_csv_file">CSV 文件</string>
<string name="tracklist_share_tcx_file">TCX 文件</string>
<string name="tracklist_clear_map">清除地图</string>
<!-- Import All -->
<string name="tracklist_btn_import_all">全部导入</string>
<!-- Format:
$1 : Successful imports
$2 : Attempted imports
$3 : MyTracks gpx path
-->
<string name="import_done">已从 %3$s 导入 %1$d 个 GPX 文件, 共 %2$d 个.</string>
<string name="import_empty">在 %s 中未找到 GPX 文件. SD 存储卡不可用或者目录中没有 GPX 文件.</string>
<string name="import_error">导入文件 %s 出错.</string>
<!-- Waypoints list -->
<string name="waypointslist_btn_delete_all">删除所有标记</string>
@@ -166,10 +195,11 @@ limitations under the License.
<string name="settings_recording">记录</string>
<string name="settings_sharing">分享</string>
<string name="settings_not_available_summary">你使用的 Android 版本无法支持</string>
<string name="settings_not_available_summary">不支持当前使用的 Android 版本</string>
<string name="settings_not_while_recording">在记录轨迹时不可用</string>
<string name="settings_announcement_frequency">提示频度</string>
<string name="settings_announcement_frequency_summary">语音提示的最小时间间隔</string>
<string name="settings_announcement_frequency">通知频度</string>
<string name="settings_announcement_frequency_summary">语音通知的最小时间间隔</string>
<string name="settings_min_recording_distance">最小记录间距</string>
<string name="settings_min_recording_distance_summary">位置记录的最小间隔距离</string>
@@ -205,23 +235,37 @@ limitations under the License.
<string name="settings_auto_resume_track_timeout">自动恢复追踪等待时间</string>
<string name="settings_auto_resume_track_timeout_summary">手机重启后自动继续上次轨迹记录的最大间隔时间</string>
<string name="settings_timestamp_track_name">使用时间作为轨迹名称</string>
<string name="settings_timestamp_track_name_summary_on">使用轨迹记录的开始时间作为默认名称</string>
<string name="settings_timestamp_track_name_summary_off">轨迹使用自动递增的数字进行命名.</string>
<string name="settings_reset">恢复默认值</string>
<string name="settings_reset_summary">将所有设置恢复到默认值</string>
<string name="settings_reset_dialog_message">你的所有设置都将恢复到默认值. 已保存的轨迹不会丢失. 确定要继续吗?</string>
<string name="settings_reset_done">所有设置已恢复到默认值.</string>
<string name="pace_label">节奏</string>
<string name="eclair_required">只在 Android 2.0 及以上版本支持</string>
<string name="settings_sensor_type">感应器类型</string>
<string name="settings_sensor_type_summary">要连接到的感应器类型</string>
<string name="settings_heart_rate_ant_sensor_id">清除 ANT 心率计的设备关联</string>
<string name="settings_power_ant_sensor_id">清除 ANT 能量感应器的设备关联</string>
<string name="settings_srm_bridge_ant_sensor_id">清除 ANT SRM 桥接感应器的设备关联</string>
<string name="settings_ant_not_paired">ANT 感应器未关联</string>
<string name="settings_ant_paired">ANT 感应器已关联到: %d</string>
<string name="bluetooth_sensor_title">蓝牙感应器</string>
<string name="bluetooth_sensor_summary">要连接到的蓝牙感应器</string>
<string name="bluetooth_sensor_summary">想要连接的蓝牙感应器</string>
<string name="settings_modular_stats_display_title">模块化状态显示</string>
<!-- Backups -->
<string name="settings_backup">备份 (测试版)</string>
<string name="settings_sd_backup">SD 存储卡备份</string>
<string name="settings_backup_to_sd">立即备份</string>
<string name="settings_backup_to_sd_summary">将你所有轨迹和设置的完整备份写入到 SD 存储卡</string>
<string name="settings_restore_from_sd">立即恢复</string>
<string name="settings_restore_from_sd_summary">从 SD 存储卡恢复所有轨迹和设置</string>
<string name="settings_no_backup_while_recording">在记录轨迹时无法处理备份数据.</string>
<!-- Backups -->
<string name="restore_overwrites_warning">从 SD 存储卡恢复备份数据将覆盖掉你当前的所有轨迹和设置. 确定要继续吗?</string>
<string name="select_backup_to_restore">请选择要恢复的备份文件</string>
<string name="no_backups">没有找到备份文件.</string>
@@ -231,7 +275,25 @@ limitations under the License.
<!-- MyTracksSky -->
<string name="mytracks_sky">GPS 卫星</string>
<!-- My Maps -->
<string name="select_map_message">从你的帐号中选择一个地图:</string>
<string name="create_new_map">创建新地图...</string>
<string name="map_list_title">发送到 Google My Maps</string>
<string name="maps_list_loading">载入地图中...</string>
<string name="maps_list_failed">现在无法载入你的地图!</string>
<string name="open_map">选择此地图</string>
<string name="edit_map_details">编辑地图详细信息</string>
<string name="share_track">分享轨迹</string>
<string name="delete_map">从你的帐号删除地图</string>
<string name="map_title">地图标题:</string>
<string name="map_description">地图描述:</string>
<string name="map_searchable_edit">让此地图和它的内容出现在搜索结果中</string>
<string name="map_not_searchable_edit">不要让这个地图的的内容出现在搜索结果中, 但其它用户依然可以通过直接 URL 访问它</string>
<string name="map_searchable">此地图和它的内容将在搜索结果中出现</string>
<string name="map_not_searchable">此地图和它的内容不会在搜索结果中出现, 但其它用户依然可以通过直接 URL 访问它</string>
<!-- Sharing -->
<string name="share_map">与朋友分享地图</string>
<string name="share_map_subject">我想与你分享一张地图</string>
<string name="share_map_body_format">我想你可能会对这个地图感兴趣:
@@ -240,7 +302,6 @@ limitations under the License.
<string name="send_track_body_format">我想你可能会对这条轨迹感兴趣.
请用 Google Earth 或其它地图软件查看此轨迹.</string>
<string name="share_track">与朋友分享轨迹</string>
<!-- Visibility -->
<string name="public_map">公开</string>
@@ -332,10 +393,13 @@ limitations under the License.
<string name="about_team">开发团队:</string>
<string name="about_version">版本:</string>
<string name="about_support">技术支持:</string>
<string name="about_privacy">隐私策略:</string>
<!-- Send to Google -->
<string name="sendtogoogle_title">发送到...</string>
<string name="sendtogoogle_send_now">立即发送</string>
<string name="sendtogoogle_create_new_map">创建新地图</string>
<string name="sendtogoogle_pick_existing_map">选择已有地图</string>
<string name="sendtogoogle_send_stats">发送轨迹统计信息</string>
<string name="sendtogoogle_send_stats_and_points">发送统计信息和路点</string>
@@ -345,10 +409,11 @@ limitations under the License.
<string name="choose_account_title">选择帐户</string>
<!-- SD card -->
<string name="io_no_external_storage_found">没有发现存贮设备. 请确认插入了 SD 卡并且你的手机没有将挂载 SD 卡到电脑.</string>
<string name="io_no_external_storage_found">没有发现存储设备. 请确认插入了 SD 存储卡并且你的手机没有将挂载 SD 卡到电脑.</string>
<string name="io_write_failed">无法写入文件.</string>
<string name="io_create_dir_failed">无法在 SD 存储卡上创建目录.</string>
<string name="io_write_finished">轨迹已导出到 SD 卡.</string>
<string name="io_create_dir_failed">无法在 SD 存储卡上创建目录card.</string>
<string name="io_write_finished">轨迹已导出到 SD 存储卡.</string>
<string name="io_read_finished">从 SD 存储卡读取完毕.</string>
<!-- VersionChecker -->
@@ -396,4 +461,20 @@ limitations under the License.
<string name="sensor_data_time">感应器数据时间</string>
<string name="power_meter_enabled">电源计量器已启用</string>
<string name="heart_rate_monitor_enabled">心率监视器已启用</string>
<string name="no_sensor_manager">没有感应器管理器</string>
<string name="enabled">已启用</string>
<string name="connecting">连接中</string>
<string name="connected">已连接</string>
<string name="disconnected">未连接</string>
<string name="no_sensor_service">没有感应器服务</string>
<string name="searching">搜索中</string>
<string name="sending">发送中</string>
<!-- Sensor Type Options -->
<string name="no_sensor_option">无</string>
<string name="ant_sensor_option">ANT+ 感应器</string>
<string name="ant_bridge_sensor_option">SRM ANT+ 转接器</string>
<string name="polar_bt_sensor_option">Polar Bluetooth</string>
<string name="zephyr_bt_sensor_option">Zephyr 蓝牙设备</string>
</resources>
+10 -145
View File
@@ -15,31 +15,6 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Task frequency -->
<string-array name="task_frequency_options">
<item>Off</item>
<item>1 min</item>
<item>2 min</item>
<item>5 min</item>
<item>10 min</item>
<item>15 min</item>
<item>30 min</item>
<item>60 min</item>
</string-array>
<!-- DO NOT TRANSLATE -->
<string-array name="task_frequency_values">
<item>-1</item>
<item>1</item>
<item>2</item>
<item>5</item>
<item>10</item>
<item>15</item>
<item>30</item>
<item>60</item>
</string-array>
<!-- Minimum recording distance -->
<string-array name="min_recording_distance_options">
<item>1 m</item>
@@ -61,18 +36,6 @@ limitations under the License.
<item>328 ft</item>
</string-array>
<!-- DO NOT TRANSLATE -->
<string-array name="min_recording_distance_values">
<item>1</item>
<item>2</item>
<item>3</item>
<item>4</item>
<item>5</item>
<item>10</item>
<item>100</item>
</string-array>
<!-- Maximum recording distance -->
<string-array name="max_recording_distance_options">
<item>50 m</item>
@@ -92,17 +55,6 @@ limitations under the License.
<item>3.1 miles</item>
</string-array>
<!-- DO NOT TRANSLATE -->
<string-array name="max_recording_distance_values">
<item>50</item>
<item>100</item>
<item>200</item>
<item>500</item>
<item>1000</item>
<item>5000</item>
</string-array>
<!-- Minimum recording interval -->
<string-array name="min_recording_interval_options">
<item>battery miser (adaptive)</item>
@@ -123,27 +75,6 @@ limitations under the License.
<item>30 min</item>
</string-array>
<!-- DO NOT TRANSLATE -->
<string-array name="min_recording_interval_values">
<item>-2</item>
<item>-1</item>
<item>0</item>
<item>2</item>
<item>3</item>
<item>4</item>
<item>5</item>
<item>10</item>
<item>20</item>
<item>30</item>
<item>60</item>
<item>120</item>
<item>300</item>
<item>480</item>
<item>900</item>
<item>1800</item>
</string-array>
<!-- Minimum required accuracy -->
<string-array name="min_required_accuracy_options">
<item>10 m (excellent GPS signal)</item>
@@ -169,23 +100,9 @@ limitations under the License.
<item>3.1 miles (poor GPS signal)</item>
</string-array>
<!-- DO NOT TRANSLATE -->
<string-array name="min_required_accuracy_values">
<item>10</item>
<item>20</item>
<item>50</item>
<item>100</item>
<item>200</item>
<item>500</item>
<item>1000</item>
<item>2000</item>
<item>5000</item>
</string-array>
<!-- Split frequency -->
<string-array name="split_frequency_options">
<item>No splitting</item>
<!-- Task frequency -->
<string-array name="task_frequency_options">
<item>Off</item>
<item>100 km</item>
<item>50 km</item>
<item>25 km</item>
@@ -201,8 +118,8 @@ limitations under the License.
<item>1 min</item>
</string-array>
<string-array name="split_frequency_options_ft">
<item>No splitting</item>
<string-array name="task_frequency_options_ft">
<item>Off</item>
<item>100 mi</item>
<item>50 mi</item>
<item>25 mi</item>
@@ -218,24 +135,6 @@ limitations under the License.
<item>1 min</item>
</string-array>
<!-- DO NOT TRANSLATE -->
<string-array name="split_frequency_values">
<item>0</item>
<item>-100</item>
<item>-50</item>
<item>-25</item>
<item>-10</item>
<item>-5</item>
<item>-1</item>
<item>60</item>
<item>30</item>
<item>15</item>
<item>10</item>
<item>5</item>
<item>2</item>
<item>1</item>
</string-array>
<!-- Auto-resume track timeout -->
<string-array name="auto_resume_track_timeout_options">
<item>Never</item>
@@ -245,16 +144,6 @@ limitations under the License.
<item>Always</item>
</string-array>
<!-- DO NOT TRANSLATE -->
<string-array name="auto_resume_track_timeout_values">
<item>0</item>
<item>5</item>
<item>10</item>
<item>15</item>
<item>-1</item>
</string-array>
<!-- Other non-preference arrays -->
<array name="activity_types">
<item>unknown</item>
@@ -281,6 +170,11 @@ limitations under the License.
<item>inline skating</item>
<item>skate boarding</item>
<item>roller skiing (classic)</item>
<item>roller skiing (skate)</item>
<item>cross-country skiing (classic)</item>
<item>cross-country skiing (skate)</item>
<item>snow shoeing</item>
<item>skiing</item>
<item>snow boarding</item>
@@ -383,33 +277,4 @@ limitations under the License.
<item>way point</item>
</array>
<!-- DO NOT TRANSLATE -->
<array name="export_formats">
<item>GPX</item>
<item>KML</item>
<item>CSV</item>
<item>TCX</item>
</array>
<array name="sensor_type_options">
<item>None</item>
<item>ANT+ Sensors</item>
<item>SRM ANT+ Bridge</item>
<item>Zephyr Bluetooth</item>
</array>
<!-- DO NOT TRANSLATE -->
<array name="sensor_type_values">
<item>@string/none</item>
<item>@string/ant_sensor_type</item>
<item>@string/srm_ant_bridge_sensor_type</item>
<item>@string/zephyr_sensor_type</item>
</array>
<!-- DO NOT TRANSLATE -->
<string-array name="ant_sensor_type_values">
<item>@string/ant_sensor_type</item>
<item>@string/srm_ant_bridge_sensor_type</item>
</string-array>
</resources>
@@ -0,0 +1,121 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2010 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Do not translate any arrays in this file. -->
<string-array name="min_required_accuracy_values">
<item>10</item>
<item>20</item>
<item>50</item>
<item>100</item>
<item>200</item>
<item>500</item>
<item>1000</item>
<item>2000</item>
<item>5000</item>
</string-array>
<string-array name="min_recording_distance_values">
<item>1</item>
<item>2</item>
<item>3</item>
<item>4</item>
<item>5</item>
<item>10</item>
<item>100</item>
</string-array>
<string-array name="max_recording_distance_values">
<item>50</item>
<item>100</item>
<item>200</item>
<item>500</item>
<item>1000</item>
<item>5000</item>
</string-array>
<string-array name="min_recording_interval_values">
<item>-2</item>
<item>-1</item>
<item>0</item>
<item>2</item>
<item>3</item>
<item>4</item>
<item>5</item>
<item>10</item>
<item>20</item>
<item>30</item>
<item>60</item>
<item>120</item>
<item>300</item>
<item>480</item>
<item>900</item>
<item>1800</item>
</string-array>
<string-array name="task_frequency_values">
<item>0</item>
<item>-100</item>
<item>-50</item>
<item>-25</item>
<item>-10</item>
<item>-5</item>
<item>-1</item>
<item>60</item>
<item>30</item>
<item>15</item>
<item>10</item>
<item>5</item>
<item>2</item>
<item>1</item>
</string-array>
<string-array name="auto_resume_track_timeout_values">
<item>0</item>
<item>5</item>
<item>10</item>
<item>15</item>
<item>-1</item>
</string-array>
<array name="export_formats">
<item>GPX</item>
<item>KML</item>
<item>CSV</item>
<item>TCX</item>
</array>
<array name="sensor_type_options">
<item>@string/no_sensor_option</item>
<item>@string/ant_sensor_option</item>
<item>@string/ant_bridge_sensor_option</item>
<item>@string/polar_bt_sensor_option</item>
<item>@string/zephyr_bt_sensor_option</item>
</array>
<array name="sensor_type_values">
<item>@string/none</item>
<item>@string/ant_sensor_type</item>
<item>@string/srm_ant_bridge_sensor_type</item>
<item>@string/polar_sensor_type</item>
<item>@string/zephyr_sensor_type</item>
</array>
<string-array name="ant_sensor_type_values">
<item>@string/ant_sensor_type</item>
<item>@string/srm_ant_bridge_sensor_type</item>
</string-array>
</resources>
+4
View File
@@ -47,4 +47,8 @@ limitations under the License.
<!-- Purple and a transparent purple -->
<color name="power_border">#FF401465</color>
<color name="power_fill">#40401465</color>
<!-- AppWidget colors -->
<color name="appwidget_text">#EDEDED</color>
<color name="appwidget_hr">#99999999</color>
</resources>
+13 -1
View File
@@ -23,7 +23,7 @@ limitations under the License.
<string name="about_weburl">mytracks.appspot.com</string>
<string name="about_privacy_weburl">m.google.com/privacy</string>
<string name="about_copyright_message">Copyright 2009 Google Inc.</string>
<string name="about_bart">Bartlomiej Niechwiej</string>
<string name="about_bart">Bartłomiej Niechwiej</string>
<string name="about_dylan">Dylan Casey</string>
<string name="about_leif">Leif Hendrik Wilden</string>
<string name="about_rdamazio">Rodrigo Damazio Bovendorp</string>
@@ -33,5 +33,17 @@ limitations under the License.
<string name="none">NONE</string>
<string name="ant_sensor_type">ANT</string>
<string name="srm_ant_bridge_sensor_type">SRM_ANT_BRIDGE</string>
<string name="polar_sensor_type">POLAR</string>
<string name="zephyr_sensor_type">ZEPHYR</string>
<!-- Send to Google URLs -->
<string name="sendtogoogle_google_fusiontables_url">google.com/fusiontables</string>
<string name="sendtogoogle_google_mymaps_url">maps.google.com</string>
<string name="sendtogoogle_google_docs_url">docs.google.com</string>
<!-- ID for Google Analytics -->
<string name="google_analytics_id">UA-7222692-2</string>
<!-- Intent actions -->
<string name="save_intent_action">android.intent.action.SAVE</string>
</resources>
+1 -2
View File
@@ -50,8 +50,7 @@ limitations under the License.
<!-- Keys for non-persisted preferences - DO NOT TRANSLATE -->
<string name="backup_to_sd_key">backupToSd</string>
<string name="restore_from_sd_key">restoreFromSd</string>
<!-- Inoperative keys used for the location of preferences items -->
<string name="reset_key">resetToDefaults</string>
<string name="sensor_options_key">sensorOptions</string>
<string name="ant_options_key">antOptions</string>
</resources>
+27 -10
View File
@@ -35,15 +35,17 @@ limitations under the License.
<!-- Error messages -->
<string name="error_no_location_manager">No location manager was found on this device!</string>
<string name="error_no_gps_location_provider">No GPS location provider was found on this device.</string>
<string name="error_sending_to_mymap">There was an error while sending your track to Google My Map. Please try again later.</string>
<string name="error_sending_to_fusiontables">There was an error while sending your track to Google Fusion Tables. Please try again later.</string>
<string name="error_sending_to_docs">There was an error while sending your track to Google Docs. Please try again later.</string>
<string name="error_sending_to_mymap">There was an error while sending your track to Google My Map.</string>
<string name="error_sending_to_fusiontables">There was an error while sending your track to Google Fusion Tables.</string>
<string name="error_sending_to_docs">There was an error while sending your track to Google Docs.</string>
<string name="error_please_try_again_later">Please try again later.</string>
<string name="error_unable_to_start_recording">Unable to start recording. Try again.</string>
<string name="error_unable_to_stop_recording">Unable to stop recording. Try again.</string>
<string name="error_unable_to_read_file">Unable to read from file.</string>
<string name="error_invalid_gpx_format">File does not have a valid GPX format.</string>
<string name="error_generic">An error occurred. Please try again.</string>
<string name="error_track_does_not_exist">Track does not exist.</string>
<string name="error_operation_cancelled">The operation was cancelled.</string>
<string name="error_out_of_memory">This file is too big (must be less than 500 KB). Aborting.</string>
<string name="error_unable_to_insert_marker">Unable to insert marker. No location fix available.</string>
@@ -56,12 +58,13 @@ limitations under the License.
<string name="status_tracks_have_been_uploaded">Your track has been sent to maps.google.com.</string>
<string name="status_tracks_have_been_uploaded_to_new_doc">Your track has been sent to a new spreadsheet at docs.google.com.</string>
<string name="status_tracks_have_been_uploaded_to_docs">Your track has been sent to docs.google.com.</string>
<string name="status_mymap_info">It may sometimes take a few minutes before new tracks appear.</string>
<string name="status_mymap_info">It may take a few minutes before new tracks appear.</string>
<string name="status_enable_gps">Please tap here to go to Security and Location Settings and check \'enable GPS satellites\'. Press back button to return.</string>
<string name="status_approximate_location">Note: An approximate location as determined from cell towers and WIFI networks is shown.</string>
<string name="status_no_location">A location can currently not be determined. Enable more location sources (see Security and Location Settings) and make sure the sky is visible. Try again later.</string>
<string name="status_waypoint_inserted">A way point marker was inserted.</string>
<string name="status_statistics_inserted">A statistics marker was inserted.</string>
<string name="status_track_upload_status">Upload status:</string>
<!-- Progress dialog -->
<string name="progress_title">Please wait...</string>
@@ -155,15 +158,17 @@ limitations under the License.
<string name="tracklist_clear_map">Clear map</string>
<!-- Import All -->
<string name="tracklist_btn_import_all">Import all</string>
<string name="import_done">Import finished, imported</string>
<!-- Format:
$1 : Successful imports
$2 : Attempted imports
$3 : MyTracks gpx path
-->
<string name="import_done">Imported %1$d of %2$d GPX files from %3$s</string>
<string name="import_empty">No GPX files found in %s. SD card may be unreadable or directory may not contain GPX files.</string>
<string name="import_multi_done">Imported %1$d of %2$d GPX files from %3$s</string>
<string name="import_multi_empty">No GPX files found in %s. SD card may be unreadable or directory may not contain GPX files.</string>
<string name="import_error">Import error for file %s</string>
<string name="import_title">Import into My Tracks</string>
<string name="import_success">Successfully imported %1$d track(s) from file.</string>
<string name="import_show_track">Show track</string>
<!-- Waypoints list -->
<string name="waypointslist_btn_delete_all">Delete all markers</string>
@@ -194,6 +199,7 @@ limitations under the License.
<string name="settings_sharing">Sharing</string>
<string name="settings_not_available_summary">Not available in your version of Android</string>
<string name="settings_not_while_recording">Not available while recording a track</string>
<string name="settings_announcement_frequency">Announcement frequency</string>
<string name="settings_announcement_frequency_summary">Minimum time between two voice announcements</string>
@@ -236,6 +242,11 @@ limitations under the License.
<string name="settings_timestamp_track_name_summary_on">The default track name will be the date and time at the start of the track</string>
<string name="settings_timestamp_track_name_summary_off">Track names will have numbers which increment for each new track.</string>
<string name="settings_reset">Reset to defaults</string>
<string name="settings_reset_summary">Revert all your settings to the default values</string>
<string name="settings_reset_dialog_message">All your settings will be erased and reverted to the default values. Saved tracks will be preserved. Are you sure?</string>
<string name="settings_reset_done">All settings have been reverted to their defaults.</string>
<string name="pace_label">Pace</string>
<string name="eclair_required">Only supported in Android 2.0 or above</string>
@@ -257,7 +268,6 @@ limitations under the License.
<string name="settings_backup_to_sd_summary">Write a full copy of all your tracks and settings to the SD card</string>
<string name="settings_restore_from_sd">Restore now</string>
<string name="settings_restore_from_sd_summary">Restore all tracks and settings from the SD card</string>
<string name="settings_no_backup_while_recording">Cannot manipulate backups while recording a track.</string>
<string name="restore_overwrites_warning">Restoring a backup from the SD card will OVERWRITE all your current tracks and settings. Are you sure?</string>
<string name="select_backup_to_restore">Select the backup to restore</string>
@@ -276,7 +286,7 @@ limitations under the License.
<string name="maps_list_failed">Your maps could not be loaded at this time!</string>
<string name="open_map">Select this Map</string>
<string name="edit_map_details">Edit Map Details</string>
<string name="share_track">Share Track with Friends</string>
<string name="share_track">Share Track</string>
<string name="delete_map">Delete Map from your Account</string>
<string name="map_title">Map Title:</string>
<string name="map_description">Map Description:</string>
@@ -295,7 +305,6 @@ limitations under the License.
<string name="send_track_body_format">I think you might be interested in this track.
To view this track use Google Earth or other mapping software.</string>
<string name="share_track">Share track with friends</string>
<!-- Visibility -->
<string name="public_map">Public</string>
@@ -492,4 +501,12 @@ limitations under the License.
<string name="notification_permission_description">Be notified when a track starts or stops being recorded.</string>
<string name="read_tracks_permission_description">Be able to read track data, such as points and waypoints.</string>
<string name="write_tracks_permission_description">Be able to write track data, such as starting recording or adding waypoints.</string>
<!-- Sensor Type Options -->
<string name="no_sensor_option">NONE</string>
<string name="ant_sensor_option">ANT+ Sensors</string>
<string name="ant_bridge_sensor_option">SRM ANT+ Bridge</string>
<string name="polar_bt_sensor_option">Polar Bluetooth</string>
<string name="zephyr_bt_sensor_option">Zephyr Bluetooth</string>
</resources>
+11
View File
@@ -74,4 +74,15 @@ limitations under the License.
<item name="android:layout_height">3dip</item>
<item name="android:layout_width">fill_parent</item>
</style>
<!-- The style for the track widget. -->
<style name="WidgetText" parent="@android:Widget.TextView">
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:textColor">@color/appwidget_text</item>
<item name="android:textSize">14sp</item>
</style>
<style name="WidgetText.Register">
<item name="android:width">160px</item>
</style>
</resources>
+10 -3
View File
@@ -42,14 +42,14 @@ limitations under the License.
android:summary="@string/settings_announcement_frequency_summary"
android:entries="@array/task_frequency_options"
android:entryValues="@array/task_frequency_values"
android:defaultValue="-1" />
android:defaultValue="0" />
<com.google.android.apps.mytracks.IntegerListPreference
android:key="@string/split_frequency_key"
android:title="@string/settings_split_frequency"
android:summary="@string/settings_split_frequency_summary"
android:entries="@array/split_frequency_options"
android:entryValues="@array/split_frequency_values"
android:entries="@array/task_frequency_options"
android:entryValues="@array/task_frequency_values"
android:defaultValue="0" />
<com.google.android.apps.mytracks.IntegerListPreference
@@ -173,4 +173,11 @@ limitations under the License.
android:persistent="false" />
</PreferenceCategory>
</PreferenceScreen>
<!-- Reset to defaults -->
<Preference
android:title="@string/settings_reset"
android:key="@string/reset_key"
android:summary="@string/settings_reset_summary"
android:persistent="false" />
</PreferenceScreen>
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<appwidget-provider
xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/track_widget"
android:minHeight="72dp"
android:minWidth="294dp"
android:updatePeriodMillis="0" />
+8 -10
View File
@@ -15,22 +15,20 @@
*/
package com.dsi.ant;
import java.util.Arrays;
import com.dsi.ant.exception.AntInterfaceException;
import com.dsi.ant.exception.AntRemoteException;
import com.dsi.ant.exception.AntServiceNotConnectedException;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import com.dsi.ant.exception.*;
import java.util.Arrays;
/**
* Public API for controlling the Ant Service. AntInterface is a proxy
@@ -63,10 +61,10 @@ public class AntInterface {
private static Object INSTANCE_LOCK = new Object();
/** The context to use. */
private static Context sContext = null;
private Context sContext = null;
/** Listens to changes to service connection status. */
private static ServiceListener sServiceListener;
private ServiceListener sServiceListener;
/** Is the ANT Radio Proxy Service connected. */
private static boolean sServiceConnected = false;
@@ -212,7 +210,7 @@ public class AntInterface {
/**
* Class for interacting with the ANT interface.
*/
private static ServiceConnection sIAntConnection = new ServiceConnection() {
private final ServiceConnection sIAntConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName pClassName, IBinder pService) {
// This is called when the connection with the service has been
// established, giving us the service object we can use to
@@ -1225,7 +1223,7 @@ public class AntInterface {
*/
public boolean requestForceClaimInterface(String appName) throws AntInterfaceException
{
if((null == appName) || ("" == appName))
if((null == appName) || ("".equals(appName)))
{
throw new IllegalArgumentException();
}
@@ -1,12 +1,12 @@
/*
* Copyright 2010 Google Inc.
*
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -15,10 +15,10 @@
*/
package com.google.android.apps.mytracks;
import com.google.android.accounts.Account;
import com.google.android.accounts.AccountManager;
import com.google.android.maps.mytracks.R;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
@@ -29,7 +29,7 @@ import android.util.Log;
* @author Sandor Dornbush
*/
public class AccountChooser {
/**
* The last selected account.
*/
@@ -44,7 +44,7 @@ public class AccountChooser {
* Handle the account being selected.
* @param account The selected account or null if none could be found
*/
public void handleAccountSelected(Account account);
public void onAccountSelected(Account account);
}
/**
@@ -52,45 +52,51 @@ public class AccountChooser {
* If no account is found the user will be alerted.
* If only one account is found that will be used.
* If multiple accounts are found the user will be allowed to choose.
*
*
* @param activity The parent activity
* @param handler The handler to be notified when an account has been selected
*/
public void chooseAccount(final Activity activity,
final AccountHandler handler) {
final Account[] accounts = AccountManager.get(activity)
.getAccountsByType(MyTracksConstants.ACCOUNT_TYPE);
.getAccountsByType(Constants.ACCOUNT_TYPE);
if (accounts.length < 1) {
alertNoAccounts(activity, handler);
return;
}
if (accounts.length == 1) {
handler.handleAccountSelected(accounts[0]);
handler.onAccountSelected(accounts[0]);
return;
}
// TODO This should be read out of a preference.
if (selectedAccount != null) {
handler.handleAccountSelected(selectedAccount);
handler.onAccountSelected(selectedAccount);
return;
}
// Let the user choose.
Log.e(MyTracksConstants.TAG, "Multiple matching accounts found.");
Log.e(Constants.TAG, "Multiple matching accounts found.");
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(R.string.choose_account_title);
builder.setCancelable(false);
builder.setPositiveButton(R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
selectedAccount = accounts[selectedAccountIndex];
handler.handleAccountSelected(selectedAccount);
dialog.dismiss();
if (selectedAccountIndex >= 0) {
selectedAccount = accounts[selectedAccountIndex];
}
handler.onAccountSelected(selectedAccount);
}
});
builder.setNegativeButton(R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
handler.handleAccountSelected(null);
dialog.dismiss();
handler.onAccountSelected(null);
}
});
String[] choices = new String[accounts.length];
@@ -107,12 +113,16 @@ public class AccountChooser {
builder.show();
}
public void setChosenAccount(String accountName, String accountType) {
selectedAccount = new Account(accountName, accountType);
}
/**
* Puts up a dialog alerting the user that no suitable account was found.
*/
private void alertNoAccounts(final Activity activity,
final AccountHandler handler) {
Log.e(MyTracksConstants.TAG, "No matching accounts found.");
Log.e(Constants.TAG, "No matching accounts found.");
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(R.string.no_account_found_title);
builder.setMessage(R.string.no_account_found);
@@ -120,7 +130,8 @@ public class AccountChooser {
builder.setNegativeButton(R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
handler.handleAccountSelected(null);
dialog.dismiss();
handler.onAccountSelected(null);
}
});
builder.show();
@@ -19,9 +19,9 @@ import java.util.List;
/**
* Activity for viewing the combined statistics for all the recorded tracks.
*
*
* Other features to add - menu items to change setings.
*
*
* @author Fergus Nelson
*/
public class AggregatedStatsActivity extends Activity implements
@@ -40,10 +40,10 @@ public class AggregatedStatsActivity extends Activity implements
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
Log.d(MyTracksConstants.TAG, "StatsActivity: onSharedPreferences changed "
Log.d(Constants.TAG, "StatsActivity: onSharedPreferences changed "
+ key);
if (key != null) {
if (key.equals(R.string.metric_units_key)) {
if (key.equals(getString(R.string.metric_units_key))) {
metricUnits = sharedPreferences.getBoolean(
getString(R.string.metric_units_key), true);
utils.setMetricUnits(metricUnits);
@@ -67,7 +67,7 @@ public class AggregatedStatsActivity extends Activity implements
sv.setScrollBarStyle(ScrollView.SCROLLBARS_OUTSIDE_INSET);
SharedPreferences preferences = getSharedPreferences(
MyTracksSettings.SETTINGS_NAME, 0);
Constants.SETTINGS_NAME, 0);
if (preferences != null) {
metricUnits = preferences.getBoolean(getString(R.string.metric_units_key), true);
preferences.registerOnSharedPreferenceChangeListener(this);
@@ -86,8 +86,8 @@ public class AggregatedStatsActivity extends Activity implements
}
/**
* 1. Reads tracks from the db
* 2. Merges the trip stats from the tracks
* 1. Reads tracks from the db
* 2. Merges the trip stats from the tracks
* 3. Updates the view
*/
private void loadAggregatedStats() {
@@ -16,8 +16,8 @@
package com.google.android.apps.mytracks;
import static android.content.Intent.ACTION_BOOT_COMPLETED;
import static com.google.android.apps.mytracks.MyTracksConstants.RESUME_TRACK_EXTRA_NAME;
import static com.google.android.apps.mytracks.MyTracksConstants.TAG;
import static com.google.android.apps.mytracks.Constants.RESUME_TRACK_EXTRA_NAME;
import static com.google.android.apps.mytracks.Constants.TAG;
import com.google.android.apps.mytracks.services.TrackRecordingService;
@@ -41,17 +41,17 @@ import android.util.Log;
*
* @author Bartlomiej Niechwiej
*/
public class MyTracksReceiver extends BroadcastReceiver {
public class BootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "MyTracksReceiver.onReceive: " + intent.getAction());
Log.d(TAG, "BootReceiver.onReceive: " + intent.getAction());
if (ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
Intent startIntent = new Intent(context, TrackRecordingService.class);
startIntent.putExtra(RESUME_TRACK_EXTRA_NAME, true);
context.startService(startIntent);
} else {
Log.w(TAG, "MyTracksReceiver: unsupported action");
Log.w(TAG, "BootReceiver: unsupported action");
}
}
}
@@ -15,31 +15,31 @@
*/
package com.google.android.apps.mytracks;
import static com.google.android.apps.mytracks.Constants.TAG;
import com.google.android.apps.mytracks.ChartView.Mode;
import com.google.android.apps.mytracks.content.MyTracksLocation;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.TrackPointsColumns;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.content.WaypointsColumns;
import com.google.android.apps.mytracks.content.TrackDataHub;
import com.google.android.apps.mytracks.content.TrackDataListener;
import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
import com.google.android.apps.mytracks.services.StatusAnnouncerFactory;
import com.google.android.apps.mytracks.content.TrackDataHub.ListenerDataType;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.services.tasks.StatusAnnouncerFactory;
import com.google.android.apps.mytracks.stats.DoubleBuffer;
import com.google.android.apps.mytracks.stats.TripStatisticsBuilder;
import com.google.android.apps.mytracks.util.ApiFeatures;
import com.google.android.apps.mytracks.util.MyTracksUtils;
import com.google.android.apps.mytracks.util.LocationUtils;
import com.google.android.apps.mytracks.util.UnitConversions;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.content.SharedPreferences;
import android.database.ContentObserver;
import android.database.Cursor;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.location.Location;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
@@ -51,53 +51,34 @@ import android.widget.LinearLayout;
import android.widget.ZoomControls;
import java.util.ArrayList;
import java.util.EnumSet;
/**
* An activity that displays a chart from the track point provider.
*
* @author Sandor Dornbush
* @author Rodrigo Damazio
*/
public class ChartActivity extends Activity implements
SharedPreferences.OnSharedPreferenceChangeListener {
private final static int BUFFER_SIZE = 1024;
private double profileLength = 0;
private boolean metricUnits = true;
private boolean reportSpeed = true;
/**
* The track id that is displayed.
*/
private long selectedTrackId = -1;
/**
* Id of the last location that was seen when reading tracks from the
* provider. This is used to determine which locations are new compared to the
* last time the chart was updated.
*/
private long lastSeenLocationId = -1;
private long startTime = -1;
private Location lastLocation;
/**
* The id of the track currently being recorded.
*/
private long recordingTrackId = -1;
public class ChartActivity extends Activity implements TrackDataListener {
private static final int CHART_SETTINGS_DIALOG = 1;
private final DoubleBuffer elevationBuffer =
new DoubleBuffer(MyTracksConstants.ELEVATION_SMOOTHING_FACTOR);
new DoubleBuffer(Constants.ELEVATION_SMOOTHING_FACTOR);
private final DoubleBuffer speedBuffer =
new DoubleBuffer(MyTracksConstants.SPEED_SMOOTHING_FACTOR);
new DoubleBuffer(Constants.SPEED_SMOOTHING_FACTOR);
private final ArrayList<double[]> pendingPoints = new ArrayList<double[]>();
private Mode mode = Mode.BY_DISTANCE;
private TrackDataHub dataHub;
/**
* Utilities to deal with the database.
*/
private MyTracksProviderUtils providerUtils;
// Stats gathered from received data.
private double profileLength = 0;
private long startTime = -1;
private Location lastLocation;
private double trackMaxSpeed;
// Modes of operation
private boolean metricUnits;
private boolean reportSpeed;
/*
* UI elements:
@@ -107,9 +88,6 @@ public class ChartActivity extends Activity implements
private LinearLayout busyPane;
private ZoomControls zoomControls;
/** Handler for callbacks to the UI thread */
private final Handler uiHandler = new Handler();
/**
* A runnable that can be posted to the UI thread. It will remove the spinner
* (if any), enable/disable zoom controls and orange pointer as appropriate
@@ -118,92 +96,24 @@ public class ChartActivity extends Activity implements
private final Runnable updateChart = new Runnable() {
@Override
public void run() {
// Get a local reference in case it's set to null concurrently with this.
TrackDataHub localDataHub = dataHub;
if (localDataHub == null || isFinishing()) {
return;
}
busyPane.setVisibility(View.GONE);
zoomControls.setIsZoomInEnabled(chartView.canZoomIn());
zoomControls.setIsZoomOutEnabled(chartView.canZoomOut());
chartView.setShowPointer(selectedTrackIsRecording());
chartView.setShowPointer(localDataHub.isRecordingSelected());
chartView.invalidate();
}
};
/**
* A runnable that can be posted to the UI thread. It will show the spinner.
*/
private final Runnable showSpinner = new Runnable() {
@Override
public void run() {
busyPane.setVisibility(View.VISIBLE);
}
};
/**
* An observer for the tracks provider. Will listen to new track points being
* added and update the chart if necessary.
*/
private ContentObserver observer;
/**
* An observer for the waypoints provider. Will listen to new way points being
* added and update the chart if necessary.
*/
private ContentObserver waypointObserver;
/**
* A thread with a looper. Post to updateTrackHandler to execute Runnables on
* this thread.
*/
private final HandlerThread updateTrackThread =
new HandlerThread("updateTrackThread");
/** Handler for updateTrackThread */
private Handler updateTrackHandler;
/**
* A runnable that updates the profile from the provider.
*/
private final Runnable updateTrackRunnable = new Runnable() {
@Override
public void run() {
readNewTrackPoints();
}
};
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
if (key != null) {
if (key.equals(getString(R.string.selected_track_key))) {
selectedTrackId =
sharedPreferences.getLong(getString(R.string.selected_track_key),
-1);
readProfileAsync();
} else if (key.equals(getString(R.string.metric_units_key))) {
metricUnits =
sharedPreferences.getBoolean(getString(R.string.metric_units_key),
true);
chartView.setMetricUnits(metricUnits);
readProfileAsync();
} else if (key.equals(getString(R.string.report_speed_key))) {
reportSpeed =
sharedPreferences.getBoolean(getString(R.string.report_speed_key),
true);
chartView.setReportSpeed(reportSpeed, this);
readProfileAsync();
} else if (key.equals(getString(R.string.recording_track_key))) {
recordingTrackId =
sharedPreferences.getLong(getString(R.string.recording_track_key),
-1);
runOnUiThread(updateChart);
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.w(MyTracksConstants.TAG, "ChartActivity.onCreate");
Log.w(TAG, "ChartActivity.onCreate");
super.onCreate(savedInstanceState);
MyTracks.getInstance().setChartActivity(this);
providerUtils = MyTracksProviderUtils.Factory.get(this);
// The volume we want to control is the Text-To-Speech volume
int volumeStream =
@@ -214,27 +124,10 @@ public class ChartActivity extends Activity implements
setContentView(R.layout.mytracks_charts);
ViewGroup layout = (ViewGroup) findViewById(R.id.elevation_chart);
chartView = new ChartView(this);
chartView.setMode(this.mode);
LayoutParams params =
new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
layout.addView(chartView, params);
SharedPreferences preferences =
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
if (preferences != null) {
selectedTrackId =
preferences.getLong(getString(R.string.selected_track_key), -1);
recordingTrackId =
preferences.getLong(getString(R.string.recording_track_key), -1);
metricUnits = preferences.getBoolean(getString(R.string.metric_units_key),
true);
chartView.setMetricUnits(metricUnits);
reportSpeed = preferences.getBoolean(getString(R.string.report_speed_key),
true);
chartView.setReportSpeed(reportSpeed, this);
preferences.registerOnSharedPreferenceChangeListener(this);
}
busyPane = (LinearLayout) findViewById(R.id.elevation_busypane);
zoomControls = (ZoomControls) findViewById(R.id.elevation_zoom);
zoomControls.setOnZoomInClickListener(new View.OnClickListener() {
@@ -249,97 +142,28 @@ public class ChartActivity extends Activity implements
zoomOut();
}
});
updateTrackThread.start();
updateTrackHandler = new Handler(updateTrackThread.getLooper());
// Register observer for the track point provider:
Handler contentHandler = new Handler();
observer = new ContentObserver(contentHandler) {
@Override
public void onChange(boolean selfChange) {
Log.d(MyTracksConstants.TAG, "ChartActivity: ContentObserver.onChange");
// Check for any new locations and append them to the currently
// recording track.
if (recordingTrackId < 0) {
// No track is being recorded. We should not be here.
return;
}
if (selectedTrackId != recordingTrackId) {
// No track, or one other than the recording track is selected, don't
// bother.
return;
}
// Update can potentially be lengthy, put it in its own thread:
updateTrackHandler.post(updateTrackRunnable);
super.onChange(selfChange);
}
};
waypointObserver = new ContentObserver(contentHandler) {
@Override
public void onChange(boolean selfChange) {
Log.d(MyTracksConstants.TAG,
"MyTracksMap: ContentObserver.onChange waypoints");
if (selectedTrackId < 0) {
return;
}
Thread t = new Thread() {
@Override
public void run() {
readWaypoints();
ChartActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
chartView.invalidate();
}
});
}
};
t.start();
super.onChange(selfChange);
}
};
readProfileAsync();
}
@Override
protected void onPause() {
super.onPause();
unregisterContentObservers();
}
@Override
protected void onResume() {
super.onResume();
// Make sure any updates that might have happened are propagated to this
// activity:
observer.onChange(false);
waypointObserver.onChange(false);
registerContentObservers();
dataHub = TrackDataHub.getStartedInstance();
dataHub.registerTrackDataListener(this, EnumSet.of(
ListenerDataType.SELECTED_TRACK_CHANGED,
ListenerDataType.TRACK_UPDATES,
ListenerDataType.POINT_UPDATES,
ListenerDataType.SAMPLED_OUT_POINT_UPDATES,
ListenerDataType.WAYPOINT_UPDATES,
ListenerDataType.DISPLAY_PREFERENCES));
}
/**
* Register the content observer for the map overlay.
*/
private void registerContentObservers() {
getContentResolver().registerContentObserver(TrackPointsColumns.CONTENT_URI,
false/* notifyForDescendents */, observer);
getContentResolver().registerContentObserver(WaypointsColumns.CONTENT_URI,
false/* notifyForDescendents */, waypointObserver);
}
@Override
protected void onPause() {
dataHub.unregisterTrackDataListener(this);
dataHub = null;
/**
* Unregister the content observer for the map overlay.
*/
private void unregisterContentObservers() {
getContentResolver().unregisterContentObserver(observer);
getContentResolver().unregisterContentObserver(waypointObserver);
}
private boolean selectedTrackIsRecording() {
return selectedTrackId == recordingTrackId;
super.onPause();
}
private void zoomIn() {
@@ -354,52 +178,10 @@ public class ChartActivity extends Activity implements
zoomControls.setIsZoomOutEnabled(chartView.canZoomOut());
}
public void setMode(Mode newMode) {
if (this.mode != newMode) {
this.mode = newMode;
chartView.setMode(this.mode);
readProfileAsync();
}
}
public Mode getMode() {
return mode;
}
public void setSeriesEnabled(int index, boolean enabled) {
chartView.getChartValueSeries(index).setEnabled(enabled);
runOnUiThread(updateChart);
}
public boolean isSeriesEnabled(int index) {
return chartView.getChartValueSeries(index).isEnabled();
}
private void readWaypoints() {
if (selectedTrackId < 0) {
return;
}
Cursor cursor = null;
chartView.clearWaypoints();
try {
// We will silently drop extra waypoints to make the app responsive.
cursor =
providerUtils.getWaypointsCursor(selectedTrackId, 0,
MyTracksConstants.MAX_DISPLAYED_TRACK_POINTS);
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
Waypoint wpt = providerUtils.createWaypoint(cursor);
chartView.addWaypoint(wpt);
} while (cursor.moveToNext());
}
}
} catch (RuntimeException e) {
Log.w(MyTracksConstants.TAG, "Caught an unexpected exception.", e);
} finally {
if (cursor != null) {
cursor.close();
}
private void setMode(Mode newMode) {
if (chartView.getMode() != newMode) {
chartView.setMode(newMode);
dataHub.reloadDataForListener(this);
}
}
@@ -407,7 +189,7 @@ public class ChartActivity extends Activity implements
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
chartSettingsMenuItem =
menu.add(0, MyTracksConstants.MENU_CHART_SETTINGS, 0,
menu.add(0, Constants.MENU_CHART_SETTINGS, 0,
R.string.chart_settings);
chartSettingsMenuItem.setIcon(R.drawable.chart_settings);
return true;
@@ -416,14 +198,53 @@ public class ChartActivity extends Activity implements
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MyTracksConstants.MENU_CHART_SETTINGS:
MyTracks.getInstance().getDialogManager().showDialogSafely(
DialogManager.DIALOG_CHART_SETTINGS);
case Constants.MENU_CHART_SETTINGS:
showDialog(CHART_SETTINGS_DIALOG);
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected Dialog onCreateDialog(int id) {
if (id == CHART_SETTINGS_DIALOG) {
final ChartSettingsDialog settingsDialog = new ChartSettingsDialog(this);
settingsDialog.setOnClickListener(new OnClickListener() {
@Override
public void onClick(DialogInterface arg0, int which) {
if (which != DialogInterface.BUTTON_POSITIVE) {
return;
}
for (int i = 0; i < ChartView.NUM_SERIES; i++) {
chartView.setChartValueSeriesEnabled(i, settingsDialog.isSeriesEnabled(i));
}
setMode(settingsDialog.getMode());
chartView.postInvalidate();
}
});
return settingsDialog;
}
return super.onCreateDialog(id);
}
@Override
protected void onPrepareDialog(int id, Dialog dialog) {
super.onPrepareDialog(id, dialog);
if (id == CHART_SETTINGS_DIALOG) {
prepareSettingsDialog((ChartSettingsDialog) dialog);
}
}
private void prepareSettingsDialog(ChartSettingsDialog settingsDialog) {
settingsDialog.setMode(chartView.getMode());
for (int i = 0; i < ChartView.NUM_SERIES; i++) {
settingsDialog.setSeriesEnabled(i, chartView.isChartValueSeriesEnabled(i));
}
}
/**
* Given a location, creates a new data point for the chart. A data point is
* an array double[3 or 6], where:
@@ -438,49 +259,48 @@ public class ChartActivity extends Activity implements
* This must be called in order for each point.
*
* @param location the location to get data for (this method takes ownership of that location)
* @param track the track to get data from
* @param result the resulting point to fill out
* @return the previous location, now available for reuse
*/
private Location getDataPoint(Location location, Track track, double[] result) {
private void fillDataPoint(Location location, double result[]) {
double timeOrDistance = Double.NaN,
elevation = Double.NaN,
speed = Double.NaN,
power = Double.NaN,
cadence = Double.NaN,
heartRate = Double.NaN;
if (location instanceof MyTracksLocation &&
((MyTracksLocation) location).getSensorDataSet() != null) {
SensorDataSet sensorData = ((MyTracksLocation) location).getSensorDataSet();
if (sensorData.hasPower()
&& sensorData.getPower().getState() == Sensor.SensorState.SENDING
&& sensorData.getPower().hasValue()) {
result[3] = sensorData.getPower().getValue();
} else {
result[3] = Double.NaN;
power = sensorData.getPower().getValue();
}
if (sensorData.hasCadence()
&& sensorData.getCadence().getState() == Sensor.SensorState.SENDING
&& sensorData.getCadence().hasValue()) {
result[4] = sensorData.getCadence().getValue();
} else {
result[4] = Double.NaN;
cadence = sensorData.getCadence().getValue();
}
if (sensorData.hasHeartRate()
&& sensorData.getHeartRate().getState() == Sensor.SensorState.SENDING
&& sensorData.getHeartRate().hasValue()) {
result[5] = sensorData.getHeartRate().getValue();
} else {
result[5] = Double.NaN;
heartRate = sensorData.getHeartRate().getValue();
}
} else {
result[3] = Double.NaN;
result[4] = Double.NaN;
result[5] = Double.NaN;
}
// TODO: Account for segment splits?
Mode mode = chartView.getMode();
switch (mode) {
case BY_DISTANCE:
result[0] = profileLength;
timeOrDistance = profileLength / 1000.0;
if (lastLocation != null) {
double d = lastLocation.distanceTo(location);
if (metricUnits) {
profileLength += d / 1000.0;
profileLength += d;
} else {
profileLength += d * UnitConversions.KM_TO_MI / 1000.0;
profileLength += d * UnitConversions.KM_TO_MI;
}
}
break;
@@ -489,16 +309,16 @@ public class ChartActivity extends Activity implements
// Base case
startTime = location.getTime();
}
result[0] = (location.getTime() - startTime);
timeOrDistance = (location.getTime() - startTime);
break;
default:
Log.w(MyTracksConstants.TAG, "ChartActivity unknown mode: " + mode);
Log.w(TAG, "ChartActivity unknown mode: " + mode);
}
elevationBuffer.setNext(metricUnits
? location.getAltitude()
: location.getAltitude() * UnitConversions.M_TO_FT);
result[1] = elevationBuffer.getAverage();
elevation = elevationBuffer.getAverage();
if (lastLocation == null) {
if (Math.abs(location.getSpeed() - 128) > 1) {
@@ -507,151 +327,152 @@ public class ChartActivity extends Activity implements
} else if (TripStatisticsBuilder.isValidSpeed(
location.getTime(), location.getSpeed(), lastLocation.getTime(),
lastLocation.getSpeed(), speedBuffer)
&& (location.getSpeed() <= track.getStatistics().getMaxSpeed())) {
&& (location.getSpeed() <= trackMaxSpeed)) {
speedBuffer.setNext(location.getSpeed());
}
result[2] = speedBuffer.getAverage() * 3.6;
speed = speedBuffer.getAverage() * 3.6;
if (!metricUnits) {
result[2] *= UnitConversions.KM_TO_MI;
speed *= UnitConversions.KM_TO_MI;
}
if (!reportSpeed && (result[2] != 0)) {
// Format as hours per unit
result[2] = (60.0 / result[2]);
if (!reportSpeed) {
if (speed != 0) {
// Format as hours per unit
speed = (60.0 / speed);
} else {
speed = Double.NaN;
}
}
Location oldLastLocation = lastLocation;
// Keep a copy so the location can be reused.
lastLocation = location;
if (oldLastLocation == null) {
// No previous location, but return a blank one for reuse
return new MyTracksLocation("");
if (result != null) {
result[0] = timeOrDistance;
result[1] = elevation;
result[2] = speed;
result[3] = power;
result[4] = cadence;
result[5] = heartRate;
}
return oldLastLocation;
}
/**
* Sets the chart data points reading from the provider. This is non-blocking.
*/
private void readProfileAsync() {
chartView.reset();
updateTrackHandler.post(new Runnable() {
@Override
public void onProviderStateChange(ProviderState state) {
// We don't care.
}
@Override
public void onCurrentLocationChanged(Location loc) {
// We don't care.
}
@Override
public void onCurrentHeadingChanged(double heading) {
// We don't care.
}
@Override
public void onSelectedTrackChanged(Track track, boolean isRecording) {
runOnUiThread(new Runnable() {
@Override
public void run() {
runOnUiThread(showSpinner);
readProfile();
readWaypoints();
runOnUiThread(updateChart);
busyPane.setVisibility(View.VISIBLE);
}
});
}
/**
* Reads the track profile from the provider. This is a blocking function and
* should not be run from the UI thread.
*/
private void readProfile() {
@Override
public void onTrackUpdated(Track track) {
if (track == null || track.getStatistics() == null) {
trackMaxSpeed = 0.0;
return;
}
trackMaxSpeed = track.getStatistics().getMaxSpeed();
}
@Override
public void clearTrackPoints() {
profileLength = 0;
lastLocation = null;
startTime = -1;
if (selectedTrackId < 0) {
return;
}
Track track = providerUtils.getTrack(selectedTrackId);
if (track == null) {
return;
}
lastSeenLocationId = track.getStartId();
final ArrayList<double[]> theData = readPointsToList(track);
elevationBuffer.reset();
chartView.reset();
speedBuffer.reset();
pendingPoints.clear();
runOnUiThread(new Runnable() {
@Override
public void run() {
chartView.setDataPoints(theData);
chartView.resetScroll();
}
});
}
/**
* Read all new track points.
*/
private void readNewTrackPoints() {
Log.i(MyTracksConstants.TAG, "MyTracks: Updating chart last seen: " + lastSeenLocationId);
Track track = providerUtils.getTrack(recordingTrackId);
if (track == null) {
Log.w(MyTracksConstants.TAG, "MyTracks: track not found");
return;
@Override
public void onNewTrackPoint(Location loc) {
if (LocationUtils.isValidLocation(loc)) {
double[] point = new double[6];
fillDataPoint(loc, point);
pendingPoints.add(point);
}
chartView.addDataPoints(readPointsToList(track));
uiHandler.post(new Runnable() {
public void run() {
chartView.invalidate();
}
});
Log.i(MyTracksConstants.TAG, "MyTracks: Updated chart last seen: " + lastSeenLocationId);
}
/**
* Get the frequency at which points should be displayed.
* Limit the number of chart readings. Ideally we would want around 1024.
* @param track The track which will be displayed.
* @return The inverse of the frequency of points to be displayed.
*/
private int getSamplingFrequency(Track track) {
long totalLocations = track.getStopId() - track.getStartId();
return Math.max(1, (int) (totalLocations / 1024.0));
@Override
public void onSampledOutTrackPoint(Location loc) {
// Still account for the point in the smoothing buffers.
fillDataPoint(loc, null);
}
private Cursor getLocationsCursor(long lastLocationRead) {
return providerUtils.getLocationsCursor(selectedTrackId, lastLocationRead, BUFFER_SIZE, false);
@Override
public void onSegmentSplit() {
// Do nothing.
}
/**
* Read all of the points to a list.
* @param track The track which will be displayed.
* @return
*/
private ArrayList<double[]> readPointsToList(Track track) {
Cursor cursor = null;
long lastLocationRead = lastSeenLocationId;
int points = 0;
int chartSamplingFrequency = getSamplingFrequency(track);
ArrayList<double[]> result = new ArrayList<double[]>();
// Need two locations so we can keep track of the last location.
Location location = new MyTracksLocation("");
try {
while (lastSeenLocationId < track.getStopId()) {
cursor = getLocationsCursor(lastLocationRead);
if (cursor != null) {
elevationBuffer.reset();
speedBuffer.reset();
if (cursor.moveToFirst()) {
final int idColumnIdx = cursor.getColumnIndexOrThrow(TrackPointsColumns._ID);
while (cursor.moveToNext()) {
points++;
providerUtils.fillLocation(cursor, location);
if (MyTracksUtils.isValidLocation(location)) {
lastLocationRead = lastSeenLocationId =
cursor.getLong(idColumnIdx);
// TODO Can we be smarter about choosing 3 or 6 entries?
double[] point = new double[6];
location = getDataPoint(location, track, point);
if (points % chartSamplingFrequency == 0) {
result.add(point);
}
}
}
} else {
lastLocationRead += BUFFER_SIZE;
}
} else {
lastLocationRead += BUFFER_SIZE;
}
cursor.close();
cursor = null;
}
return result;
} finally {
if (cursor != null) {
cursor.close();
}
}
@Override
public void onNewTrackPointsDone() {
chartView.addDataPoints(pendingPoints);
pendingPoints.clear();
runOnUiThread(updateChart);
}
@Override
public void clearWaypoints() {
chartView.clearWaypoints();
}
@Override
public void onNewWaypoint(Waypoint wpt) {
chartView.addWaypoint(wpt);
}
@Override
public void onNewWaypointsDone() {
runOnUiThread(updateChart);
}
@Override
public boolean onUnitsChanged(boolean metric) {
boolean changed = metric != this.metricUnits;
if (!changed) return false;
this.metricUnits = metric;
chartView.setMetricUnits(metric);
return true; // Reload data
}
@SuppressWarnings("hiding")
@Override
public boolean onReportSpeedChanged(boolean reportSpeed) {
boolean changed = reportSpeed != this.reportSpeed;
if (!changed) return false;
this.reportSpeed = reportSpeed;
chartView.setReportSpeed(reportSpeed, this);
return true; // Reload data
}
}
@@ -1,12 +1,12 @@
/*
* Copyright 2009 Google Inc.
*
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -36,6 +36,7 @@ import android.widget.RadioGroup;
public class ChartSettingsDialog extends Dialog {
private RadioButton distance;
private CheckBox[] series;
private OnClickListener clickListener;
public ChartSettingsDialog(Context context) {
super(context);
@@ -44,23 +45,31 @@ public class ChartSettingsDialog extends Dialog {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.chart_settings);
Button cancel = (Button) findViewById(R.id.chart_settings_cancel);
cancel.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (clickListener != null) {
clickListener.onClick(ChartSettingsDialog.this, BUTTON_NEGATIVE);
}
dismiss();
}
});
Button ok = (Button) findViewById(R.id.chart_settings_ok);
ok.setOnClickListener(new View.OnClickListener() {
Button okButton = (Button) findViewById(R.id.chart_settings_ok);
okButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
handleOk();
if (clickListener != null) {
clickListener.onClick(ChartSettingsDialog.this, BUTTON_POSITIVE);
}
dismiss();
}
});
distance = (RadioButton) findViewById(R.id.chart_settings_by_distance);
series = new CheckBox[ChartView.NUM_SERIES];
series[ChartView.ELEVATION_SERIES] =
(CheckBox) findViewById(R.id.chart_settings_elevation);
@@ -74,29 +83,30 @@ public class ChartSettingsDialog extends Dialog {
(CheckBox) findViewById(R.id.chart_settings_heart_rate);
}
public void setup(ChartActivity chart) {
if (chart == null) {
return;
}
public void setMode(Mode mode) {
RadioGroup rd = (RadioGroup) findViewById(R.id.chart_settings_x);
rd.check(chart.getMode() == Mode.BY_DISTANCE
rd.check(mode == Mode.BY_DISTANCE
? R.id.chart_settings_by_distance
: R.id.chart_settings_by_time);
for (int i = 0; i < ChartView.NUM_SERIES; i++) {
series[i].setChecked(chart.isSeriesEnabled(i));
}
}
private void handleOk() {
ChartActivity chart = MyTracks.getInstance().getChartActivity();
chart.setMode(distance.isChecked() ? Mode.BY_DISTANCE : Mode.BY_TIME);
public void setSeriesEnabled(int seriesIdx, boolean enabled) {
series[seriesIdx].setChecked(enabled);
}
// TODO: check that something is visible.
for (int i = 0; i < ChartView.NUM_SERIES; i++) {
chart.setSeriesEnabled(i, series[i].isChecked());
}
public Mode getMode() {
if (distance == null) return Mode.BY_DISTANCE;
dismiss();
return distance.isChecked() ? Mode.BY_DISTANCE : Mode.BY_TIME;
}
public boolean isSeriesEnabled(int seriesIdx) {
if (series == null) return true;
return series[seriesIdx].isChecked();
}
public void setOnClickListener(OnClickListener clickListener) {
this.clickListener = clickListener;
}
}
@@ -1,12 +1,12 @@
/*
* Copyright 2009 Google Inc.
*
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -48,7 +48,7 @@ public class ChartValueSeries {
private double spread;
private int interval;
private boolean enabled = true;
/**
* This class controls how effective min/max values of a {@link ChartValueSeries} are calculated.
*/
@@ -70,10 +70,10 @@ public class ChartValueSeries {
this.intervals = intervals;
this.absoluteMin = absoluteMin;
this.absoluteMax = absoluteMax;
this.zoomLevels = zoomLevels;
this.zoomLevels = zoomLevels;
checkArgs();
}
private void checkArgs() {
if (intervals <= 0 || zoomLevels == null || zoomLevels.length == 0) {
throw new IllegalArgumentException("Expecing positive intervals and non-empty zoom levels");
@@ -100,12 +100,12 @@ public class ChartValueSeries {
public int[] getZoomLevels() {
return zoomLevels;
}
/**
* Calculates the interval between markings given the min and max values.
* This function attempts to find the smallest zoom level that fits [min,max] after rounding
* it to the current zoom level.
*
*
* @param min the minimum value in the series
* @param max the maximum value in the series
* @return the calculated interval for the given range
@@ -136,7 +136,7 @@ public class ChartValueSeries {
* @param fill The paint for filling the chart
* @param stroke The paint for stroking the outside the chart, optional
* @param zoomSettings The settings related to zooming
*
*
* TODO: Get rid of Context and inject appropriate values instead.
*/
public ChartValueSeries(Context context, String formatString, int fillColor, int strokeColor,
@@ -207,7 +207,7 @@ public class ChartValueSeries {
}
min = Math.min(min, zoomSettings.getAbsoluteMin());
max = Math.max(max, zoomSettings.getAbsoluteMax());
this.interval = zoomSettings.calculateInterval(min, max);
// Round it up.
effectiveMax = ((int) (max / interval)) * interval + interval;
@@ -1,12 +1,12 @@
/*
* Copyright 2008 Google Inc.
*
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -28,9 +28,9 @@ import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.drawable.Drawable;
import android.view.MotionEvent;
import android.view.VelocityTracker;
@@ -49,6 +49,7 @@ import java.util.ArrayList;
* @author Leif Hendrik Wilden
*/
public class ChartView extends View {
private static final int MIN_ZOOM_LEVEL = 1;
/*
* Scrolling logic:
@@ -62,40 +63,41 @@ public class ChartView extends View {
* Zoom logic:
*/
private int zoomLevel = 1;
private final int minZoomLevel = 1;
private int maxZoomLevel = 10;
private static final int MAX_INTERVALS = 5;
/*
* Borders, margins, dimensions (in pixels):
*/
private int leftBorder = -1;
/**
* Unscaled top border of the chart.
* Unscaled top border of the chart.
*/
private static final int TOP_BORDER = 15;
/**
* Device scaled top border of the chart.
*/
private int topBorder;
/**
* Unscaled bottom border of the chart.
* Unscaled bottom border of the chart.
*/
private static final float BOTTOM_BORDER = 40;
/**
* Device scaled bottom border of the chart.
*/
private int bottomBorder;
private static final int RIGHT_BORDER = 17;
/** Space to leave for drawing the unit labels */
private static final int UNIT_BORDER = 15;
private static final int FONT_HEIGHT = 10;
private int w = 0;
private int h = 0;
private int effectiveWidth = 0;
@@ -118,11 +120,11 @@ public class ChartView extends View {
private ChartValueSeries[] series;
private final ExtremityMonitor xMonitor = new ExtremityMonitor();
private final NumberFormat xFormat = new DecimalFormat("###,###");
private final NumberFormat xShortFormat = new DecimalFormat("#.0");
private static final NumberFormat X_FORMAT = new DecimalFormat("###,###");
private static final NumberFormat X_SHORT_FORMAT = new DecimalFormat("#.0");
/*
* Paints etc. used when drawing the histogram:
* Paints etc. used when drawing the chart:
*/
private final Paint borderPaint = new Paint();
private final Paint labelPaint = new Paint();
@@ -174,7 +176,7 @@ public class ChartView extends View {
gridBarPaint.set(gridPaint);
gridBarPaint.setPathEffect(new DashPathEffect(new float[] {3, 2}, 0));
clearPaint.setStyle(Style.FILL);
clearPaint.setColor(context.getResources().getColor(R.color.white));
clearPaint.setAntiAlias(false);
@@ -197,7 +199,7 @@ public class ChartView extends View {
updateDimensions();
}
public void setUpChartValueSeries(Context context) {
private void setUpChartValueSeries(Context context) {
series = new ChartValueSeries[NUM_SERIES];
// Create the value series.
@@ -271,49 +273,12 @@ public class ChartView extends View {
: R.string.pace_label));
}
/**
* Gets the data that is displayed by the chart.
*
* @return an array list with data points
*/
public ArrayList<double[]> getData() {
return data;
}
/**
* Sets the data that is to be displayed by the chart.
*
* @param theData an array list of data points
*/
public synchronized void setDataPoints(ArrayList<double[]> theData) {
scrollTo(0, 0);
zoomLevel = 1;
data.clear();
xMonitor.reset();
for (ChartValueSeries cvs : series) {
cvs.reset();
}
addDataPoints(theData);
}
/**
* Adds a new data point to the chart.
*
* @param theData a data point
*/
public synchronized void addDataPoint(double[] theData) {
data.add(theData);
addDataPointInternal(theData);
updateDimensions();
setUpPath();
}
private void addDataPointInternal(double[] theData) {
xMonitor.update(theData[0]);
int min = Math.min(series.length, theData.length - 1);
for (int i = 0; i < min; i++) {
if (!Double.isNaN(theData[i + 1])) {
series[i].update(theData[i + 1]);
for (int i = 1; i <= min; i++) {
if (!Double.isNaN(theData[i])) {
series[i - 1].update(theData[i]);
}
}
// Fill in the extra's if needed.
@@ -329,25 +294,32 @@ public class ChartView extends View {
*
* @param theData an array list of data points to be added
*/
public synchronized void addDataPoints(ArrayList<double[]> theData) {
data.addAll(theData);
for (int i = 0; i < theData.size(); i++) {
double d[] = theData.get(i);
addDataPointInternal(d);
public void addDataPoints(ArrayList<double[]> theData) {
synchronized (data) {
data.addAll(theData);
for (int i = 0; i < theData.size(); i++) {
double d[] = theData.get(i);
addDataPointInternal(d);
}
updateDimensions();
setUpPath();
}
updateDimensions();
setUpPath();
}
/**
* Clears all data.
* Call this only from the UI thread!
*/
public synchronized void reset() {
data.clear();
zoomLevel = 1;
public void reset() {
synchronized (data) {
data.clear();
xMonitor.reset();
zoomLevel = 1;
updateDimensions();
}
}
public void resetScroll() {
scrollTo(0, 0);
updateDimensions();
}
/**
@@ -361,7 +333,7 @@ public class ChartView extends View {
* @return true if the chart can be zoomed out
*/
public boolean canZoomOut() {
return zoomLevel > minZoomLevel;
return zoomLevel > MIN_ZOOM_LEVEL;
}
/**
@@ -392,13 +364,6 @@ public class ChartView extends View {
}
}
/**
* @return the current zoom level (1 equals to showing all data points)
*/
public int getZoomLevel() {
return zoomLevel;
}
/**
* Initiates flinging.
*
@@ -427,14 +392,6 @@ public class ChartView extends View {
scrollTo(scrollX, 0);
}
/**
* Sets the scroll position of the chart. This will trigger a redraw.
*/
@Override
public void scrollTo(int x, int y) {
super.scrollTo(x, y);
}
/**
* @return the current display mode (by distance, by time)
*/
@@ -444,6 +401,7 @@ public class ChartView extends View {
/**
* Sets the display mode (by distance, by time).
* It is expected that after the mode change, data will be reloaded.
*/
public void setMode(Mode mode) {
this.mode = mode;
@@ -527,8 +485,8 @@ public class ChartView extends View {
}
if (nearestWaypoint != null && dmin < 100) {
Intent intent =
new Intent(getContext(), MyTracksWaypointDetails.class);
intent.putExtra("waypointid", nearestWaypoint.getId());
new Intent(getContext(), WaypointDetails.class);
intent.putExtra(WaypointDetails.WAYPOINT_ID_EXTRA, nearestWaypoint.getId());
getContext().startActivity(intent);
return true;
}
@@ -551,63 +509,60 @@ public class ChartView extends View {
}
@Override
protected synchronized void onDraw(Canvas c) {
if (w != c.getWidth() || h != c.getHeight()) {
// Dimensions have changed (for example due to orientation change).
w = c.getWidth();
h = c.getHeight();
effectiveWidth = Math.max(0, w - leftBorder - RIGHT_BORDER);
effectiveHeight = Math.max(0, h - topBorder - bottomBorder);
setUpPath();
}
c.save();
c.drawColor(Color.WHITE);
if (data.size() < 1) {
drawXAxis(c);
drawYAxis(c);
c.restore();
return;
}
c.save();
c.clipRect(leftBorder + 1 + getScrollX(), topBorder + 1,
w - RIGHT_BORDER + getScrollX() - 1, h - bottomBorder - 1);
protected void onDraw(Canvas c) {
synchronized (data) {
updateEffectiveDimensionsIfChanged(c);
drawGrid(c);
// Draw the data series.
for (ChartValueSeries cvs : series) {
if (cvs.isEnabled() && cvs.hasData()) {
cvs.drawPath(c);
}
}
// Draw the waypoints.
for (int i = 1; i < waypoints.size(); i++) {
final Waypoint waypoint = waypoints.get(i);
if (waypoint.getLocation() == null) {
continue;
}
// Keep original state.
c.save();
final float x = getWaypointX(waypoint);
c.drawLine(x, h - bottomBorder, x, topBorder, gridPaint);
c.translate(x - markerWidth / 2, markerHeight);
if (waypoints.get(i).getType() == Waypoint.TYPE_STATISTICS) {
statsMarker.draw(c);
} else {
waypointMarker.draw(c);
}
c.restore();
}
c.drawColor(Color.WHITE);
c.restore();
// Draw the axis and labels.
if (data.isEmpty()) {
// No data, draw only axes
drawXAxis(c);
drawYAxis(c);
c.restore();
return;
}
// Clip to graph drawing space
c.save();
clipToGraphSpace(c);
// Draw the grid and the data on it.
drawGrid(c);
drawDataSeries(c);
drawWaypoints(c);
// Go back to full canvas drawing.
c.restore();
// Draw the axes and their labels.
drawAxesAndLabels(c);
// Go back to original state.
c.restore();
// Draw the pointer
if (showPointer) {
drawPointer(c);
}
}
}
/** Clips the given canvas to the area where the graph lines should be drawn. */
private void clipToGraphSpace(Canvas c) {
c.clipRect(leftBorder + 1 + getScrollX(), topBorder + 1,
w - RIGHT_BORDER + getScrollX() - 1, h - bottomBorder - 1);
}
/** Draws the axes and their labels into th e given canvas. */
private void drawAxesAndLabels(Canvas c) {
drawXLabels(c);
drawXAxis(c);
drawSeriesTitles(c);
c.translate(getScrollX(), 0);
drawYAxis(c);
float density = getContext().getResources().getDisplayMetrics().density;
@@ -618,15 +573,47 @@ public class ChartView extends View {
x -= drawYLabels(cvs, c, x) + spacer;
}
}
c.restore();
if (showPointer && !data.isEmpty()) {
c.translate(getX(maxX) - pointer.getIntrinsicWidth() / 2,
getY(series[0], data.get(data.size() - 1)[1])
- pointer.getIntrinsicHeight() / 2 - 12);
pointer.draw(c);
}
/** Draws the current pointer into the given canvas. */
private void drawPointer(Canvas c) {
c.translate(getX(maxX) - pointer.getIntrinsicWidth() / 2,
getY(series[0], data.get(data.size() - 1)[1])
- pointer.getIntrinsicHeight() / 2 - 12);
pointer.draw(c);
}
/** Draws the waypoints into the given canvas. */
private void drawWaypoints(Canvas c) {
for (int i = 1; i < waypoints.size(); i++) {
final Waypoint waypoint = waypoints.get(i);
if (waypoint.getLocation() == null) {
continue;
}
c.save();
final float x = getWaypointX(waypoint);
c.drawLine(x, h - bottomBorder, x, topBorder, gridPaint);
c.translate(x - (float) markerWidth / 2.0f, (float) markerHeight);
if (waypoints.get(i).getType() == Waypoint.TYPE_STATISTICS) {
statsMarker.draw(c);
} else {
waypointMarker.draw(c);
}
c.restore();
}
}
/** Draws the data series into the given canvas. */
private void drawDataSeries(Canvas c) {
for (ChartValueSeries cvs : series) {
if (cvs.isEnabled() && cvs.hasData()) {
cvs.drawPath(c);
}
}
}
/** Draws the colored titles for the data series. */
private void drawSeriesTitles(Canvas c) {
int sections = 1;
for (ChartValueSeries cvs : series) {
@@ -644,17 +631,24 @@ public class ChartView extends View {
}
/**
* Sets up the path that is used to draw the histogram in onDraw(). The path
* Sets up the path that is used to draw the chart in onDraw(). The path
* needs to be updated any time after the data or histogram dimensions change.
*/
private synchronized void setUpPath() {
for (ChartValueSeries cvs : series) {
cvs.getPath().reset();
}
if (data.isEmpty()) {
return;
}
private void setUpPath() {
synchronized (data) {
for (ChartValueSeries cvs : series) {
cvs.getPath().reset();
}
if (!data.isEmpty()) {
drawPaths();
closePaths();
}
}
}
/** Actually draws the data points as a path. */
private void drawPaths() {
// All of the data points to the respective series.
// TODO: Come up with a better sampling than Math.max(1, (maxZoomLevel - zoomLevel + 1) / 2);
int sampling = 1;
@@ -673,7 +667,10 @@ public class ChartView extends View {
}
}
}
}
/** Closes the drawn path so it looks like a solid graph. */
private void closePaths() {
// Close the path.
int yCorner = topBorder + effectiveHeight;
int xCorner = getX(data.get(0)[0]);
@@ -692,12 +689,13 @@ public class ChartView extends View {
}
}
}
/**
* Find the index of the first point which has a series populated.
* @param seriesIndex The index of the value series to search for.
* Finds the index of the first point which has a series populated.
*
* @param seriesIndex The index of the value series to search for
* @return The index in the first data for the point in the series that has series
* index value populated or -1 if none is found.
* index value populated or -1 if none is found
*/
private int getFirstPointPopulatedIndex(int seriesIndex) {
for (int i = 0; i < data.size(); i++) {
@@ -709,7 +707,7 @@ public class ChartView extends View {
}
/**
* Update the histogram dimensions.
* Updates the chart dimensions.
*/
private void updateDimensions() {
maxX = xMonitor.getMax();
@@ -728,12 +726,31 @@ public class ChartView extends View {
}
}
float density = getContext().getResources().getDisplayMetrics().density;
// TODO: This should be function of the number of variables displayed.
maxLength = Math.max(maxLength, 1);
leftBorder = (int) (density * (4 + 8 * maxLength));
effectiveWidth = w - leftBorder - RIGHT_BORDER;
bottomBorder = (int) (density * BOTTOM_BORDER);
topBorder = (int) (density * TOP_BORDER);
effectiveHeight = h - topBorder - bottomBorder;
updateEffectiveDimensions();
}
/** Updates the effective dimensions where the graph will be drawn. */
private void updateEffectiveDimensions() {
effectiveWidth = Math.max(0, w - leftBorder - RIGHT_BORDER);
effectiveHeight = Math.max(0, h - topBorder - bottomBorder);
}
/**
* Updates the effective dimensions where the graph will be drawn, only if the
* dimensions of the given canvas have changed since the last call.
*/
private void updateEffectiveDimensionsIfChanged(Canvas c) {
if (w != c.getWidth() || h != c.getHeight()) {
// Dimensions have changed (for example due to orientation change).
w = c.getWidth();
h = c.getHeight();
updateEffectiveDimensions();
setUpPath();
}
}
private int getX(double distance) {
@@ -746,6 +763,7 @@ public class ChartView extends View {
- (int) ((y - cvs.getMin()) * effectiveHeight / effectiveSpread);
}
/** Draws the labels on the X axis into the given canvas. */
private void drawXLabels(Canvas c) {
double interval = (int) (maxX / zoomLevel / 4);
boolean shortFormat = false;
@@ -770,6 +788,7 @@ public class ChartView extends View {
}
}
/** Draws the labels on the Y axis into the given canvas. */
private float drawYLabels(ChartValueSeries cvs, Canvas c, int x) {
int interval = cvs.getInterval();
float maxTextWidth = 0;
@@ -779,13 +798,14 @@ public class ChartView extends View {
return maxTextWidth;
}
/** Draws a single label on the X axis. */
private void drawXLabel(Canvas c, double x, boolean shortFormat) {
if (x < 0) {
return;
}
String s =
(mode == Mode.BY_DISTANCE)
? (shortFormat ? xShortFormat.format(x) : xFormat.format(x))
? (shortFormat ? X_SHORT_FORMAT.format(x) : X_FORMAT.format(x))
: StringUtils.formatTime((long) x);
c.drawText(s,
getX(x),
@@ -793,6 +813,7 @@ public class ChartView extends View {
labelPaint);
}
/** Draws a single label on the Y axis. */
private float drawYLabel(ChartValueSeries cvs, Canvas c, int x, int y) {
int desiredY = (int) ((y - cvs.getMin()) * effectiveHeight /
(cvs.getInterval() * MAX_INTERVALS));
@@ -804,6 +825,7 @@ public class ChartView extends View {
return p.measureText(text);
}
/** Draws the actual X axis line and its label. */
private void drawXAxis(Canvas canvas) {
float rightEdge = getX(maxX);
final int y = effectiveHeight + topBorder;
@@ -815,6 +837,7 @@ public class ChartView extends View {
canvas.drawText(s, rightEdge, effectiveHeight + .2f * UNIT_BORDER + topBorder, labelPaint);
}
/** Draws the actual Y axis line and its label. */
private void drawYAxis(Canvas canvas) {
canvas.drawRect(0, 0,
leftBorder - 1, effectiveHeight + topBorder + UNIT_BORDER + 1,
@@ -826,18 +849,15 @@ public class ChartView extends View {
int y = i * effectiveHeight / MAX_INTERVALS + topBorder;
canvas.drawLine(leftBorder - 5, y, leftBorder, y, gridPaint);
}
Context c = getContext();
// TODO: This should really show units for all series.
String s = metricUnits ? c.getString(R.string.meter) : c.getString(R.string.feet);
canvas.drawText(s, leftBorder - UNIT_BORDER * .2f, UNIT_BORDER * .8f + topBorder, labelPaint);
}
private synchronized void drawGrid(Canvas c) {
if (data.isEmpty()) {
return;
}
/** Draws the grid for the graph. */
private void drawGrid(Canvas c) {
float rightEdge = getX(maxX);
for (int i = 1; i < MAX_INTERVALS; ++i) {
int y = i * effectiveHeight / MAX_INTERVALS + topBorder;
@@ -846,14 +866,24 @@ public class ChartView extends View {
}
/**
* Gets one of the chart value series.
* The index should be one of the following values:
* ELEVATION_SERIES or SPEED_SERIES
* Returns whether a given time series is enabled for drawing.
*
* @param index of the value series
* @return The chart series at the index
* @param index the time series, one of {@link #ELEVATION_SERIES},
* {@link #SPEED_SERIES}, {@link #POWER_SERIES}, etc.
* @return true if drawn, false otherwise
*/
public ChartValueSeries getChartValueSeries(int index) {
return series[index];
public boolean isChartValueSeriesEnabled(int index) {
return series[index].isEnabled();
}
/**
* Sets whether a given time series will be enabled for drawing.
*
* @param index the time series, one of {@link #ELEVATION_SERIES},
* {@link #SPEED_SERIES}, {@link #POWER_SERIES}, etc.
* @return true to be drawn, false otherwise
*/
public void setChartValueSeriesEnabled(int index, boolean enabled) {
series[index].setEnabled(enabled);
}
}
@@ -78,7 +78,7 @@ class CheckUnits {
private static void accept(Context context, SharedPreferences preferences) {
recordCheckPerformed(preferences);
Intent startIntent = new Intent(context, MyTracksSettings.class);
Intent startIntent = new Intent(context, SettingsActivity.class);
context.startActivity(startIntent);
}
@@ -20,18 +20,13 @@ package com.google.android.apps.mytracks;
*
* @author Leif Hendrik Wilden
*/
public abstract class MyTracksConstants {
public abstract class Constants {
/**
* Should be used by all log statements
*/
public static final String TAG = "MyTracks";
/**
* Name of the gps location provider:
*/
public static final String GPS_PROVIDER = "gps";
/**
* Name of the top-level directory inside the SD card where our files will
* be read from/written to.
@@ -55,7 +50,7 @@ public abstract class MyTracksConstants {
public static final int AUTHENTICATE_TO_DOCLIST = 10;
public static final int AUTHENTICATE_TO_TRIX = 11;
public static final int DELETE_TRACK = 13;
public static final int SEND_TO_GOOGLE_DIALOG = 14;
public static final int SEND_TO_GOOGLE = 14;
public static final int SHARE_LINK = 15;
public static final int SHARE_GPX_FILE = 16;
public static final int SHARE_KML_FILE = 17;
@@ -140,6 +135,12 @@ public abstract class MyTracksConstants {
*/
public static final int MAX_LOADED_TRACK_POINTS = 20000;
/**
* Maximum number of track points ever loaded at once from the provider into
* memory in a single call to read points.
*/
public static final int MAX_LOADED_TRACK_POINTS_PER_BATCH = 1000;
/**
* Maximum number of way points displayed by the map overlay.
*/
@@ -168,6 +169,12 @@ public abstract class MyTracksConstants {
*/
public static final double MAX_ACCELERATION = 0.02;
/** Maximum age of a GPS location to be considered current. */
public static final long MAX_LOCATION_AGE_MS = 60 * 1000; // 1 minute
/** Maximum age of a network location to be considered current. */
public static final long MAX_NETWORK_AGE_MS = 1000 * 60 * 10; // 10 minutes
/**
* The type of account that we can use for gdata uploads.
*/
@@ -182,32 +189,32 @@ public abstract class MyTracksConstants {
public static int getActionFromMenuId(int menuId) {
switch (menuId) {
case MyTracksConstants.MENU_SEND_TO_GOOGLE:
return MyTracksConstants.SEND_TO_GOOGLE_DIALOG;
case MyTracksConstants.MENU_EDIT:
return MyTracksConstants.EDIT_DETAILS;
case MyTracksConstants.MENU_DELETE:
return MyTracksConstants.DELETE_TRACK;
case MyTracksConstants.MENU_SHARE_LINK:
return MyTracksConstants.SHARE_LINK;
case MyTracksConstants.MENU_SHARE_KML_FILE:
return MyTracksConstants.SHARE_KML_FILE;
case MyTracksConstants.MENU_SHARE_GPX_FILE:
return MyTracksConstants.SHARE_GPX_FILE;
case MyTracksConstants.MENU_SHARE_CSV_FILE:
return MyTracksConstants.SHARE_CSV_FILE;
case MyTracksConstants.MENU_SHARE_TCX_FILE:
return MyTracksConstants.SHARE_TCX_FILE;
case MyTracksConstants.MENU_SAVE_GPX_FILE:
return MyTracksConstants.SAVE_GPX_FILE;
case MyTracksConstants.MENU_SAVE_KML_FILE:
return MyTracksConstants.SAVE_KML_FILE;
case MyTracksConstants.MENU_SAVE_CSV_FILE:
return MyTracksConstants.SAVE_CSV_FILE;
case MyTracksConstants.MENU_SAVE_TCX_FILE:
return MyTracksConstants.SAVE_TCX_FILE;
case MyTracksConstants.MENU_CLEAR_MAP:
return MyTracksConstants.CLEAR_MAP;
case Constants.MENU_SEND_TO_GOOGLE:
return Constants.SEND_TO_GOOGLE;
case Constants.MENU_EDIT:
return Constants.EDIT_DETAILS;
case Constants.MENU_DELETE:
return Constants.DELETE_TRACK;
case Constants.MENU_SHARE_LINK:
return Constants.SHARE_LINK;
case Constants.MENU_SHARE_KML_FILE:
return Constants.SHARE_KML_FILE;
case Constants.MENU_SHARE_GPX_FILE:
return Constants.SHARE_GPX_FILE;
case Constants.MENU_SHARE_CSV_FILE:
return Constants.SHARE_CSV_FILE;
case Constants.MENU_SHARE_TCX_FILE:
return Constants.SHARE_TCX_FILE;
case Constants.MENU_SAVE_GPX_FILE:
return Constants.SAVE_GPX_FILE;
case Constants.MENU_SAVE_KML_FILE:
return Constants.SAVE_KML_FILE;
case Constants.MENU_SAVE_CSV_FILE:
return Constants.SAVE_CSV_FILE;
case Constants.MENU_SAVE_TCX_FILE:
return Constants.SAVE_TCX_FILE;
case Constants.MENU_CLEAR_MAP:
return Constants.CLEAR_MAP;
default:
return -1;
}
@@ -216,8 +223,22 @@ public abstract class MyTracksConstants {
public static final String MAPSHOP_BASE_URL =
"http://maps.google.com/maps/ms";
/*
* Default values - keep in sync with those in preferences.xml.
*/
public static final int DEFAULT_ANNOUNCEMENT_FREQUENCY = -1;
public static final int DEFAULT_AUTO_RESUME_TRACK_TIMEOUT = 10; // In min.
public static final int DEFAULT_MAX_RECORDING_DISTANCE = 200;
public static final int DEFAULT_MIN_RECORDING_DISTANCE = 5;
public static final int DEFAULT_MIN_RECORDING_INTERVAL = 0;
public static final int DEFAULT_MIN_REQUIRED_ACCURACY = 200;
public static final int DEFAULT_SPLIT_FREQUENCY = 0;
public static final String SETTINGS_NAME = "SettingsActivity";
/**
* This is an abstract utility class.
*/
protected MyTracksConstants() { }
protected Constants() { }
}
@@ -1,12 +1,12 @@
/*
* Copyright 2008 Google Inc.
*
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -34,12 +34,12 @@ import android.util.Log;
*
* @author Leif Hendrik Wilden
*/
public class MyTracksDeleteAllTracks extends Handler {
public class DeleteAllTracks extends Handler {
private final Context context;
private final Runnable done;
public MyTracksDeleteAllTracks(Context context, Runnable done) {
public DeleteAllTracks(Context context, Runnable done) {
this.context = context;
this.done = done;
}
@@ -56,13 +56,14 @@ public class MyTracksDeleteAllTracks extends Handler {
builder.setIcon(android.R.drawable.ic_dialog_alert);
builder.setPositiveButton(context.getString(R.string.yes),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int i) {
dialog.dismiss();
Log.w(MyTracksConstants.TAG, "deleting all!");
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
Log.w(Constants.TAG, "deleting all!");
MyTracksProviderUtils.Factory.get(context).deleteAllTracks();
SharedPreferences prefs =
context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences.Editor editor = prefs.edit();
// TODO: Go through data manager
editor.putLong(context.getString(R.string.selected_track_key), -1);
ApiFeatures.getInstance().getApiPlatformAdapter().applyPreferenceChanges(editor);
if (done != null) {
@@ -73,8 +74,8 @@ public class MyTracksDeleteAllTracks extends Handler {
});
builder.setNegativeButton(context.getString(R.string.no),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int i) {
dialog.dismiss();
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
dialog = builder.create();
@@ -1,12 +1,12 @@
/*
* Copyright 2010 Google Inc.
*
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -15,217 +15,57 @@
*/
package com.google.android.apps.mytracks;
import com.google.android.maps.mytracks.R;
import static com.google.android.apps.mytracks.Constants.TAG;
import android.app.AlertDialog;
import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.WindowManager.BadTokenException;
/**
* A class to handle all dialog related events for My Tracks.
*
*
* @author Sandor Dornbush
*/
public class DialogManager {
public static final int DIALOG_CHART_SETTINGS = 1;
public static final int DIALOG_IMPORT_PROGRESS = 2;
public static final int DIALOG_PROGRESS = 3;
public static final int DIALOG_SEND_TO_GOOGLE = 4;
public static final int DIALOG_SEND_TO_GOOGLE_RESULT = 5;
public static final int DIALOG_WRITE_PROGRESS = 6;
private ProgressDialog progressDialog;
private ProgressDialog importProgressDialog;
private ProgressDialog writeProgressDialog;
private SendToGoogleDialog sendToGoogleDialog;
private AlertDialog sendToGoogleResultDialog;
private ChartSettingsDialog chartSettingsDialog;
private MyTracks activity;
public DialogManager(MyTracks activity) {
this.activity = activity;
}
protected Dialog onCreateDialog(int id, Bundle args) {
switch (id) {
case DIALOG_CHART_SETTINGS:
chartSettingsDialog = new ChartSettingsDialog(activity);
return chartSettingsDialog;
case DIALOG_IMPORT_PROGRESS:
importProgressDialog = new ProgressDialog(activity);
importProgressDialog.setIcon(android.R.drawable.ic_dialog_info);
importProgressDialog.setTitle(
activity.getString(R.string.progress_title));
importProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
importProgressDialog.setMessage(
activity.getString(R.string.import_progress_message));
return importProgressDialog;
case DIALOG_PROGRESS:
progressDialog = new ProgressDialog(activity);
progressDialog.setIcon(android.R.drawable.ic_dialog_info);
progressDialog.setTitle(activity.getString(R.string.progress_title));
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMessage("");
progressDialog.setMax(100);
progressDialog.setProgress(10);
return progressDialog;
case DIALOG_SEND_TO_GOOGLE:
sendToGoogleDialog = new SendToGoogleDialog(activity);
return sendToGoogleDialog;
case DIALOG_SEND_TO_GOOGLE_RESULT:
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setIcon(android.R.drawable.ic_dialog_info);
builder.setTitle("Title");
builder.setMessage("Message");
builder.setPositiveButton(activity.getString(R.string.ok), null);
builder.setNeutralButton(activity.getString(R.string.share_track),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
SendToGoogleDialog sendToGoogleDialog = getSendToGoogleDialog();
final boolean sentToMyMaps = sendToGoogleDialog.getSendToMyMaps();
final boolean sentToFusionTables = sendToGoogleDialog.getSendToFusionTables();
activity.shareLinkToMap(sentToMyMaps, sentToFusionTables);
dialog.dismiss();
}
});
sendToGoogleResultDialog = builder.create();
return sendToGoogleResultDialog;
case DIALOG_WRITE_PROGRESS:
writeProgressDialog = new ProgressDialog(activity);
writeProgressDialog.setIcon(android.R.drawable.ic_dialog_info);
writeProgressDialog.setTitle(
activity.getString(R.string.progress_title));
writeProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
writeProgressDialog.setMessage(
activity.getString(R.string.write_progress_message));
return writeProgressDialog;
/**
* The equivalent of {@link #showDialogSafely(int)}, but for a specific
* dialog instance.
*/
public static void showDialogSafely(Activity activity, final Dialog dialog) {
if (activity.isFinishing()) {
Log.w(TAG, "Activity finishing - not showing dialog");
return;
}
return null;
}
protected void onPrepareDialog(int id, Dialog dialog) {
switch (id) {
case DIALOG_SEND_TO_GOOGLE:
activity.resetSendToGoogleStatus();
break;
case DIALOG_SEND_TO_GOOGLE_RESULT:
boolean success = activity.getSendToGoogleSuccess();
sendToGoogleResultDialog.setTitle(
success ? R.string.success : R.string.error);
sendToGoogleResultDialog.setIcon(success
? android.R.drawable.ic_dialog_info
: android.R.drawable.ic_dialog_alert);
sendToGoogleResultDialog.setMessage(activity.getSendToGoogleResultMessage());
boolean canShare =
activity.getSendToFusionTablesTableId() != null &&
activity.getSendToMyMapsMapId() != null;
View share =
sendToGoogleResultDialog.findViewById(android.R.id.button3);
if (share != null) {
share.setVisibility(canShare ? View.VISIBLE : View.GONE);
}
break;
case DIALOG_CHART_SETTINGS:
Log.d(MyTracksConstants.TAG, "MyTracks.onPrepare chart dialog");
chartSettingsDialog.setup(activity.getChartActivity());
break;
}
}
public void setProgressMessage(final String message) {
activity.runOnUiThread(new Runnable() {
public void run() {
synchronized (this) {
if (progressDialog != null) {
progressDialog.setMessage(message);
}
}
}
});
}
public void setProgressValue(final int percent) {
activity.runOnUiThread(new Runnable() {
public void run() {
synchronized (this) {
if (progressDialog != null) {
progressDialog.setProgress(percent);
}
}
}
});
}
/**
* @return the sendToGoogleDialog
*/
public SendToGoogleDialog getSendToGoogleDialog() {
return sendToGoogleDialog;
}
/**
* Shows a dialog with the given message.
* Does it on the UI thread.
*
* @param success if true, displays an info icon/title, otherwise an error
* icon/title
* @param message resource string id
*/
public void showMessageDialog(final int message, final boolean success) {
activity.runOnUiThread(new Runnable() {
public void run() {
AlertDialog dialog = null;
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setMessage(activity.getString(message));
builder.setNegativeButton(activity.getString(R.string.ok), null);
builder.setIcon(success ? android.R.drawable.ic_dialog_info :
android.R.drawable.ic_dialog_alert);
builder.setTitle(success ? R.string.success : R.string.error);
dialog = builder.create();
dialog.show();
}
});
}
/**
* Just like showDialog, but will catch a BadTokenException that sometimes
* (very rarely) gets thrown. This might happen if the user hits the "back"
* button immediately after sending tracks to google.
*
* @param id the dialog id
*/
public void showDialogSafely(final int id) {
activity.runOnUiThread(new Runnable() {
public void run() {
try {
activity.showDialog(id);
dialog.show();
} catch (BadTokenException e) {
Log.w(MyTracksConstants.TAG,
"Could not display dialog with id " + id, e);
Log.w(TAG, "Could not display dialog", e);
} catch (IllegalStateException e) {
Log.w(MyTracksConstants.TAG,
"Could not display dialog with id " + id, e);
Log.w(TAG, "Could not display dialog", e);
}
}
});
}
/**
* Dismisses the progress dialog if it is showing. Executed on the UI thread.
* The equivalent of {@link #dismissDialogSafely(int)}, but for a specific
* dialog instance.
*/
public void dismissDialogSafely(final int id) {
public static void dismissDialogSafely(Activity activity, final Dialog dialog) {
if (activity.isFinishing()) {
Log.w(TAG, "Activity finishing - not dismissing dialog");
return;
}
activity.runOnUiThread(new Runnable() {
public void run() {
try {
activity.dismissDialog(id);
dialog.dismiss();
} catch (IllegalArgumentException e) {
// This will be thrown if this dialog was not shown before.
}
@@ -233,4 +73,5 @@ public class DialogManager {
});
}
private DialogManager() {}
}
@@ -98,7 +98,7 @@ class Eula {
ApiFeatures.getInstance().getApiPlatformAdapter().applyPreferenceChanges(
preferences.edit().putBoolean(PREFERENCE_EULA_ACCEPTED, true));
Intent startIntent = new Intent(activity, WelcomeActivity.class);
activity.startActivityForResult(startIntent, MyTracksConstants.WELCOME);
activity.startActivityForResult(startIntent, Constants.WELCOME);
}
private static void refuse(Activity activity) {
@@ -1,12 +1,12 @@
/*
* Copyright 2009 Google Inc.
*
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -17,10 +17,10 @@ package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.TracksColumns;
import com.google.android.apps.mytracks.io.TrackWriter;
import com.google.android.apps.mytracks.io.TrackWriterFactory;
import com.google.android.apps.mytracks.io.TrackWriterFactory.TrackFileFormat;
import com.google.android.apps.mytracks.util.MyTracksUtils;
import com.google.android.apps.mytracks.io.file.TrackWriter;
import com.google.android.apps.mytracks.io.file.TrackWriterFactory;
import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
import com.google.android.apps.mytracks.util.SystemUtils;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
@@ -29,8 +29,6 @@ import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.PowerManager.WakeLock;
import android.util.Log;
import android.widget.Toast;
@@ -71,14 +69,14 @@ public class ExportAllTracks {
format = TrackFileFormat.TCX;
break;
default:
Log.w(MyTracksConstants.TAG, "Unknown export format: " + which);
Log.w(Constants.TAG, "Unknown export format: " + which);
}
}
};
public ExportAllTracks(Activity activity) {
this.activity = activity;
Log.i(MyTracksConstants.TAG, "ExportAllTracks: Starting");
Log.i(Constants.TAG, "ExportAllTracks: Starting");
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setSingleChoiceItems(R.array.export_formats, 0, itemClick);
@@ -91,12 +89,7 @@ public class ExportAllTracks {
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
HandlerThread handlerThread;
Handler handler;
handlerThread = new HandlerThread("SendToMyMaps");
handlerThread.start();
handler = new Handler(handlerThread.getLooper());
handler.post(runner);
new Thread(runner, "SendToMyMaps").start();
}
};
@@ -113,14 +106,14 @@ public class ExportAllTracks {
*/
private void aquireLocksAndExport() {
SharedPreferences prefs =
activity.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
activity.getSharedPreferences(Constants.SETTINGS_NAME, 0);
long recordingTrackId = -1;
if (prefs != null) {
recordingTrackId =
prefs.getLong(activity.getString(R.string.recording_track_key), -1);
prefs.getLong(activity.getString(R.string.recording_track_key), -1);
}
if (recordingTrackId != -1) {
wakeLock = MyTracksUtils.acquireWakeLock(activity, wakeLock);
wakeLock = SystemUtils.acquireWakeLock(activity, wakeLock);
}
// Now we can safely export everything.
@@ -130,10 +123,10 @@ public class ExportAllTracks {
// TODO check what happens if we started recording after getting this lock.
if (wakeLock != null && wakeLock.isHeld()) {
wakeLock.release();
Log.i(MyTracksConstants.TAG, "ExportAllTracks: Releasing wake lock.");
Log.i(Constants.TAG, "ExportAllTracks: Releasing wake lock.");
}
Log.i(MyTracksConstants.TAG, "ExportAllTracks: Done");
Toast.makeText(activity, R.string.export_done, Toast.LENGTH_SHORT).show();
Log.i(Constants.TAG, "ExportAllTracks: Done");
showToast(R.string.export_done, Toast.LENGTH_SHORT);
}
private void makeProgressDialog(final int trackCount) {
@@ -163,7 +156,7 @@ public class ExportAllTracks {
}
final int trackCount = cursor.getCount();
Log.i(MyTracksConstants.TAG,
Log.i(Constants.TAG,
"ExportAllTracks: Exporting: " + cursor.getCount() + " tracks.");
int idxTrackId = cursor.getColumnIndexOrThrow(TracksColumns._ID);
activity.runOnUiThread(new Runnable() {
@@ -186,15 +179,19 @@ public class ExportAllTracks {
});
long id = cursor.getLong(idxTrackId);
Log.i(MyTracksConstants.TAG, "ExportAllTracks: exporting: " + id);
Log.i(Constants.TAG, "ExportAllTracks: exporting: " + id);
TrackWriter writer =
TrackWriterFactory.newWriter(activity, providerUtils, id, format);
if (writer == null) {
showToast(R.string.error_track_does_not_exist, Toast.LENGTH_LONG);
return;
}
writer.writeTrack();
if (!writer.wasSuccess()) {
// Abort the whole export on the first error.
int error = writer.getErrorMessage();
Toast.makeText(activity, error, Toast.LENGTH_LONG).show();
showToast(writer.getErrorMessage(), Toast.LENGTH_LONG);
return;
}
}
@@ -210,4 +207,13 @@ public class ExportAllTracks {
}
}
}
private void showToast(final int messageId, final int length) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(activity, messageId, length).show();
}
});
}
}
@@ -1,12 +1,12 @@
/*
* Copyright 2011 Google Inc.
*
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -16,17 +16,15 @@
package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.io.GpxImporter;
import com.google.android.apps.mytracks.io.file.GpxImporter;
import com.google.android.apps.mytracks.util.FileUtils;
import com.google.android.apps.mytracks.util.MyTracksUtils;
import com.google.android.apps.mytracks.util.SystemUtils;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.PowerManager.WakeLock;
import android.util.Log;
import android.widget.Toast;
@@ -45,7 +43,7 @@ import org.xml.sax.SAXException;
/**
* A class that will import all GPX tracks in /sdcard/MyTracks/gpx/
*
*
* @author David Piggott
*/
public class ImportAllTracks {
@@ -60,15 +58,11 @@ public class ImportAllTracks {
public ImportAllTracks(Activity activity) {
this.activity = activity;
Log.i(MyTracksConstants.TAG, "ImportAllTracks: Starting");
Log.i(Constants.TAG, "ImportAllTracks: Starting");
fileUtils = new FileUtils();
gpxPath = fileUtils.buildExternalDirectoryPath("gpx");
HandlerThread handlerThread;
Handler handler;
handlerThread = new HandlerThread("ImportAllTracks");
handlerThread.start();
handler = new Handler(handlerThread.getLooper());
handler.post(runner);
new Thread(runner).start();
}
private final Runnable runner = new Runnable() {
@@ -82,13 +76,13 @@ public class ImportAllTracks {
* track. Acquire a wake lock if there is no current track.
*/
private void aquireLocksAndImport() {
SharedPreferences prefs = activity.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
SharedPreferences prefs = activity.getSharedPreferences(Constants.SETTINGS_NAME, 0);
long recordingTrackId = -1;
if (prefs != null) {
recordingTrackId = prefs.getLong(activity.getString(R.string.recording_track_key), -1);
}
if (recordingTrackId != -1) {
wakeLock = MyTracksUtils.acquireWakeLock(activity, wakeLock);
wakeLock = SystemUtils.acquireWakeLock(activity, wakeLock);
}
// Now we can safely import everything.
@@ -98,15 +92,15 @@ public class ImportAllTracks {
// TODO check what happens if we started recording after getting this lock.
if (wakeLock != null && wakeLock.isHeld()) {
wakeLock.release();
Log.i(MyTracksConstants.TAG, "ImportAllTracks: Releasing wake lock.");
Log.i(Constants.TAG, "ImportAllTracks: Releasing wake lock.");
}
Log.i(MyTracksConstants.TAG, "ImportAllTracks: Done");
Log.i(Constants.TAG, "ImportAllTracks: Done");
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
if (gpxFileCount == 0) {
builder.setMessage(activity.getString(R.string.import_empty, gpxPath + "/"));
builder.setMessage(activity.getString(R.string.import_multi_empty, gpxPath + "/"));
} else {
builder.setMessage(activity.getString(R.string.import_done, importSuccessCount, gpxFileCount,
builder.setMessage(activity.getString(R.string.import_multi_done, importSuccessCount, gpxFileCount,
gpxPath + "/"));
}
builder.setPositiveButton(R.string.ok, null);
@@ -141,7 +135,7 @@ public class ImportAllTracks {
return;
}
Log.i(MyTracksConstants.TAG, "ImportAllTracks: Importing: " + gpxFileCount + " tracks.");
Log.i(Constants.TAG, "ImportAllTracks: Importing: " + gpxFileCount + " tracks.");
activity.runOnUiThread(new Runnable() {
public void run() {
makeProgressDialog(gpxFileCount);
@@ -180,19 +174,19 @@ public class ImportAllTracks {
* notifications and returns false on failure.
*/
private boolean importFile(File gpxFile, MyTracksProviderUtils providerUtils) {
Log.i(MyTracksConstants.TAG, "ImportAllTracks: importing: " + gpxFile.getName());
Log.i(Constants.TAG, "ImportAllTracks: importing: " + gpxFile.getName());
try {
GpxImporter.importGPXFile(new FileInputStream(gpxFile), providerUtils);
return true;
} catch (FileNotFoundException e) {
Log.w(MyTracksConstants.TAG, "GPX file wasn't found/went missing: "
Log.w(Constants.TAG, "GPX file wasn't found/went missing: "
+ gpxFile.getAbsolutePath(), e);
} catch (ParserConfigurationException e) {
Log.w(MyTracksConstants.TAG, "Error parsing file: " + gpxFile.getAbsolutePath(), e);
Log.w(Constants.TAG, "Error parsing file: " + gpxFile.getAbsolutePath(), e);
} catch (SAXException e) {
Log.w(MyTracksConstants.TAG, "Error parsing file: " + gpxFile.getAbsolutePath(), e);
Log.w(Constants.TAG, "Error parsing file: " + gpxFile.getAbsolutePath(), e);
} catch (IOException e) {
Log.w(MyTracksConstants.TAG, "Error reading file: " + gpxFile.getAbsolutePath(), e);
Log.w(Constants.TAG, "Error reading file: " + gpxFile.getAbsolutePath(), e);
}
Toast.makeText(activity, activity.getString(R.string.import_error, gpxFile.getName()),
Toast.LENGTH_LONG).show();
@@ -0,0 +1,600 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks;
import static com.google.android.apps.mytracks.Constants.TAG;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.TrackDataHub;
import com.google.android.apps.mytracks.content.TrackDataHub.ListenerDataType;
import com.google.android.apps.mytracks.content.TrackDataListener;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.io.file.SaveActivity;
import com.google.android.apps.mytracks.io.sendtogoogle.SendActivity;
import com.google.android.apps.mytracks.services.tasks.StatusAnnouncerFactory;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.ApiFeatures;
import com.google.android.apps.mytracks.util.GeoRect;
import com.google.android.apps.mytracks.util.LocationUtils;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.mytracks.R;
import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.SubMenu;
import android.view.View;
import android.view.View.OnCreateContextMenuListener;
import android.view.Window;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import java.util.EnumSet;
/**
* The map view activity of the MyTracks application.
*
* @author Leif Hendrik Wilden
* @author Rodrigo Damazio
*/
public class MapActivity extends com.google.android.maps.MapActivity
implements View.OnTouchListener, View.OnClickListener,
TrackDataListener {
// Saved instance state keys:
// ---------------------------
private static final String KEY_CURRENT_LOCATION = "currentLocation";
private static final String KEY_KEEP_MY_LOCATION_VISIBLE = "keepMyLocationVisible";
private TrackDataHub dataHub;
/**
* True if the map should be scrolled so that the pointer is always in the
* visible area.
*/
private boolean keepMyLocationVisible;
/**
* The current pointer location.
* This is kept to quickly center on it when the user requests.
*/
private Location currentLocation;
// UI elements:
// -------------
private RelativeLayout screen;
private MapView mapView;
private MapOverlay mapOverlay;
private LinearLayout messagePane;
private TextView messageText;
private LinearLayout busyPane;
private ImageButton optionsBtn;
private MenuItem myLocation;
private MenuItem toggleLayers;
/**
* We are not displaying driving directions. Just an arbitrary track that is
* not associated to any licensed mapping data. Therefore it should be okay to
* return false here and still comply with the terms of service.
*/
@Override
protected boolean isRouteDisplayed() {
return false;
}
/**
* We are displaying a location. This needs to return true in order to comply
* with the terms of service.
*/
@Override
protected boolean isLocationDisplayed() {
return true;
}
// Application life cycle:
// ------------------------
@Override
protected void onCreate(Bundle bundle) {
Log.d(TAG, "MapActivity.onCreate");
super.onCreate(bundle);
// The volume we want to control is the Text-To-Speech volume
int volumeStream =
new StatusAnnouncerFactory(ApiFeatures.getInstance()).getVolumeStream();
setVolumeControlStream(volumeStream);
// We don't need a window title bar:
requestWindowFeature(Window.FEATURE_NO_TITLE);
// Inflate the layout:
setContentView(R.layout.mytracks_layout);
// Remove the window's background because the MapView will obscure it
getWindow().setBackgroundDrawable(null);
// Set up a map overlay:
screen = (RelativeLayout) findViewById(R.id.screen);
mapView = (MapView) findViewById(R.id.map);
mapView.requestFocus();
mapOverlay = new MapOverlay(this);
mapView.getOverlays().add(mapOverlay);
mapView.setOnTouchListener(this);
mapView.setBuiltInZoomControls(true);
messagePane = (LinearLayout) findViewById(R.id.messagepane);
messageText = (TextView) findViewById(R.id.messagetext);
busyPane = (LinearLayout) findViewById(R.id.busypane);
optionsBtn = (ImageButton) findViewById(R.id.showOptions);
optionsBtn.setOnCreateContextMenuListener(contextMenuListener);
optionsBtn.setOnClickListener(this);
}
@Override
protected void onRestoreInstanceState(Bundle bundle) {
Log.d(TAG, "MapActivity.onRestoreInstanceState");
if (bundle != null) {
super.onRestoreInstanceState(bundle);
keepMyLocationVisible =
bundle.getBoolean(KEY_KEEP_MY_LOCATION_VISIBLE, false);
if (bundle.containsKey(KEY_CURRENT_LOCATION)) {
currentLocation = (Location) bundle.getParcelable(KEY_CURRENT_LOCATION);
if (currentLocation != null) {
showCurrentLocation();
}
} else {
currentLocation = null;
}
}
}
@Override
protected void onResume() {
Log.d(TAG, "MapActivity.onResume");
super.onResume();
dataHub = TrackDataHub.getStartedInstance();
dataHub.registerTrackDataListener(this, EnumSet.of(
ListenerDataType.SELECTED_TRACK_CHANGED,
ListenerDataType.POINT_UPDATES,
ListenerDataType.WAYPOINT_UPDATES,
ListenerDataType.LOCATION_UPDATES,
ListenerDataType.COMPASS_UPDATES));
}
@Override
protected void onSaveInstanceState(Bundle outState) {
Log.d(TAG, "MapActivity.onSaveInstanceState");
outState.putBoolean(KEY_KEEP_MY_LOCATION_VISIBLE, keepMyLocationVisible);
if (currentLocation != null) {
outState.putParcelable(KEY_CURRENT_LOCATION, currentLocation);
}
super.onSaveInstanceState(outState);
}
@Override
protected void onPause() {
Log.d(TAG, "MapActivity.onPause");
dataHub.unregisterTrackDataListener(this);
dataHub = null;
super.onPause();
}
// Utility functions:
// -------------------
/**
* Shows the options button if a track is selected, or hide it if not.
*/
private void updateOptionsButton(boolean trackSelected) {
optionsBtn.setVisibility(
trackSelected ? View.VISIBLE : View.INVISIBLE);
}
/**
* Tests if a location is visible.
*
* @param location a given location
* @return true if the given location is within the visible map area
*/
private boolean locationIsVisible(Location location) {
if (location == null || mapView == null) {
return false;
}
GeoPoint center = mapView.getMapCenter();
int latSpan = mapView.getLatitudeSpan();
int lonSpan = mapView.getLongitudeSpan();
// Bottom of map view is obscured by zoom controls/buttons.
// Subtract a margin from the visible area:
GeoPoint marginBottom = mapView.getProjection().fromPixels(
0, mapView.getHeight());
GeoPoint marginTop = mapView.getProjection().fromPixels(0,
mapView.getHeight()
- mapView.getZoomButtonsController().getZoomControls().getHeight());
int margin =
Math.abs(marginTop.getLatitudeE6() - marginBottom.getLatitudeE6());
GeoRect r = new GeoRect(center, latSpan, lonSpan);
r.top += margin;
GeoPoint geoPoint = LocationUtils.getGeoPoint(location);
return r.contains(geoPoint);
}
/**
* Moves the location pointer to the current location and center the map if
* the current location is outside the visible area.
*/
private void showCurrentLocation() {
if (mapOverlay == null || mapView == null) {
return;
}
mapOverlay.setMyLocation(currentLocation);
mapView.postInvalidate();
if (currentLocation != null && keepMyLocationVisible && !locationIsVisible(currentLocation)) {
GeoPoint geoPoint = LocationUtils.getGeoPoint(currentLocation);
MapController controller = mapView.getController();
controller.animateTo(geoPoint);
}
}
@Override
public void onTrackUpdated(Track track) {
// We don't care.
}
/**
* Zooms and pans the map so that the given track is visible.
*
* @param track the track
*/
private void zoomMapToBoundaries(Track track) {
if (mapView == null) {
return;
}
if (track == null || track.getNumberOfPoints() < 2) {
return;
}
TripStatistics stats = track.getStatistics();
int bottom = stats.getBottom();
int left = stats.getLeft();
int latSpanE6 = stats.getTop() - bottom;
int lonSpanE6 = stats.getRight() - left;
if (latSpanE6 > 0
&& latSpanE6 < 180E6
&& lonSpanE6 > 0
&& lonSpanE6 < 360E6) {
keepMyLocationVisible = false;
GeoPoint center = new GeoPoint(
bottom + latSpanE6 / 2,
left + lonSpanE6 / 2);
if (LocationUtils.isValidGeoPoint(center)) {
mapView.getController().setCenter(center);
mapView.getController().zoomToSpan(latSpanE6, lonSpanE6);
}
}
}
/**
* Zooms and pans the map so that the given waypoint is visible.
*/
public void showWaypoint(long waypointId) {
MyTracksProviderUtils providerUtils = MyTracksProviderUtils.Factory.get(this);
Waypoint wpt = providerUtils.getWaypoint(waypointId);
if (wpt != null && wpt.getLocation() != null) {
keepMyLocationVisible = false;
GeoPoint center = new GeoPoint(
(int) (wpt.getLocation().getLatitude() * 1E6),
(int) (wpt.getLocation().getLongitude() * 1E6));
mapView.getController().setCenter(center);
mapView.getController().setZoom(20);
mapView.invalidate();
}
}
@Override
public void onSelectedTrackChanged(final Track track, final boolean isRecording) {
runOnUiThread(new Runnable() {
@Override
public void run() {
boolean trackSelected = track != null;
updateOptionsButton(trackSelected);
mapOverlay.setTrackDrawingEnabled(trackSelected);
if (trackSelected) {
busyPane.setVisibility(View.VISIBLE);
zoomMapToBoundaries(track);
mapOverlay.setShowEndMarker(!isRecording);
busyPane.setVisibility(View.GONE);
}
mapView.invalidate();
}
});
}
private final OnCreateContextMenuListener contextMenuListener =
new OnCreateContextMenuListener() {
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
menu.setHeaderTitle(R.string.tracklist_this_track);
menu.add(0, Constants.MENU_EDIT, 0,
R.string.tracklist_edit_track);
if (!dataHub.isRecordingSelected()) {
menu.add(0, Constants.MENU_SEND_TO_GOOGLE, 0,
R.string.tracklist_send_to_google);
SubMenu share = menu.addSubMenu(0, Constants.MENU_SHARE, 0,
R.string.tracklist_share_track);
share.add(0, Constants.MENU_SHARE_LINK, 0,
R.string.tracklist_share_link);
share.add(0, Constants.MENU_SHARE_GPX_FILE, 0,
R.string.tracklist_share_gpx_file);
share.add(0, Constants.MENU_SHARE_KML_FILE, 0,
R.string.tracklist_share_kml_file);
share.add(0, Constants.MENU_SHARE_CSV_FILE, 0,
R.string.tracklist_share_csv_file);
share.add(0, Constants.MENU_SHARE_TCX_FILE, 0,
R.string.tracklist_share_tcx_file);
SubMenu save = menu.addSubMenu(0,
Constants.MENU_WRITE_TO_SD_CARD, 0,
R.string.tracklist_write_to_sd);
save.add(0, Constants.MENU_SAVE_GPX_FILE, 0,
R.string.tracklist_save_as_gpx);
save.add(0, Constants.MENU_SAVE_KML_FILE, 0,
R.string.tracklist_save_as_kml);
save.add(0, Constants.MENU_SAVE_CSV_FILE, 0,
R.string.tracklist_save_as_csv);
save.add(0, Constants.MENU_SAVE_TCX_FILE, 0,
R.string.tracklist_save_as_tcx);
menu.add(0, Constants.MENU_CLEAR_MAP, 0,
R.string.tracklist_clear_map);
menu.add(0, Constants.MENU_DELETE, 0,
R.string.tracklist_delete_track);
}
}
};
@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
switch (item.getItemId()) {
case Constants.MENU_SEND_TO_GOOGLE:
SendActivity.sendToGoogle(this, dataHub.getSelectedTrackId(), false);
return true;
case Constants.MENU_SHARE_LINK:
SendActivity.sendToGoogle(this, dataHub.getSelectedTrackId(), true);
return true;
case Constants.MENU_SAVE_GPX_FILE:
case Constants.MENU_SAVE_KML_FILE:
case Constants.MENU_SAVE_CSV_FILE:
case Constants.MENU_SAVE_TCX_FILE:
case Constants.MENU_SHARE_GPX_FILE:
case Constants.MENU_SHARE_KML_FILE:
case Constants.MENU_SHARE_CSV_FILE:
case Constants.MENU_SHARE_TCX_FILE:
SaveActivity.handleExportTrackAction(this, dataHub.getSelectedTrackId(),
Constants.getActionFromMenuId(item.getItemId()));
return true;
default:
return super.onMenuItemSelected(featureId, item);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
myLocation = menu.add(0, Constants.MENU_MY_LOCATION, 0,
R.string.mylocation);
myLocation.setIcon(android.R.drawable.ic_menu_mylocation);
toggleLayers = menu.add(0, Constants.MENU_TOGGLE_LAYERS, 0,
R.string.switch_to_sat);
toggleLayers.setIcon(android.R.drawable.ic_menu_mapmode);
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
toggleLayers.setTitle(mapView.isSatellite() ?
R.string.switch_to_map : R.string.switch_to_sat);
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case Constants.MENU_MY_LOCATION: {
dataHub.forceUpdateLocation();
keepMyLocationVisible = true;
if (mapView.getZoomLevel() < 18) {
mapView.getController().setZoom(18);
}
return true;
}
case Constants.MENU_TOGGLE_LAYERS: {
mapView.setSatellite(!mapView.isSatellite());
return true;
}
}
return super.onOptionsItemSelected(item);
}
@Override
public void onClick(View v) {
if (v == messagePane) {
startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
} else if (v == optionsBtn) {
optionsBtn.performLongClick();
}
}
/**
* We want the pointer to become visible again in case of the next location
* update:
*/
@Override
public boolean onTouch(View view, MotionEvent event) {
if (keepMyLocationVisible && event.getAction() == MotionEvent.ACTION_MOVE) {
if (!locationIsVisible(currentLocation)) {
keepMyLocationVisible = false;
}
}
return false;
}
@Override
public void onProviderStateChange(ProviderState state) {
final int messageId;
final boolean isGpsDisabled;
switch (state) {
case DISABLED:
messageId = R.string.status_enable_gps;
isGpsDisabled = true;
break;
case NO_FIX:
case BAD_FIX:
messageId = R.string.wait_for_fix;
isGpsDisabled = false;
break;
case GOOD_FIX:
// Nothing to show.
messageId = -1;
isGpsDisabled = false;
break;
default:
throw new IllegalArgumentException("Unexpected state: " + state);
}
runOnUiThread(new Runnable() {
@Override
public void run() {
if (messageId != -1) {
messageText.setText(messageId);
messagePane.setVisibility(View.VISIBLE);
if (isGpsDisabled) {
// Give a warning about this state.
Toast.makeText(MapActivity.this,
R.string.error_no_gps_location_provider,
Toast.LENGTH_LONG).show();
// Make clicking take the user to the location settings.
messagePane.setOnClickListener(MapActivity.this);
} else {
messagePane.setOnClickListener(null);
}
} else {
messagePane.setVisibility(View.GONE);
}
screen.requestLayout();
}
});
}
@Override
public void onCurrentLocationChanged(Location location) {
currentLocation = location;
showCurrentLocation();
}
@Override
public void onCurrentHeadingChanged(double heading) {
synchronized (this) {
if (mapOverlay.setHeading((float) heading)) {
mapView.postInvalidate();
}
}
}
@Override
public void clearWaypoints() {
mapOverlay.clearWaypoints();
}
@Override
public void onNewWaypoint(Waypoint waypoint) {
if (LocationUtils.isValidLocation(waypoint.getLocation())) {
// TODO: Optimize locking inside addWaypoint
mapOverlay.addWaypoint(waypoint);
}
}
@Override
public void onNewWaypointsDone() {
mapView.postInvalidate();
}
@Override
public void clearTrackPoints() {
mapOverlay.clearPoints();
}
@Override
public void onNewTrackPoint(Location loc) {
mapOverlay.addLocation(loc);
}
@Override
public void onSegmentSplit() {
mapOverlay.addSegmentSplit();
}
@Override
public void onSampledOutTrackPoint(Location loc) {
// We don't care.
}
@Override
public void onNewTrackPointsDone() {
mapView.postInvalidate();
}
@Override
public boolean onUnitsChanged(boolean metric) {
// We don't care.
return false;
}
@Override
public boolean onReportSpeedChanged(boolean reportSpeed) {
// We don't care.
return false;
}
}
@@ -15,8 +15,10 @@
*/
package com.google.android.apps.mytracks;
import static com.google.android.apps.mytracks.Constants.TAG;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.util.MyTracksUtils;
import com.google.android.apps.mytracks.util.LocationUtils;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
@@ -33,6 +35,7 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
@@ -45,7 +48,7 @@ import java.util.concurrent.BlockingQueue;
*
* @author Leif Hendrik Wilden
*/
public class MyTracksOverlay extends Overlay {
public class MapOverlay extends Overlay {
private final Drawable[] arrows;
private final int arrowWidth, arrowHeight;
@@ -71,7 +74,7 @@ public class MyTracksOverlay extends Overlay {
private GeoPoint lastReferencePoint;
private Rect lastViewRect;
private Path lastPath;
/**
* Represents a pre-processed {@code Location} to speed up drawing.
* This class is more like a data object and doesn't provide accessors.
@@ -79,20 +82,31 @@ public class MyTracksOverlay extends Overlay {
private static class CachedLocation {
public final boolean valid;
public final GeoPoint geoPoint;
/**
* Constructor for an invalid cached location.
*/
public CachedLocation() {
this.valid = false;
this.geoPoint = null;
}
/**
* Constructor for a potentially valid cached location.
*/
public CachedLocation(Location location) {
this.valid = MyTracksUtils.isValidLocation(location);
this.geoPoint = valid ? MyTracksUtils.getGeoPoint(location) : null;
this.valid = LocationUtils.isValidLocation(location);
this.geoPoint = valid ? LocationUtils.getGeoPoint(location) : null;
}
};
public MyTracksOverlay(Context context) {
public MapOverlay(Context context) {
this.context = context;
this.waypoints = new ArrayList<Waypoint>();
this.points = new ArrayList<CachedLocation>(1024);
this.pendingPoints = new ArrayBlockingQueue<CachedLocation>(
MyTracksConstants.MAX_DISPLAYED_TRACK_POINTS, true);
Constants.MAX_DISPLAYED_TRACK_POINTS, true);
// TODO: Can we use a FrameAnimation or similar here rather
// than individual resources for each arrow direction?
@@ -153,7 +167,7 @@ public class MyTracksOverlay extends Overlay {
/**
* Add a location to the map overlay.
*
*
* NOTE: This method doesn't take ownership of the given location, so it is
* safe to reuse the same location while calling this method.
*
@@ -161,7 +175,18 @@ public class MyTracksOverlay extends Overlay {
*/
public void addLocation(Location l) {
// Queue up in the pending queue until it's merged with {@code #points}.
pendingPoints.offer(new CachedLocation(l));
if (!pendingPoints.offer(new CachedLocation(l))) {
Log.e(TAG, "Unable to add pending points");
}
}
/**
* Adds a segment split to the map overlay.
*/
public void addSegmentSplit() {
if (!pendingPoints.offer(new CachedLocation())) {
Log.e(TAG, "Unable to add pending points");
}
}
public void addWaypoint(Waypoint wpt) {
@@ -172,7 +197,7 @@ public class MyTracksOverlay extends Overlay {
}
}
}
public int getNumLocations() {
synchronized (points) {
return points.size() + pendingPoints.size();
@@ -185,7 +210,7 @@ public class MyTracksOverlay extends Overlay {
return waypoints.size();
}
}
public void clearPoints() {
synchronized (points) {
points.clear();
@@ -217,10 +242,15 @@ public class MyTracksOverlay extends Overlay {
// It's safe to keep projection within a single draw operation.
final Projection projection = getMapProjection(mapView);
if (projection == null) {
Log.w(TAG, "No projection, unable to draw");
return;
}
// Get the current viewing window.
if (trackDrawingEnabled) {
Rect viewRect = getMapViewRect(mapView);
// Draw the selected track:
drawTrack(canvas, projection, viewRect);
@@ -231,12 +261,12 @@ public class MyTracksOverlay extends Overlay {
// Draw the current location
drawMyLocation(canvas, projection);
}
// Visible for testing.
Projection getMapProjection(MapView mapView) {
return mapView.getProjection();
}
// Visible for testing.
Rect getMapViewRect(MapView mapView) {
int w = mapView.getLongitudeSpan();
@@ -245,12 +275,12 @@ public class MyTracksOverlay extends Overlay {
int cy = mapView.getMapCenter().getLatitudeE6();
return new Rect(cx - w / 2, cy - h / 2, cx + w / 2, cy + h / 2);
}
// Visible for testing.
Path newPath() {
return new Path();
}
// Visible for testing.
Path getLastPath() {
return lastPath;
@@ -260,7 +290,7 @@ public class MyTracksOverlay extends Overlay {
synchronized (waypoints) {;
for (Waypoint wpt : waypoints) {
Location loc = wpt.getLocation();
drawElement(canvas, projection, MyTracksUtils.getGeoPoint(loc),
drawElement(canvas, projection, LocationUtils.getGeoPoint(loc),
wpt.getType() == Waypoint.TYPE_STATISTICS ? statsMarker
: waypointMarker, -(markerWidth / 2) + 3, -markerHeight);
}
@@ -274,7 +304,7 @@ public class MyTracksOverlay extends Overlay {
}
Point pt = drawElement(canvas, projection,
MyTracksUtils.getGeoPoint(myLocation), arrows[lastHeading],
LocationUtils.getGeoPoint(myLocation), arrows[lastHeading],
-(arrowWidth / 2) + 3, -(arrowHeight / 2));
// Draw the error circle.
float radius = projection.metersToEquatorPixels(myLocation.getAccuracy());
@@ -286,9 +316,9 @@ public class MyTracksOverlay extends Overlay {
synchronized (points) {
// Merge the pending points with the list of cached locations.
final GeoPoint referencePoint = projection.fromPixels(0, 0);
int newPoints = pendingPoints.drainTo(points);
int newPoints = pendingPoints.drainTo(points);
boolean newProjection = !viewRect.equals(lastViewRect) ||
!referencePoint.equals(lastReferencePoint);
!referencePoint.equals(lastReferencePoint);
if (newPoints == 0 && lastPath != null && !newProjection) {
// No need to recreate path (same points and viewing area).
path = lastPath;
@@ -300,12 +330,12 @@ public class MyTracksOverlay extends Overlay {
} else if (lastPath != null && !newProjection) {
// Incremental update of the path, without repositioning the view.
path = lastPath;
updatePath(projection, viewRect, path, numPoints - newPoints);
updatePath(projection, viewRect, path, numPoints - newPoints);
} else {
// The view has changed so we have to start from scratch.
path = newPath();
path.incReserve(numPoints);
updatePath(projection, viewRect, path, 0);
updatePath(projection, viewRect, path, 0);
}
lastPath = path;
}
@@ -326,7 +356,7 @@ public class MyTracksOverlay extends Overlay {
}
}
}
// Draw the "Start" marker.
for (int i = 0; i < points.size(); ++i) {
if (points.get(i).valid) {
@@ -336,7 +366,7 @@ public class MyTracksOverlay extends Overlay {
}
}
}
private void updatePath(Projection projection, Rect viewRect, Path path,
int startLocationIdx) {
// Whether to start a new segment on new valid and visible point.
@@ -352,7 +382,7 @@ public class MyTracksOverlay extends Overlay {
newSegment = true;
continue;
}
final GeoPoint geoPoint = loc.geoPoint;
// Check if this breaks the existing segment.
boolean visible = alwaysVisible || viewRect.contains(
@@ -362,7 +392,7 @@ public class MyTracksOverlay extends Overlay {
newSegment = true;
}
lastVisible = visible;
// Either move to beginning of a new segment or continue the old one.
projection.toPixels(geoPoint, pt);
if (newSegment) {
@@ -373,7 +403,7 @@ public class MyTracksOverlay extends Overlay {
}
}
}
// Visible for testing.
Point drawElement(Canvas canvas, Projection projection, GeoPoint geoPoint,
Drawable element, int offsetX, int offsetY) {
@@ -423,7 +453,7 @@ public class MyTracksOverlay extends Overlay {
return false;
}
final Location tapLocation = MyTracksUtils.getLocation(p);
final Location tapLocation = LocationUtils.getLocation(p);
double dmin = Double.MAX_VALUE;
Waypoint waypoint = null;
synchronized (waypoints) {
@@ -442,8 +472,8 @@ public class MyTracksOverlay extends Overlay {
if (waypoint != null &&
dmin < 15000000 / Math.pow(2, mapView.getZoomLevel())) {
Intent intent = new Intent(context, MyTracksWaypointDetails.class);
intent.putExtra("waypointid", waypoint.getId());
Intent intent = new Intent(context, WaypointDetails.class);
intent.putExtra(WaypointDetails.WAYPOINT_ID_EXTRA, waypoint.getId());
context.startActivity(intent);
return true;
}
@@ -64,21 +64,21 @@ class MenuManager {
return true;
}
case R.id.menu_list_tracks: {
activity.startActivityForResult(new Intent(activity, MyTracksList.class),
MyTracksConstants.SHOW_TRACK);
activity.startActivityForResult(new Intent(activity, TrackList.class),
Constants.SHOW_TRACK);
return true;
}
case R.id.menu_list_markers: {
Intent startIntent = new Intent(activity, MyTracksWaypointsList.class);
Intent startIntent = new Intent(activity, WaypointsList.class);
startIntent.putExtra("trackid", activity.getSelectedTrackId());
activity.startActivityForResult(startIntent, MyTracksConstants.SHOW_WAYPOINT);
activity.startActivityForResult(startIntent, Constants.SHOW_WAYPOINT);
return true;
}
case R.id.menu_sensor_state: {
return startActivity(SensorStateActivity.class);
}
case R.id.menu_settings: {
return startActivity(MyTracksSettings.class);
return startActivity(SettingsActivity.class);
}
case R.id.menu_aggregated_stats: {
return startActivity(AggregatedStatsActivity.class);
@@ -86,8 +86,8 @@ class MenuManager {
case R.id.menu_help: {
return startActivity(WelcomeActivity.class);
}
case MyTracksConstants.MENU_CLEAR_MAP: {
activity.setSelectedTrackId(-1);
case Constants.MENU_CLEAR_MAP: {
activity.clearSelectedTrack();
return true;
}
}
@@ -1,12 +1,12 @@
/*
* Copyright 2011 Google Inc.
*
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -15,22 +15,20 @@
*/
package com.google.android.apps.mytracks;
import com.google.android.accounts.Account;
import static com.google.android.apps.mytracks.Constants.TAG;
import com.google.android.apps.mytracks.io.AuthManager;
import com.google.android.apps.mytracks.io.AuthManager.AuthCallback;
import com.google.android.apps.mytracks.io.AuthManagerFactory;
import com.google.android.apps.mytracks.io.MyMapsFactory;
import com.google.android.apps.mytracks.io.mymaps.MapsFacade;
import com.google.android.apps.mytracks.io.mymaps.MapsService;
import com.google.android.apps.mytracks.io.mymaps.MyMapsConstants;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.MenuItem;
import android.util.Log;
import android.view.View;
import android.view.View.OnCreateContextMenuListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
@@ -43,29 +41,15 @@ import android.widget.TextView;
* @author Rodrigo Damazio
*/
public class MyMapsList extends Activity implements MapsFacade.MapsListCallback {
private static final int MENU_OPEN = 0;
private static final int MENU_SHARE = 2;
private static final int GET_LOGIN = 1;
public static final String EXTRA_ACCOUNT_NAME = "accountName";
public static final String EXTRA_ACCOUNT_TYPE = "accountType";
private MapsFacade mapsClient;
private AuthManager auth;
private MyMapsListAdapter listAdapter;
private int contextPosition;
private final OnCreateContextMenuListener contextMenuListener =
new OnCreateContextMenuListener() {
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
AdapterView.AdapterContextMenuInfo info =
(AdapterView.AdapterContextMenuInfo) menuInfo;
contextPosition = info.position;
menu.add(0, MENU_OPEN, 0, R.string.open_map);
menu.add(0, MENU_SHARE, 0, R.string.share_map);
}
};
private final OnItemClickListener clickListener =
new OnItemClickListener() {
@Override
@@ -84,7 +68,7 @@ public class MyMapsList extends Activity implements MapsFacade.MapsListCallback
super.onCreate(icicle);
auth = AuthManagerFactory.getAuthManager(this, GET_LOGIN, null, true,
MapsService.getServiceName());
MyMapsConstants.SERVICE_NAME);
setContentView(R.layout.list);
@@ -92,7 +76,6 @@ public class MyMapsList extends Activity implements MapsFacade.MapsListCallback
ListView list = (ListView) findViewById(R.id.maplist);
list.setOnItemClickListener(clickListener);
list.setOnCreateContextMenuListener(contextMenuListener);
list.setAdapter(listAdapter);
startLogin();
@@ -102,30 +85,35 @@ public class MyMapsList extends Activity implements MapsFacade.MapsListCallback
// Starts in the UI thread.
// TODO fix this for non-froyo devices.
if (AuthManagerFactory.useModernAuthManager()) {
MyTracks.getInstance().getAccountChooser().chooseAccount(
MyMapsList.this,
new AccountChooser.AccountHandler() {
@Override
public void handleAccountSelected(Account account) {
// Account selection happens in the UI thread.
if (account != null) {
// The user did not quit and there was a valid google
// account.
doLogin(account);
}
}
});
Intent intent = getIntent();
String accountName = intent.getStringExtra(EXTRA_ACCOUNT_NAME);
String accountType = intent.getStringExtra(EXTRA_ACCOUNT_TYPE);
if (accountName == null || accountType == null) {
Log.e(TAG, "Didn't receive account name or type");
setResult(RESULT_CANCELED);
finish();
return;
}
doLogin(auth.getAccountObject(accountName, accountType));
} else {
doLogin(null);
}
}
private void doLogin(final Account account) {
private void doLogin(final Object account) {
// Starts in the UI thread.
auth.doLogin(new Runnable() {
public void run() {
auth.doLogin(new AuthCallback() {
@Override
public void onAuthResult(boolean success) {
if (!success) {
setResult(RESULT_CANCELED);
finish();
return;
}
// Runs in UI thread.
mapsClient = MyMapsFactory.newMapsClient(MyMapsList.this, auth);
mapsClient = new MapsFacade(MyMapsList.this, auth);
startLookup();
}
@@ -184,27 +172,4 @@ public class MyMapsList extends Activity implements MapsFacade.MapsListCallback
}
super.onActivityResult(requestCode, resultCode, data);
}
@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
switch (item.getItemId()) {
case MENU_OPEN:
clickListener.onItemClick(null, null, contextPosition, 0);
return true;
case MENU_SHARE:
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_SUBJECT,
getText(R.string.share_map_subject));
String[] listItem = (String[]) listAdapter.getMapListingArray(contextPosition);
shareIntent.putExtra(Intent.EXTRA_TEXT, String.format(
getText(R.string.share_map_body_format).toString(),
listItem[1],
MapsService.buildMapUrl(listItem[0])));
startActivity(Intent.createChooser(shareIntent,
getText(R.string.share_map).toString()));
return true;
}
return false;
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -15,9 +15,11 @@
*/
package com.google.android.apps.mytracks;
import static com.google.android.apps.mytracks.MyTracksConstants.TAG;
import static com.google.android.apps.mytracks.Constants.TAG;
import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.apps.mytracks.services.ITrackRecordingService;
import com.google.android.apps.mytracks.services.TrackRecordingServiceConnection;
import com.google.android.apps.mytracks.services.sensors.SensorUtils;
import com.google.android.maps.mytracks.R;
import com.google.protobuf.InvalidProtocolBufferException;
@@ -57,6 +59,11 @@ public class SensorStateActivity extends Activity {
}
};
/**
* Connection to the recording service.
*/
private TrackRecordingServiceConnection serviceConnection;
/**
* A task which will update the U/I.
*/
@@ -79,35 +86,45 @@ public class SensorStateActivity extends Activity {
setContentView(R.layout.sensor_state);
// TODO: Allow reading from sensors even if service is not running.
serviceConnection = new TrackRecordingServiceConnection(this, stateUpdater);
serviceConnection.bindIfRunning();
updateState();
}
@Override
protected void onResume() {
super.onResume();
serviceConnection.bindIfRunning();
timer = new Timer();
timer.schedule(new RefreshTask(), REFRESH_PERIOD_MS, REFRESH_PERIOD_MS);
}
@Override
protected void onPause() {
super.onPause();
timer.cancel();
timer.purge();
timer = null;
super.onPause();
}
@Override
protected void onDestroy() {
serviceConnection.unbind();
super.onDestroy();
}
protected void updateState() {
MyTracks mt = MyTracks.getInstance();
ITrackRecordingService service =
mt == null ? null : mt.getTrackRecordingService();
ITrackRecordingService service = serviceConnection.getServiceIfBound();
if (service == null) {
Log.d(MyTracksConstants.TAG, "Could not get track recording service.");
Log.d(Constants.TAG, "Could not get track recording service.");
updateSensorState(Sensor.SensorState.NONE);
updateSensorData(null);
return;
}
Sensor.SensorDataSet sds = null;
try {
byte[] buff = service.getSensorData();
@@ -116,9 +133,9 @@ public class SensorStateActivity extends Activity {
updateSensorData(sds);
}
} catch (RemoteException e) {
Log.e(MyTracksConstants.TAG, "Could not read sensor data.", e);
Log.e(Constants.TAG, "Could not read sensor data.", e);
} catch (InvalidProtocolBufferException e) {
Log.e(MyTracksConstants.TAG, "Could not read sensor data.", e);
Log.e(Constants.TAG, "Could not read sensor data.", e);
}
updateSensorData(sds);
@@ -126,7 +143,7 @@ public class SensorStateActivity extends Activity {
int i = service.getSensorState();
updateSensorState(Sensor.SensorState.valueOf(i));
} catch (RemoteException e) {
Log.e(MyTracksConstants.TAG, "Could not read sensor state.", e);
Log.e(Constants.TAG, "Could not read sensor state.", e);
updateSensorState(Sensor.SensorState.NONE);
}
}
@@ -153,8 +170,8 @@ public class SensorStateActivity extends Activity {
if (sds.hasPower() && sds.getPower().hasValue()
&& sds.getPower().getState() == Sensor.SensorState.SENDING) {
utils.setText(R.id.power_state_register,
Integer.toString(sds.getPower().getValue()));
utils.setText(R.id.power_state_register,
Integer.toString(sds.getPower().getValue()));
} else {
utils.setText(R.id.power_state_register,
SensorUtils.getStateAsString(
@@ -180,14 +197,14 @@ public class SensorStateActivity extends Activity {
if (sds.hasHeartRate() && sds.getHeartRate().hasValue()
&& sds.getHeartRate().getState() == Sensor.SensorState.SENDING) {
utils.setText(R.id.heart_rate_register,
Integer.toString(sds.getHeartRate().getValue()));
Integer.toString(sds.getHeartRate().getValue()));
} else {
utils.setText(R.id.heart_rate_register,
SensorUtils.getStateAsString(
sds.hasHeartRate()
? sds.getHeartRate().getState()
: Sensor.SensorState.NONE,
this));
utils.setText(R.id.heart_rate_register,
SensorUtils.getStateAsString(
sds.hasHeartRate()
? sds.getHeartRate().getState()
: Sensor.SensorState.NONE,
this));
}
}
}
@@ -15,31 +15,38 @@
*/
package com.google.android.apps.mytracks;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static com.google.android.apps.mytracks.Constants.TAG;
import com.google.android.apps.mytracks.io.backup.BackupActivityHelper;
import com.google.android.apps.mytracks.io.backup.BackupPreferencesListener;
import com.google.android.apps.mytracks.services.StatusAnnouncerFactory;
import com.google.android.apps.mytracks.services.sensors.ant.AntUtils;
import com.google.android.apps.mytracks.services.tasks.StatusAnnouncerFactory;
import com.google.android.apps.mytracks.util.ApiFeatures;
import com.google.android.apps.mytracks.util.BluetoothDeviceUtils;
import com.google.android.maps.mytracks.R;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.provider.Settings;
import android.util.Log;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* An activity that let's the user see and edit the settings.
@@ -47,28 +54,14 @@ import android.provider.Settings;
* @author Leif Hendrik Wilden
* @author Rodrigo Damazio
*/
public class MyTracksSettings extends PreferenceActivity {
public static final String SETTINGS_NAME = "MyTracksSettings";
/*
* Default values - keep in sync with those in preferences.xml.
*/
public static final int DEFAULT_AUTO_RESUME_TRACK_TIMEOUT = 10; // In min.
public static final int DEFAULT_ANNOUNCEMENT_FREQUENCY = -1;
public static final int DEFAULT_MAX_RECORDING_DISTANCE = 200;
public static final int DEFAULT_MIN_RECORDING_DISTANCE = 5;
public static final int DEFAULT_MIN_RECORDING_INTERVAL = 0;
public static final int DEFAULT_MIN_REQUIRED_ACCURACY = 200;
public static final int DEFAULT_SPLIT_FREQUENCY = 0;
public class SettingsActivity extends PreferenceActivity {
private BackupPreferencesListener backupListener;
private SharedPreferences preferences;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle) {
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
// The volume we want to control is the Text-To-Speech volume
@@ -79,7 +72,7 @@ public class MyTracksSettings extends PreferenceActivity {
// Tell it where to read/write preferences
PreferenceManager preferenceManager = getPreferenceManager();
preferenceManager.setSharedPreferencesName(SETTINGS_NAME);
preferenceManager.setSharedPreferencesName(Constants.SETTINGS_NAME);
preferenceManager.setSharedPreferencesMode(0);
// Set up automatic preferences backup
@@ -119,6 +112,16 @@ public class MyTracksSettings extends PreferenceActivity {
announcementFrequency.setSummary(
R.string.settings_not_available_summary);
}
// Hook up action for resetting all settings
Preference resetPreference = findPreference(getString(R.string.reset_key));
resetPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference arg0) {
onResetPreferencesClick();
return true;
}
});
}
private void customizeSensorOptionsPreferences() {
@@ -177,19 +180,24 @@ public class MyTracksSettings extends PreferenceActivity {
findPreference(getString(R.string.backup_to_sd_key));
Preference restoreNowPreference =
findPreference(getString(R.string.restore_from_sd_key));
Preference resetPreference = findPreference(getString(R.string.reset_key));
// If recording, disable backup/restore
// If recording, disable backup/restore/reset
// (we don't want to get to inconsistent states)
boolean recording =
preferences.getLong(getString(R.string.recording_track_key), -1) != -1;
backupNowPreference.setEnabled(!recording);
restoreNowPreference.setEnabled(!recording);
resetPreference.setEnabled(!recording);
backupNowPreference.setSummary(
recording ? R.string.settings_no_backup_while_recording
recording ? R.string.settings_not_while_recording
: R.string.settings_backup_to_sd_summary);
restoreNowPreference.setSummary(
recording ? R.string.settings_no_backup_while_recording
recording ? R.string.settings_not_while_recording
: R.string.settings_restore_from_sd_summary);
resetPreference.setSummary(
recording ? R.string.settings_not_while_recording
: R.string.settings_reset_summary);
// Add actions to the backup preferences
backupNowPreference.setOnPreferenceClickListener(
@@ -197,7 +205,7 @@ public class MyTracksSettings extends PreferenceActivity {
@Override
public boolean onPreferenceClick(Preference preference) {
BackupActivityHelper backupHelper =
new BackupActivityHelper(MyTracksSettings.this);
new BackupActivityHelper(SettingsActivity.this);
backupHelper.writeBackup();
return true;
}
@@ -207,7 +215,7 @@ public class MyTracksSettings extends PreferenceActivity {
@Override
public boolean onPreferenceClick(Preference preference) {
BackupActivityHelper backupHelper =
new BackupActivityHelper(MyTracksSettings.this);
new BackupActivityHelper(SettingsActivity.this);
backupHelper.restoreBackup();
return true;
}
@@ -224,7 +232,8 @@ public class MyTracksSettings extends PreferenceActivity {
private void updateSensorSettings(String sensorType) {
boolean usesBluetooth =
getString(R.string.zephyr_sensor_type).equals(sensorType);
getString(R.string.zephyr_sensor_type).equals(sensorType)
|| getString(R.string.polar_sensor_type).equals(sensorType);
findPreference(
getString(R.string.bluetooth_sensor_key)).setEnabled(usesBluetooth);
findPreference(
@@ -232,10 +241,14 @@ public class MyTracksSettings extends PreferenceActivity {
// Update the ANT+ sensors.
// TODO: Only enable on phones that have ANT+.
findPreference(getString(R.string.ant_heart_rate_sensor_id_key))
.setEnabled(getString(R.string.ant_sensor_type).equals(sensorType));
findPreference(getString(R.string.ant_srm_bridge_sensor_id_key))
.setEnabled(getString(R.string.srm_ant_bridge_sensor_type).equals(sensorType));
Preference antHrm = findPreference(getString(R.string.ant_heart_rate_sensor_id_key));
Preference antSrm = findPreference(getString(R.string.ant_srm_bridge_sensor_id_key));
if (antHrm != null && antSrm != null) {
antHrm
.setEnabled(getString(R.string.ant_sensor_type).equals(sensorType));
antSrm
.setEnabled(getString(R.string.srm_ant_bridge_sensor_type).equals(sensorType));
}
}
/**
@@ -254,9 +267,6 @@ public class MyTracksSettings extends PreferenceActivity {
final ListPreference minRequiredAccuracy =
(ListPreference) findPreference(
getString(R.string.min_required_accuracy_key));
final ListPreference splitFrequency =
(ListPreference) findPreference(
getString(R.string.split_frequency_key));
minRecordingDistance.setEntries(isMetric
? R.array.min_recording_distance_options
@@ -267,11 +277,20 @@ public class MyTracksSettings extends PreferenceActivity {
minRequiredAccuracy.setEntries(isMetric
? R.array.min_required_accuracy_options
: R.array.min_required_accuracy_options_ft);
splitFrequency.setEntries(isMetric
? R.array.split_frequency_options
: R.array.split_frequency_options_ft);
setTaskOptions(isMetric, R.string.announcement_frequency_key);
setTaskOptions(isMetric, R.string.split_frequency_key);
}
/**
* Set the user visible options for a periodic task.
*/
private void setTaskOptions(boolean isMetric, int listId) {
final ListPreference taskFrequency =
(ListPreference) findPreference(getString(listId));
taskFrequency.setEntries(isMetric
? R.array.task_frequency_options
: R.array.task_frequency_options_ft);
}
/**
* Configures preference actions related to bluetooth.
@@ -311,4 +330,53 @@ public class MyTracksSettings extends PreferenceActivity {
devicesPreference.setEntryValues(entryValuesArray);
devicesPreference.setEntries(entriesArray);
}
/** Callback for when user asks to reset all settings. */
private void onResetPreferencesClick() {
AlertDialog dialog = new AlertDialog.Builder(this)
.setCancelable(true)
.setTitle(R.string.settings_reset)
.setMessage(R.string.settings_reset_dialog_message)
.setPositiveButton(android.R.string.ok,
new OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int button) {
onResetPreferencesConfirmed();
}
})
.setNegativeButton(android.R.string.cancel, null)
.create();
dialog.show();
}
/** Callback for when user confirms resetting all settings. */
private void onResetPreferencesConfirmed() {
// Change preferences in a separate thread.
new Thread() {
@Override
public void run() {
Log.i(TAG, "Resetting all settings");
// Actually wipe preferences (and save synchronously).
preferences.edit().clear().commit();
// Give UI feedback in the UI thread.
runOnUiThread(new Runnable() {
@Override
public void run() {
// Give feedback to the user.
Toast.makeText(
SettingsActivity.this,
R.string.settings_reset_done,
Toast.LENGTH_SHORT).show();
// Restart the settings activity so all changes are loaded.
Intent intent = getIntent();
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
});
}
}.start();
}
}
@@ -15,26 +15,22 @@
*/
package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.MyTracksProviderUtilsImpl;
import static com.google.android.apps.mytracks.Constants.TAG;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.TracksColumns;
import com.google.android.apps.mytracks.content.WaypointsColumns;
import com.google.android.apps.mytracks.services.StatusAnnouncerFactory;
import com.google.android.apps.mytracks.content.TrackDataHub;
import com.google.android.apps.mytracks.content.TrackDataHub.ListenerDataType;
import com.google.android.apps.mytracks.content.TrackDataListener;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.services.ServiceUtils;
import com.google.android.apps.mytracks.services.tasks.StatusAnnouncerFactory;
import com.google.android.apps.mytracks.util.ApiFeatures;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.database.ContentObserver;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Menu;
@@ -42,68 +38,44 @@ import android.view.MenuItem;
import android.view.Window;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.EnumSet;
/**
* An activity that displays track statistics to the user.
*
* @author Sandor Dornbush
* @author Rodrigo Damazio
*/
public class StatsActivity extends Activity
implements OnSharedPreferenceChangeListener {
public class StatsActivity extends Activity implements TrackDataListener {
/**
* A runnable for posting to the UI thread. Will update the total time field.
*/
private final Runnable updateResults = new Runnable() {
public void run() {
if (dataHub != null && dataHub.isRecordingSelected()) {
utils.setTime(R.id.total_time_register,
System.currentTimeMillis() - startTime);
}
}
};
private StatsUtilities utils;
private UIUpdateThread thread;
private ContentObserver observer;
/**
* The id of the currently selected track.
*/
private long selectedTrackId = -1;
/**
* The id of the currently recording track.
*/
private long recordingTrackId = -1;
/**
* The start time of the selected track.
*/
private long startTime = -1;
/**
* True if distances should be displayed in metric units (from shared
* preferences).
*/
private boolean metricUnits = true;
/**
* True if pace should be displayed as dist/time (from shared preferences).
*/
private boolean displaySpeed = true;
/**
* true if activity has resumed and is on top
*/
private boolean activityOnTop = false;
/**
* If true, the statistics for the current segment are shown, otherwise
* for the full track.
*/
private boolean showCurrentSegment = false;
private MyTracksProviderUtils providerUtils;
/**
* A runnable for posting to the UI thread. Will update the total time field.
*/
private final Runnable updateResults = new Runnable() {
public void run() {
updateTotalTime();
}
};
private TrackDataHub dataHub;
private SharedPreferences preferences;
/**
* A thread that updates the total time field every second.
@@ -112,35 +84,33 @@ public class StatsActivity extends Activity
public UIUpdateThread() {
super();
Log.i(MyTracksConstants.TAG, "Created UI update thread");
Log.i(TAG, "Created UI update thread");
}
@Override
public void run() {
Log.i(MyTracksConstants.TAG, "Started UI update thread");
while (MyTracks.getInstance().isRecording()) {
long sleeptime = 1000;
Log.i(TAG, "Started UI update thread");
while (ServiceUtils.isRecording(StatsActivity.this, null, preferences)) {
runOnUiThread(updateResults);
try {
Thread.sleep(sleeptime);
Thread.sleep(1000L);
} catch (InterruptedException e) {
Log.w(MyTracksConstants.TAG,
"StatsActivity: Caught exception on sleep.", e);
Log.w(TAG, "StatsActivity: Caught exception on sleep.", e);
break;
}
}
Log.w(MyTracksConstants.TAG, "UIUpdateThread finished.");
Log.w(TAG, "UIUpdateThread finished.");
}
}
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
preferences = getSharedPreferences(Constants.SETTINGS_NAME, 0);
utils = new StatsUtilities(this);
providerUtils = new MyTracksProviderUtilsImpl(getContentResolver());
// The volume we want to control is the Text-To-Speech volume
int volumeStream =
new StatusAnnouncerFactory(ApiFeatures.getInstance()).getVolumeStream();
@@ -151,40 +121,10 @@ public class StatsActivity extends Activity
setContentView(R.layout.stats);
Handler contentHandler = new Handler();
observer = new ContentObserver(contentHandler) {
@Override
public void onChange(boolean selfChange) {
Log.d(MyTracksConstants.TAG, "StatsActivity: ContentObserver.onChange");
restoreStats();
super.onChange(selfChange);
}
};
ScrollView sv = ((ScrollView) findViewById(R.id.scrolly));
sv.setScrollBarStyle(ScrollView.SCROLLBARS_OUTSIDE_INSET);
SharedPreferences preferences =
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
if (preferences != null) {
selectedTrackId = preferences.getLong(
getString(R.string.selected_track_key), -1);
recordingTrackId = preferences.getLong(
getString(R.string.recording_track_key), -1);
metricUnits = preferences.getBoolean(
getString(R.string.metric_units_key), true);
displaySpeed =
preferences.getBoolean(getString(R.string.report_speed_key), true);
checkLiveTrack();
restoreStats();
showUnknownLocation();
preferences.registerOnSharedPreferenceChangeListener(this);
}
utils.setMetricUnits(metricUnits);
utils.setReportSpeed(displaySpeed);
utils.updateUnits();
utils.setSpeedLabel(R.id.speed_label, R.string.speed, R.string.pace_label);
utils.setSpeedLabels();
showUnknownLocation();
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
@@ -193,89 +133,76 @@ public class StatsActivity extends Activity
}
}
@Override
protected void onResume() {
super.onResume();
dataHub = TrackDataHub.getStartedInstance();
dataHub.registerTrackDataListener(this, EnumSet.of(
ListenerDataType.SELECTED_TRACK_CHANGED,
ListenerDataType.TRACK_UPDATES,
ListenerDataType.LOCATION_UPDATES,
ListenerDataType.DISPLAY_PREFERENCES));
}
@Override
protected void onPause() {
unregisterLocationListener();
dataHub.unregisterTrackDataListener(this);
dataHub = null;
if (thread != null) {
thread.interrupt();
thread = null;
}
getContentResolver().unregisterContentObserver(observer);
activityOnTop = false;
super.onPause();
super.onStop();
}
@Override
protected void onResume() {
activityOnTop = true;
checkLiveTrack();
restoreStats();
showUnknownLocation();
super.onResume();
public boolean onUnitsChanged(boolean metric) {
// Ignore if unchanged.
if (metric == utils.isMetricUnits()) return false;
utils.setMetricUnits(metric);
updateLabels();
return true; // Reload data
}
@Override
public void onSharedPreferenceChanged(
final SharedPreferences sharedPreferences, final String key) {
Log.d(MyTracksConstants.TAG,
"StatsActivity: onSharedPreferences changed " + key);
if (key != null) {
runOnUiThread(new Runnable() {
@Override
public void run() {
if (key.equals(getString(R.string.selected_track_key))) {
selectedTrackId =
sharedPreferences.getLong(
getString(R.string.selected_track_key),
-1);
checkLiveTrack();
restoreStats();
showUnknownLocation();
} else if (key.equals(getString(R.string.recording_track_key))) {
recordingTrackId =
sharedPreferences.getLong(
getString(R.string.recording_track_key),
-1);
checkLiveTrack();
restoreStats();
showUnknownLocation();
} else if (key.equals(getString(R.string.metric_units_key))) {
metricUnits =
sharedPreferences.getBoolean(
getString(R.string.metric_units_key), true);
utils.setMetricUnits(metricUnits);
utils.updateUnits();
restoreStats();
} else if (key.equals(getString(R.string.report_speed_key))) {
displaySpeed =
sharedPreferences.getBoolean(
getString(R.string.report_speed_key),
true);
utils.setReportSpeed(displaySpeed);
utils.updateUnits();
utils.setSpeedLabel(
R.id.speed_label, R.string.speed, R.string.pace_label);
Log.w(MyTracksConstants.TAG, "Setting speed labels");
utils.setSpeedLabels();
restoreStats();
}
}
});
}
public boolean onReportSpeedChanged(boolean displaySpeed) {
// Ignore if unchanged.
if (displaySpeed == utils.isReportSpeed()) return false;
utils.setReportSpeed(displaySpeed);
updateLabels();
return true; // Reload data
}
private void updateLabels() {
runOnUiThread(new Runnable() {
@Override
public void run() {
utils.updateUnits();
utils.setSpeedLabel(R.id.speed_label, R.string.speed, R.string.pace_label);
utils.setSpeedLabels();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuItem currentSegment = menu.add(0,
MyTracksConstants.MENU_CURRENT_SEGMENT, 0, R.string.current_segment);
Constants.MENU_CURRENT_SEGMENT, 0, R.string.current_segment);
currentSegment.setIcon(R.drawable.ic_menu_lastsegment);
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem item = menu.findItem(MyTracksConstants.MENU_CURRENT_SEGMENT);
MenuItem item = menu.findItem(Constants.MENU_CURRENT_SEGMENT);
if (item != null) {
item.setTitle(showCurrentSegment
? getString(R.string.current_track)
@@ -287,139 +214,14 @@ public class StatsActivity extends Activity
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MyTracksConstants.MENU_CURRENT_SEGMENT:
case Constants.MENU_CURRENT_SEGMENT:
showCurrentSegment = !showCurrentSegment;
restoreStats();
// TODO: Re-read only the data that interests us
return true;
}
return super.onOptionsItemSelected(item);
}
private final LocationListener locationListener = new LocationListener() {
@Override
public void onLocationChanged(Location l) {
if (selectedTrackIsRecording()) {
showLocation(l);
}
}
@Override
public void onProviderDisabled(String provider) {
// Do nothing
}
@Override
public void onProviderEnabled(String provider) {
// Do nothing
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// Do nothing
}
};
/**
* Registers to receive location updates from the GPS location provider.
*/
private void registerLocationListener() {
LocationManager locationManager =
(LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (locationManager != null) {
LocationProvider gpsProvider =
locationManager.getProvider(MyTracksConstants.GPS_PROVIDER);
if (gpsProvider == null) {
Toast.makeText(this, getString(R.string.error_no_gps_location_provider),
Toast.LENGTH_LONG).show();
return;
} else {
Log.d(MyTracksConstants.TAG, "StatsActivity: Using location provider "
+ gpsProvider.getName());
}
locationManager.requestLocationUpdates(gpsProvider.getName(),
0/*minTime*/, 0/*minDist*/, locationListener);
}
}
/**
* Unregisters all location listener.
*/
private void unregisterLocationListener() {
LocationManager locationManager =
(LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (locationManager != null) {
locationManager.removeUpdates(locationListener);
}
}
/**
* @return true if the selected track is the currently recording track
*/
private boolean selectedTrackIsRecording() {
return MyTracks.getInstance().isRecording()
&& selectedTrackId == recordingTrackId;
}
/**
* Reads values for selected tracks from provider and update the UI.
*/
private void restoreStats() {
if (selectedTrackId < 0) {
utils.setAllToUnknown();
return;
}
Track track = providerUtils.getTrack(selectedTrackId);
if (track == null || track.getStatistics() == null) {
utils.setAllToUnknown();
return;
}
startTime = track.getStatistics().getStartTime();
if (!selectedTrackIsRecording()) {
utils.setTime(R.id.total_time_register,
track.getStatistics().getTotalTime());
}
utils.setAllStats(track.getStatistics());
}
/**
* Checks if this activity needs to update live track data or not.
* If so, make sure that:
* a) a thread keeps updating the total time
* b) a location listener is registered
* c) a content observer is registered
* Otherwise unregister listeners, observers, and kill update thread.
*/
private void checkLiveTrack() {
final boolean isRecording = selectedTrackIsRecording();
final boolean startThread =
(thread == null) && isRecording && activityOnTop;
final boolean killThread =
(thread != null) && (!isRecording || !activityOnTop);
if (startThread) {
thread = new UIUpdateThread();
thread.start();
getContentResolver().registerContentObserver(
TracksColumns.CONTENT_URI, false, observer);
getContentResolver().registerContentObserver(
WaypointsColumns.CONTENT_URI, false, observer);
registerLocationListener();
} else if (killThread) {
thread.interrupt();
thread = null;
getContentResolver().unregisterContentObserver(observer);
unregisterLocationListener();
}
}
public void updateTotalTime() {
if (selectedTrackIsRecording()) {
utils.setTime(R.id.total_time_register,
System.currentTimeMillis() - startTime);
}
}
/**
* Updates the given location fields (latitude, longitude, altitude) and all
* other fields.
@@ -439,4 +241,125 @@ public class StatsActivity extends Activity
utils.setUnknown(R.id.longitude_register);
utils.setUnknown(R.id.speed_register);
}
@Override
public void onSelectedTrackChanged(Track track, boolean isRecording) {
/*
* Checks if this activity needs to update live track data or not.
* If so, make sure that:
* a) a thread keeps updating the total time
* b) a location listener is registered
* c) a content observer is registered
* Otherwise unregister listeners, observers, and kill update thread.
*/
final boolean startThread = (thread == null) && isRecording;
final boolean killThread = (thread != null) && (!isRecording);
if (startThread) {
thread = new UIUpdateThread();
thread.start();
} else if (killThread) {
thread.interrupt();
thread = null;
}
}
@Override
public void onCurrentLocationChanged(final Location loc) {
TrackDataHub localDataHub = dataHub;
if (localDataHub != null && localDataHub.isRecordingSelected()) {
runOnUiThread(new Runnable() {
@Override
public void run() {
if (loc != null) {
showLocation(loc);
} else {
showUnknownLocation();
}
}
});
}
}
@Override
public void onCurrentHeadingChanged(double heading) {
// We don't care.
}
@Override
public void onProviderStateChange(ProviderState state) {
switch (state) {
case DISABLED:
case NO_FIX:
runOnUiThread(new Runnable() {
@Override
public void run() {
showUnknownLocation();
}
});
break;
}
}
@Override
public void onTrackUpdated(final Track track) {
TrackDataHub localDataHub = dataHub;
final boolean recordingSelected = localDataHub != null && localDataHub.isRecordingSelected();
runOnUiThread(new Runnable() {
@Override
public void run() {
if (track == null || track.getStatistics() == null) {
utils.setAllToUnknown();
return;
}
startTime = track.getStatistics().getStartTime();
if (!recordingSelected) {
utils.setTime(R.id.total_time_register,
track.getStatistics().getTotalTime());
showUnknownLocation();
}
utils.setAllStats(track.getStatistics());
}
});
}
@Override
public void clearWaypoints() {
// We don't care.
}
@Override
public void onNewWaypoint(Waypoint wpt) {
// We don't care.
}
@Override
public void onNewWaypointsDone() {
// We don't care.
}
@Override
public void clearTrackPoints() {
// We don't care.
}
@Override
public void onNewTrackPoint(Location loc) {
// We don't care.
}
@Override
public void onSegmentSplit() {
// We don't care.
}
@Override
public void onSampledOutTrackPoint(Location loc) {
// We don't care.
}
@Override
public void onNewTrackPointsDone() {
// We don't care.
}
}
@@ -83,6 +83,8 @@ public class StatsUtilities {
public void setText(int id, double d, NumberFormat format) {
if (!Double.isNaN(d) && !Double.isInfinite(d)) {
setText(id, format.format(d));
} else {
setUnknown(id);
}
}
@@ -218,7 +220,7 @@ public class StatsUtilities {
setGrade(R.id.max_grade_register, maxGrade);
}
public void setAllStats(TripStatistics stats) {
public void setAllStats(TripStatistics stats) {
setTime(R.id.moving_time_register, stats.getMovingTime());
setDistance(R.id.total_distance_register, stats.getTotalDistance() / 1000);
setSpeed(R.id.average_speed_register, stats.getAverageSpeed() * 3.6);
@@ -235,7 +237,7 @@ public class StatsUtilities {
}
public void setSpeedLabel(int id, int speedString, int paceString) {
Log.w(MyTracksConstants.TAG, "Setting view " + id +
Log.w(Constants.TAG, "Setting view " + id +
" to " + reportSpeed +
" speed: " + speedString +
" pace: " + paceString);
@@ -243,7 +245,7 @@ public class StatsUtilities {
if (tv != null) {
tv.setText(reportSpeed ? speedString : paceString);
} else {
Log.w(MyTracksConstants.TAG, "Could not find id: " + id);
Log.w(Constants.TAG, "Could not find id: " + id);
}
}
@@ -37,7 +37,7 @@ import android.widget.EditText;
*
* @author Leif Hendrik Wilden
*/
public class MyTracksDetails extends Activity implements OnClickListener {
public class TrackDetails extends Activity implements OnClickListener {
/**
* The id of the track being edited (taken from bundle, "trackid")
@@ -56,7 +56,7 @@ public class MyTracksDetails extends Activity implements OnClickListener {
// Required extra when launching this intent:
trackId = getIntent().getLongExtra("trackid", -1);
if (trackId < 0) {
Log.d(MyTracksConstants.TAG,
Log.d(Constants.TAG,
"MyTracksDetails intent was launched w/o track id.");
finish();
return;
@@ -1,12 +1,12 @@
/*
* Copyright 2008 Google Inc.
*
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -16,6 +16,10 @@
package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.content.TracksColumns;
import com.google.android.apps.mytracks.io.file.SaveActivity;
import com.google.android.apps.mytracks.io.sendtogoogle.SendActivity;
import com.google.android.apps.mytracks.services.ServiceUtils;
import com.google.android.apps.mytracks.services.TrackRecordingServiceConnection;
import com.google.android.apps.mytracks.util.StringUtils;
import com.google.android.apps.mytracks.util.UnitConversions;
import com.google.android.maps.mytracks.R;
@@ -45,7 +49,7 @@ import android.widget.TextView;
*
* @author Leif Hendrik Wilden
*/
public class MyTracksList extends ListActivity
public class TrackList extends ListActivity
implements SharedPreferences.OnSharedPreferenceChangeListener,
View.OnClickListener {
@@ -70,45 +74,54 @@ public class MyTracksList extends ListActivity
AdapterView.AdapterContextMenuInfo info =
(AdapterView.AdapterContextMenuInfo) menuInfo;
contextPosition = info.position;
trackId = MyTracksList.this.listView.getAdapter().getItemId(
trackId = TrackList.this.listView.getAdapter().getItemId(
contextPosition);
menu.add(0, MyTracksConstants.MENU_SHOW, 0,
menu.add(0, Constants.MENU_SHOW, 0,
R.string.tracklist_show_track);
menu.add(0, MyTracksConstants.MENU_EDIT, 0,
menu.add(0, Constants.MENU_EDIT, 0,
R.string.tracklist_edit_track);
if (!MyTracks.getInstance().isRecording()
|| trackId != recordingTrackId) {
menu.add(0, MyTracksConstants.MENU_SEND_TO_GOOGLE, 0,
if (!isRecording() || trackId != recordingTrackId) {
menu.add(0, Constants.MENU_SEND_TO_GOOGLE, 0,
R.string.tracklist_send_to_google);
SubMenu share = menu.addSubMenu(0, MyTracksConstants.MENU_SHARE, 0,
SubMenu share = menu.addSubMenu(0, Constants.MENU_SHARE, 0,
R.string.tracklist_share_track);
share.add(0, MyTracksConstants.MENU_SHARE_LINK, 0,
share.add(0, Constants.MENU_SHARE_LINK, 0,
R.string.tracklist_share_link);
share.add(0, MyTracksConstants.MENU_SHARE_GPX_FILE, 0,
share.add(0, Constants.MENU_SHARE_GPX_FILE, 0,
R.string.tracklist_share_gpx_file);
share.add(0, MyTracksConstants.MENU_SHARE_KML_FILE, 0,
share.add(0, Constants.MENU_SHARE_KML_FILE, 0,
R.string.tracklist_share_kml_file);
share.add(0, MyTracksConstants.MENU_SHARE_CSV_FILE, 0,
share.add(0, Constants.MENU_SHARE_CSV_FILE, 0,
R.string.tracklist_share_csv_file);
share.add(0, MyTracksConstants.MENU_SHARE_TCX_FILE, 0,
share.add(0, Constants.MENU_SHARE_TCX_FILE, 0,
R.string.tracklist_share_tcx_file);
SubMenu save = menu.addSubMenu(0,
MyTracksConstants.MENU_WRITE_TO_SD_CARD, 0,
Constants.MENU_WRITE_TO_SD_CARD, 0,
R.string.tracklist_write_to_sd);
save.add(0, MyTracksConstants.MENU_SAVE_GPX_FILE, 0,
save.add(0, Constants.MENU_SAVE_GPX_FILE, 0,
R.string.tracklist_save_as_gpx);
save.add(0, MyTracksConstants.MENU_SAVE_KML_FILE, 0,
save.add(0, Constants.MENU_SAVE_KML_FILE, 0,
R.string.tracklist_save_as_kml);
save.add(0, MyTracksConstants.MENU_SAVE_CSV_FILE, 0,
save.add(0, Constants.MENU_SAVE_CSV_FILE, 0,
R.string.tracklist_save_as_csv);
save.add(0, MyTracksConstants.MENU_SAVE_TCX_FILE, 0,
save.add(0, Constants.MENU_SAVE_TCX_FILE, 0,
R.string.tracklist_save_as_tcx);
menu.add(0, MyTracksConstants.MENU_DELETE, 0,
menu.add(0, Constants.MENU_DELETE, 0,
R.string.tracklist_delete_track);
}
}
};
private final Runnable serviceBindingChanged = new Runnable() {
@Override
public void run() {
updateButtonsEnabled();
}
};
private TrackRecordingServiceConnection serviceConnection;
private SharedPreferences preferences;
@Override
public void onSharedPreferenceChanged(
SharedPreferences sharedPreferences, String key) {
@@ -132,45 +145,59 @@ public class MyTracksList extends ListActivity
protected void onListItemClick(ListView l, View v, int position, long id) {
Intent result = new Intent();
result.putExtra("trackid", id);
setResult(MyTracksConstants.SHOW_TRACK, result);
setResult(Constants.SHOW_TRACK, result);
finish();
}
@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
if (!super.onMenuItemSelected(featureId, item)) {
switch (item.getItemId()) {
case MyTracksConstants.MENU_SHOW: {
onListItemClick(null, null, 0, trackId);
return true;
}
case MyTracksConstants.MENU_EDIT: {
Intent intent = new Intent(this, MyTracksDetails.class);
intent.putExtra("trackid", trackId);
startActivity(intent);
return true;
}
case MyTracksConstants.MENU_SHARE:
case MyTracksConstants.MENU_WRITE_TO_SD_CARD:
return false;
default: {
Intent result = new Intent();
result.putExtra("trackid", trackId);
setResult(
MyTracksConstants.getActionFromMenuId(item.getItemId()), result);
finish();
return true;
}
switch (item.getItemId()) {
case Constants.MENU_SHOW: {
onListItemClick(null, null, 0, trackId);
return true;
}
case Constants.MENU_EDIT: {
Intent intent = new Intent(this, TrackDetails.class);
intent.putExtra("trackid", trackId);
startActivity(intent);
return true;
}
case Constants.MENU_SHARE:
case Constants.MENU_WRITE_TO_SD_CARD:
return false;
case Constants.MENU_SEND_TO_GOOGLE:
SendActivity.sendToGoogle(this, trackId, false);
return true;
case Constants.MENU_SHARE_LINK:
SendActivity.sendToGoogle(this, trackId, true);
return true;
case Constants.MENU_SAVE_GPX_FILE:
case Constants.MENU_SAVE_KML_FILE:
case Constants.MENU_SAVE_CSV_FILE:
case Constants.MENU_SAVE_TCX_FILE:
case Constants.MENU_SHARE_GPX_FILE:
case Constants.MENU_SHARE_KML_FILE:
case Constants.MENU_SHARE_CSV_FILE:
case Constants.MENU_SHARE_TCX_FILE:
SaveActivity.handleExportTrackAction(this, trackId,
Constants.getActionFromMenuId(item.getItemId()));
return true;
default: {
Intent result = new Intent();
result.putExtra("trackid", trackId);
setResult(
Constants.getActionFromMenuId(item.getItemId()), result);
finish();
return true;
}
}
return false;
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.tracklist_btn_delete_all: {
Handler h = new MyTracksDeleteAllTracks(this, null);
Handler h = new DeleteAllTracks(this, null);
h.handleMessage(null);
break;
}
@@ -197,12 +224,19 @@ public class MyTracksList extends ListActivity
listView = getListView();
listView.setOnCreateContextMenuListener(contextMenuListener);
findViewById(R.id.tracklist_btn_delete_all).setOnClickListener(this);
findViewById(R.id.tracklist_btn_export_all).setOnClickListener(this);
preferences = getSharedPreferences(Constants.SETTINGS_NAME, 0);
serviceConnection = new TrackRecordingServiceConnection(this, serviceBindingChanged);
View deleteAll = findViewById(R.id.tracklist_btn_delete_all);
deleteAll.setOnClickListener(this);
View exportAll = findViewById(R.id.tracklist_btn_export_all);
exportAll.setOnClickListener(this);
updateButtonsEnabled();
findViewById(R.id.tracklist_btn_import_all).setOnClickListener(this);
SharedPreferences preferences =
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
preferences.registerOnSharedPreferenceChangeListener(this);
metricUnits =
preferences.getBoolean(getString(R.string.metric_units_key), true);
@@ -215,6 +249,29 @@ public class MyTracksList extends ListActivity
setListAdapter();
}
@Override
protected void onStart() {
super.onStart();
serviceConnection.bindIfRunning();
}
@Override
protected void onDestroy() {
serviceConnection.unbind();
super.onDestroy();
}
private void updateButtonsEnabled() {
View deleteAll = findViewById(R.id.tracklist_btn_delete_all);
View exportAll = findViewById(R.id.tracklist_btn_export_all);
boolean notRecording = !isRecording();
deleteAll.setEnabled(notRecording);
exportAll.setEnabled(notRecording);
}
private void setListAdapter() {
// Get a cursor with all tracks
SimpleCursorAdapter adapter = new SimpleCursorAdapter(
@@ -278,4 +335,8 @@ public class MyTracksList extends ListActivity
});
setListAdapter(adapter);
}
private boolean isRecording() {
return ServiceUtils.isRecording(TrackList.this, serviceConnection.getServiceIfBound(), preferences);
}
}
@@ -39,7 +39,7 @@ import android.widget.ImageView;
*
* @author Leif Hendrik Wilden
*/
public class MyTracksWaypointDetails extends Activity
public class WaypointDetails extends Activity
implements OnClickListener {
public static final String WAYPOINT_ID_EXTRA = "com.google.android.apps.mytracks.WAYPOINT_ID";
@@ -65,7 +65,7 @@ public class MyTracksWaypointDetails extends Activity
utils = new StatsUtilities(this);
SharedPreferences preferences =
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
getSharedPreferences(Constants.SETTINGS_NAME, 0);
if (preferences != null) {
boolean useMetric =
preferences.getBoolean(getString(R.string.metric_units_key), true);
@@ -82,7 +82,7 @@ public class MyTracksWaypointDetails extends Activity
// Required extra when launching this intent:
waypointId = getIntent().getLongExtra(WAYPOINT_ID_EXTRA, -1);
if (waypointId < 0) {
Log.d(MyTracksConstants.TAG,
Log.d(Constants.TAG,
"MyTracksWaypointsDetails intent was launched w/o waypoint id.");
finish();
return;
@@ -1,12 +1,12 @@
/*
* Copyright 2009 Google Inc.
*
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -15,10 +15,14 @@
*/
package com.google.android.apps.mytracks;
import static com.google.android.apps.mytracks.Constants.TAG;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.content.WaypointCreationRequest;
import com.google.android.apps.mytracks.content.WaypointsColumns;
import com.google.android.apps.mytracks.services.ITrackRecordingService;
import com.google.android.apps.mytracks.services.TrackRecordingServiceConnection;
import com.google.android.apps.mytracks.util.StringUtils;
import com.google.android.maps.mytracks.R;
@@ -43,24 +47,25 @@ import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
import android.widget.Toast;
/**
* Activity which shows the list of waypoints in a track.
*
* @author Leif Hendrik Wilden
*/
public class MyTracksWaypointsList extends ListActivity
public class WaypointsList extends ListActivity
implements View.OnClickListener {
private int contextPosition = -1;
private long trackId = -1;
private long waypointId = -1;
private long selectedWaypointId = -1;
private ListView listView = null;
private Button insertWaypointButton = null;
private Button insertStatisticsButton = null;
private long recordingTrackId = -1;
private long selectedTrackId = -1;
private MyTracksProviderUtils providerUtils;
private TrackRecordingServiceConnection serviceConnection;
private Cursor waypointsCursor = null;
@@ -72,17 +77,20 @@ public class MyTracksWaypointsList extends ListActivity
AdapterView.AdapterContextMenuInfo info =
(AdapterView.AdapterContextMenuInfo) menuInfo;
contextPosition = info.position;
waypointId = MyTracksWaypointsList.this.listView.getAdapter()
selectedWaypointId = WaypointsList.this.listView.getAdapter()
.getItemId(contextPosition);
int type = providerUtils.getWaypoint(info.id).getType();
menu.add(0, MyTracksConstants.MENU_SHOW, 0,
R.string.waypointslist_show_waypoint);
menu.add(0, MyTracksConstants.MENU_EDIT, 0,
R.string.waypointslist_edit_waypoint);
menu.add(0, MyTracksConstants.MENU_DELETE, 0,
R.string.waypointslist_delete_waypoint).setEnabled(
recordingTrackId < 0 || type == Waypoint.TYPE_WAYPOINT ||
info.id != providerUtils.getLastWaypointId(recordingTrackId));
Waypoint waypoint = providerUtils.getWaypoint(info.id);
if (waypoint != null) {
int type = waypoint.getType();
menu.add(0, Constants.MENU_SHOW, 0,
R.string.waypointslist_show_waypoint);
menu.add(0, Constants.MENU_EDIT, 0,
R.string.waypointslist_edit_waypoint);
menu.add(0, Constants.MENU_DELETE, 0,
R.string.waypointslist_delete_waypoint).setEnabled(
recordingTrackId < 0 || type == Waypoint.TYPE_WAYPOINT ||
info.id != providerUtils.getLastWaypointId(recordingTrackId));
}
}
};
@@ -90,8 +98,8 @@ public class MyTracksWaypointsList extends ListActivity
protected void onListItemClick(ListView l, View v, int position, long id) {
Intent result = new Intent();
result.putExtra("trackid", trackId);
result.putExtra(MyTracksWaypointDetails.WAYPOINT_ID_EXTRA, id);
setResult(MyTracksConstants.EDIT_WAYPOINT, result);
result.putExtra(WaypointDetails.WAYPOINT_ID_EXTRA, id);
setResult(Constants.EDIT_WAYPOINT, result);
finish();
}
@@ -99,19 +107,19 @@ public class MyTracksWaypointsList extends ListActivity
public boolean onMenuItemSelected(int featureId, MenuItem item) {
if (!super.onMenuItemSelected(featureId, item)) {
switch (item.getItemId()) {
case MyTracksConstants.MENU_SHOW: {
onListItemClick(null, null, 0, waypointId);
case Constants.MENU_SHOW: {
onListItemClick(null, null, 0, selectedWaypointId);
return true;
}
case MyTracksConstants.MENU_EDIT: {
Intent intent = new Intent(this, MyTracksWaypointDetails.class);
case Constants.MENU_EDIT: {
Intent intent = new Intent(this, WaypointDetails.class);
intent.putExtra("trackid", trackId);
intent.putExtra(MyTracksWaypointDetails.WAYPOINT_ID_EXTRA, waypointId);
intent.putExtra(WaypointDetails.WAYPOINT_ID_EXTRA, selectedWaypointId);
startActivity(intent);
return true;
}
case MyTracksConstants.MENU_DELETE: {
deleteWaypoint(waypointId);
case Constants.MENU_DELETE: {
deleteWaypoint(selectedWaypointId);
}
}
}
@@ -123,6 +131,7 @@ public class MyTracksWaypointsList extends ListActivity
super.onCreate(savedInstanceState);
providerUtils = MyTracksProviderUtils.Factory.get(this);
serviceConnection = new TrackRecordingServiceConnection(this, null);
// We don't need a window title bar:
requestWindowFeature(Window.FEATURE_NO_TITLE);
@@ -139,7 +148,10 @@ public class MyTracksWaypointsList extends ListActivity
(Button) findViewById(R.id.waypointslist_btn_insert_statistics);
insertStatisticsButton.setOnClickListener(this);
SharedPreferences preferences =
getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
getSharedPreferences(Constants.SETTINGS_NAME, 0);
// TODO: Get rid of selected and recording track IDs
long selectedTrackId = -1;
if (preferences != null) {
recordingTrackId =
preferences.getLong(getString(R.string.recording_track_key), -1);
@@ -157,7 +169,7 @@ public class MyTracksWaypointsList extends ListActivity
trackId = -1;
}
final long firstWaypointId = providerUtils.getFirstWaypointId(trackId);
final long firstWaypointId = providerUtils.getFirstWaypointId(trackId);
waypointsCursor = getContentResolver().query(
WaypointsColumns.CONTENT_URI, null,
WaypointsColumns.TRACKID + "=" + trackId + " AND "
@@ -166,6 +178,20 @@ public class MyTracksWaypointsList extends ListActivity
setListAdapter();
}
@Override
protected void onResume() {
super.onResume();
serviceConnection.bindIfRunning();
}
@Override
protected void onDestroy() {
serviceConnection.unbind();
super.onDestroy();
}
@Override
public void onClick(View v) {
WaypointCreationRequest request;
@@ -179,25 +205,40 @@ public class MyTracksWaypointsList extends ListActivity
default:
return;
}
long id;
try {
id = MyTracks.getInstance().insertWaypoint(request);
} catch (RemoteException e) {
Log.e(MyTracksConstants.TAG, "Cannot insert marker.", e);
return;
} catch (IllegalStateException e) {
Log.e(MyTracksConstants.TAG, "Cannot insert marker.", e);
return;
}
long id = insertWaypoint(request);
if (id < 0) {
Log.e(MyTracksConstants.TAG, "Failed to insert marker.");
Toast.makeText(this, R.string.error_unable_to_insert_marker,
Toast.LENGTH_LONG).show();
Log.e(Constants.TAG, "Failed to insert marker.");
return;
}
Intent intent = new Intent(this, MyTracksWaypointDetails.class);
intent.putExtra(MyTracksWaypointDetails.WAYPOINT_ID_EXTRA, id);
Intent intent = new Intent(this, WaypointDetails.class);
intent.putExtra(WaypointDetails.WAYPOINT_ID_EXTRA, id);
startActivity(intent);
}
private long insertWaypoint(WaypointCreationRequest request) {
try {
ITrackRecordingService trackRecordingService = serviceConnection.getServiceIfBound();
if (trackRecordingService != null) {
long waypointId = trackRecordingService.insertWaypoint(request);
if (waypointId >= 0) {
Toast.makeText(this, R.string.status_statistics_inserted,
Toast.LENGTH_LONG).show();
return waypointId;
}
} else {
Log.e(TAG, "Not connected to service, not inserting waypoint");
}
} catch (RemoteException e) {
Log.e(Constants.TAG, "Cannot insert marker.", e);
} catch (IllegalStateException e) {
Log.e(Constants.TAG, "Cannot insert marker.", e);
}
return -1;
}
private void setListAdapter() {
// Get a cursor with all tracks
SimpleCursorAdapter adapter = new SimpleCursorAdapter(
@@ -207,7 +248,7 @@ public class MyTracksWaypointsList extends ListActivity
new String[] { WaypointsColumns.NAME, WaypointsColumns.TIME,
WaypointsColumns.CATEGORY, WaypointsColumns.TYPE },
new int[] { R.id.waypointslist_item_name,
R.id.waypointslist_item_time,
R.id.waypointslist_item_time,
R.id.waypointslist_item_category,
R.id.waypointslist_item_icon });
@@ -217,7 +258,7 @@ public class MyTracksWaypointsList extends ListActivity
waypointsCursor.getColumnIndexOrThrow(WaypointsColumns.TYPE);
adapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
@Override
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
if (columnIndex == timeIdx) {
long time = cursor.getLong(timeIdx);
TextView textView = (TextView) view;
@@ -256,17 +297,17 @@ public class MyTracksWaypointsList extends ListActivity
builder.setPositiveButton(getString(R.string.yes),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int i) {
dialog.dismiss();
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
providerUtils.deleteWaypoint(waypointId,
new StringUtils(MyTracksWaypointsList.this));
new StringUtils(WaypointsList.this));
}
});
builder.setNegativeButton(getString(R.string.no),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int i) {
dialog.dismiss();
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
dialog = builder.create();
@@ -15,7 +15,7 @@
*/
package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.util.MyTracksUtils;
import com.google.android.apps.mytracks.util.SystemUtils;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
@@ -82,6 +82,6 @@ public class WelcomeActivity extends Activity {
AlertDialog dialog = builder.create();
dialog.show();
((TextView) dialog.findViewById(R.id.about_version_register)).
setText(MyTracksUtils.getMyTracksVersion(this));
setText(SystemUtils.getMyTracksVersion(this));
}
}
@@ -0,0 +1,265 @@
package com.google.android.apps.mytracks.content;
import static com.google.android.apps.mytracks.Constants.TAG;
import com.google.android.apps.mytracks.content.TrackDataHub.ListenerDataType;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.database.ContentObserver;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import java.util.EnumSet;
import java.util.Set;
/**
* External data source manager, which converts system-level events into My Tracks data events.
*
* @author Rodrigo Damazio
*/
class DataSourceManager {
/** Single interface for receiving system events that were registered for. */
interface DataSourceListener {
void notifyTrackUpdated();
void notifyWaypointUpdated();
void notifyPointsUpdated();
void notifyPreferenceChanged(String key);
void notifyLocationProviderEnabled(boolean enabled);
void notifyLocationProviderAvailable(boolean available);
void notifyLocationChanged(Location loc);
void notifyHeadingChanged(float heading);
}
private final DataSourceListener listener;
/** Observer for when the tracks table is updated. */
private class TrackObserver extends ContentObserver {
public TrackObserver() {
super(contentHandler);
}
@Override
public void onChange(boolean selfChange) {
listener.notifyTrackUpdated();
}
}
/** Observer for when the waypoints table is updated. */
private class WaypointObserver extends ContentObserver {
public WaypointObserver() {
super(contentHandler);
}
@Override
public void onChange(boolean selfChange) {
listener.notifyWaypointUpdated();
}
}
/** Observer for when the points table is updated. */
private class PointObserver extends ContentObserver {
public PointObserver() {
super(contentHandler);
}
@Override
public void onChange(boolean selfChange) {
listener.notifyPointsUpdated();
}
}
/** Listener for when preferences change. */
private class HubSharedPreferenceListener implements OnSharedPreferenceChangeListener {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
listener.notifyPreferenceChanged(key);
}
}
/** Listener for the current location (independent from track data). */
private class CurrentLocationListener implements
LocationListener {
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
if (!LocationManager.GPS_PROVIDER.equals(provider)) return;
listener.notifyLocationProviderAvailable(status == LocationProvider.AVAILABLE);
}
@Override
public void onProviderEnabled(String provider) {
if (!LocationManager.GPS_PROVIDER.equals(provider)) return;
listener.notifyLocationProviderEnabled(true);
}
@Override
public void onProviderDisabled(String provider) {
if (!LocationManager.GPS_PROVIDER.equals(provider)) return;
listener.notifyLocationProviderEnabled(false);
}
@Override
public void onLocationChanged(Location location) {
listener.notifyLocationChanged(location);
}
}
/** Listener for compass readings. */
private class CompassListener implements
SensorEventListener {
@Override
public void onSensorChanged(SensorEvent event) {
listener.notifyHeadingChanged(event.values[0]);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// Do nothing
}
}
/** Wrapper for registering internal listeners. */
private final DataSourcesWrapper dataSources;
// Internal listeners (to receive data from the system)
private final Set<ListenerDataType> registeredListeners =
EnumSet.noneOf(ListenerDataType.class);
private final Handler contentHandler;
private final ContentObserver pointObserver;
private final ContentObserver waypointObserver;
private final ContentObserver trackObserver;
private final LocationListener locationListener;
private final OnSharedPreferenceChangeListener preferenceListener;
private final SensorEventListener compassListener;
DataSourceManager(DataSourceListener listener, DataSourcesWrapper dataSources) {
this.listener = listener;
this.dataSources = dataSources;
contentHandler = new Handler();
pointObserver = new PointObserver();
waypointObserver = new WaypointObserver();
trackObserver = new TrackObserver();
compassListener = new CompassListener();
locationListener = new CurrentLocationListener();
preferenceListener = new HubSharedPreferenceListener();
}
/** Updates the internal (sensor, position, etc) listeners. */
void updateAllListeners(EnumSet<ListenerDataType> externallyNeededListeners) {
EnumSet<ListenerDataType> neededListeners = EnumSet.copyOf(externallyNeededListeners);
// Special case - map sampled-out points type to points type since they
// correspond to the same internal listener.
if (neededListeners.contains(ListenerDataType.SAMPLED_OUT_POINT_UPDATES)) {
neededListeners.remove(ListenerDataType.SAMPLED_OUT_POINT_UPDATES);
neededListeners.add(ListenerDataType.POINT_UPDATES);
}
Log.d(TAG, "Updating internal listeners to types " + neededListeners);
// Unnecessary = registered - needed
Set<ListenerDataType> unnecessaryListeners = EnumSet.copyOf(registeredListeners);
unnecessaryListeners.removeAll(neededListeners);
// Missing = needed - registered
Set<ListenerDataType> missingListeners = EnumSet.copyOf(neededListeners);
missingListeners.removeAll(registeredListeners);
// Remove all unnecessary listeners.
for (ListenerDataType type : unnecessaryListeners) {
unregisterListener(type);
}
// Add all missing listeners.
for (ListenerDataType type : missingListeners) {
registerListener(type);
}
// Now all needed types are registered.
registeredListeners.clear();
registeredListeners.addAll(neededListeners);
}
private void registerListener(ListenerDataType type) {
switch (type) {
case COMPASS_UPDATES: {
// Listen to compass
Sensor compass = dataSources.getSensor(Sensor.TYPE_ORIENTATION);
if (compass != null) {
Log.d(TAG, "TrackDataHub: Now registering sensor listener.");
dataSources.registerSensorListener(compassListener, compass, SensorManager.SENSOR_DELAY_UI);
}
break;
}
case LOCATION_UPDATES:
dataSources.requestLocationUpdates(locationListener);
break;
case POINT_UPDATES:
dataSources.registerContentObserver(
TrackPointsColumns.CONTENT_URI, false, pointObserver);
break;
case TRACK_UPDATES:
dataSources.registerContentObserver(TracksColumns.CONTENT_URI, false, trackObserver);
break;
case WAYPOINT_UPDATES:
dataSources.registerContentObserver(
WaypointsColumns.CONTENT_URI, false, waypointObserver);
break;
case DISPLAY_PREFERENCES:
dataSources.registerOnSharedPreferenceChangeListener(preferenceListener);
break;
case SAMPLED_OUT_POINT_UPDATES:
throw new IllegalArgumentException("Should have been mapped to point updates");
}
}
private void unregisterListener(ListenerDataType type) {
switch (type) {
case COMPASS_UPDATES:
dataSources.unregisterSensorListener(compassListener);
break;
case LOCATION_UPDATES:
dataSources.removeLocationUpdates(locationListener);
break;
case POINT_UPDATES:
dataSources.unregisterContentObserver(pointObserver);
break;
case TRACK_UPDATES:
dataSources.unregisterContentObserver(trackObserver);
break;
case WAYPOINT_UPDATES:
dataSources.unregisterContentObserver(waypointObserver);
break;
case DISPLAY_PREFERENCES:
dataSources.unregisterOnSharedPreferenceChangeListener(preferenceListener);
break;
case SAMPLED_OUT_POINT_UPDATES:
throw new IllegalArgumentException("Should have been mapped to point updates");
}
}
/** Unregisters all internal (sensor, position, etc.) listeners. */
void unregisterAllListeners() {
dataSources.removeLocationUpdates(locationListener);
dataSources.unregisterSensorListener(compassListener);
dataSources.unregisterContentObserver(trackObserver);
dataSources.unregisterContentObserver(waypointObserver);
dataSources.unregisterContentObserver(pointObserver);
dataSources.unregisterOnSharedPreferenceChangeListener(preferenceListener);
}
}
@@ -0,0 +1,54 @@
/*
* Copyright 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.content;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.database.ContentObserver;
import android.hardware.Sensor;
import android.hardware.SensorEventListener;
import android.location.Location;
import android.location.LocationListener;
import android.net.Uri;
/**
* Interface for abstracting registration of external data source listeners.
*
* @author Rodrigo Damazio
*/
interface DataSourcesWrapper {
// Preferences
void registerOnSharedPreferenceChangeListener(
OnSharedPreferenceChangeListener listener);
void unregisterOnSharedPreferenceChangeListener(
OnSharedPreferenceChangeListener listener);
// Content provider
void registerContentObserver(Uri contentUri, boolean descendents,
ContentObserver observer);
void unregisterContentObserver(ContentObserver observer);
// Sensors
Sensor getSensor(int type);
void registerSensorListener(SensorEventListener listener,
Sensor sensor, int sensorDelay);
void unregisterSensorListener(SensorEventListener listener);
// Location
boolean isLocationProviderEnabled(String provider);
void requestLocationUpdates(LocationListener listener);
void removeLocationUpdates(LocationListener listener);
Location getLastKnownLocation();
}
@@ -0,0 +1,166 @@
/*
* Copyright 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.content;
import static com.google.android.apps.mytracks.Constants.MAX_LOCATION_AGE_MS;
import static com.google.android.apps.mytracks.Constants.MAX_NETWORK_AGE_MS;
import com.google.android.apps.mytracks.Constants;
import com.google.android.maps.mytracks.R;
import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.database.ContentObserver;
import android.hardware.Sensor;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.net.Uri;
import android.util.Log;
import android.widget.Toast;
/**
* Real implementation of the data sources, which talks to system services.
*
* @author Rodrigo Damazio
*/
class DataSourcesWrapperImpl implements DataSourcesWrapper {
// System services
private final SensorManager sensorManager;
private final LocationManager locationManager;
private final ContentResolver contentResolver;
private final SharedPreferences sharedPreferences;
private final Context context;
DataSourcesWrapperImpl(Context context, SharedPreferences sharedPreferences) {
this.context = context;
this.sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
this.contentResolver = context.getContentResolver();
this.sharedPreferences = sharedPreferences;
}
@Override
public void registerOnSharedPreferenceChangeListener(
OnSharedPreferenceChangeListener listener) {
sharedPreferences.registerOnSharedPreferenceChangeListener(listener);
}
@Override
public void unregisterOnSharedPreferenceChangeListener(
OnSharedPreferenceChangeListener listener) {
sharedPreferences.unregisterOnSharedPreferenceChangeListener(listener);
}
@Override
public void registerContentObserver(Uri contentUri, boolean descendents,
ContentObserver observer) {
contentResolver.registerContentObserver(contentUri, descendents, observer);
}
@Override
public void unregisterContentObserver(ContentObserver observer) {
contentResolver.unregisterContentObserver(observer);
}
@Override
public Sensor getSensor(int type) {
return sensorManager.getDefaultSensor(type);
}
@Override
public void registerSensorListener(SensorEventListener listener,
Sensor sensor, int sensorDelay) {
sensorManager.registerListener(listener, sensor, sensorDelay);
}
@Override
public void unregisterSensorListener(SensorEventListener listener) {
sensorManager.unregisterListener(listener);
}
@Override
public boolean isLocationProviderEnabled(String provider) {
return locationManager.isProviderEnabled(provider);
}
@Override
public void requestLocationUpdates(LocationListener listener) {
// Check if the provider exists.
LocationProvider gpsProvider = locationManager.getProvider(LocationManager.GPS_PROVIDER);
if (gpsProvider == null) {
listener.onProviderDisabled(LocationManager.GPS_PROVIDER);
locationManager.removeUpdates(listener);
return;
}
// Listen to GPS location.
String providerName = gpsProvider.getName();
Log.d(Constants.TAG, "TrackDataHub: Using location provider " + providerName);
locationManager.requestLocationUpdates(providerName,
0 /*minTime*/, 0 /*minDist*/, listener);
// Give an initial update on provider state.
if (locationManager.isProviderEnabled(providerName)) {
listener.onProviderEnabled(providerName);
} else {
listener.onProviderDisabled(providerName);
}
// Listen to network location
try {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
1000 * 60 * 5 /*minTime*/, 0 /*minDist*/, listener);
} catch (RuntimeException e) {
// If anything at all goes wrong with getting a cell location do not
// abort. Cell location is not essential to this app.
Log.w(Constants.TAG, "Could not register network location listener.", e);
}
}
@Override
public Location getLastKnownLocation() {
// TODO: Let's look at more advanced algorithms to determine the best
// current location.
Location loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
final long now = System.currentTimeMillis();
if (loc == null || loc.getTime() < now - MAX_LOCATION_AGE_MS) {
// We don't have a recent GPS fix, just use cell towers if available
loc = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
int toastResId = R.string.status_approximate_location;
if (loc == null || loc.getTime() < now - MAX_NETWORK_AGE_MS) {
// We don't have a recent cell tower location, let the user know:
toastResId = R.string.status_no_location;
}
// Let the user know we have only an approximate location:
Toast.makeText(context, context.getString(toastResId), Toast.LENGTH_LONG).show();
}
return loc;
}
@Override
public void removeLocationUpdates(LocationListener listener) {
locationManager.removeUpdates(listener);
}
}
@@ -1,12 +1,12 @@
/*
* Copyright 2008 Google Inc.
*
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -15,7 +15,7 @@
*/
package com.google.android.apps.mytracks.content;
import com.google.android.apps.mytracks.MyTracksConstants;
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.util.ApiFeatures;
import android.content.ContentProvider;
@@ -154,12 +154,12 @@ public class MyTracksProvider extends ContentProvider {
// Sensor data.
if (oldVersion <= 17) {
Log.w(TAG, "Upgrade DB: Adding sensor column.");
db.execSQL("ALTER TABLE " + TRACKPOINTS_TABLE
db.execSQL("ALTER TABLE " + TRACKPOINTS_TABLE
+ " ADD " + TrackPointsColumns.SENSOR + " BLOB");
}
if (oldVersion <= 18) {
Log.w(TAG, "Upgrade DB: Adding tableid column.");
db.execSQL("ALTER TABLE " + TRACKS_TABLE
db.execSQL("ALTER TABLE " + TRACKS_TABLE
+ " ADD " + TracksColumns.TABLEID + " STRING");
}
}
@@ -186,19 +186,25 @@ public class MyTracksProvider extends ContentProvider {
@Override
public boolean onCreate() {
DatabaseHelper dbHelper = new DatabaseHelper(getContext());
db = dbHelper.getWritableDatabase();
try {
db = dbHelper.getWritableDatabase();
} catch (SQLiteException e) {
Log.e(TAG, "Unable to open database for writing", e);
}
return db != null;
}
@Override
public int delete(Uri url, String where, String[] selectionArgs) {
String table;
boolean shouldVacuum = false;
switch (urlMatcher.match(url)) {
case TRACKPOINTS:
table = TRACKPOINTS_TABLE;
break;
case TRACKS:
table = TRACKS_TABLE;
shouldVacuum = true;
break;
case WAYPOINTS:
table = WAYPOINTS_TABLE;
@@ -210,6 +216,13 @@ public class MyTracksProvider extends ContentProvider {
Log.w(MyTracksProvider.TAG, "provider delete in " + table + "!");
int count = db.delete(table, where, selectionArgs);
getContext().getContentResolver().notifyChange(url, null, true);
if (shouldVacuum) {
// If a potentially large amount of data was deleted, we want to reclaim its space.
Log.i(TAG, "Vacuuming the database");
db.execSQL("VACUUM");
}
return count;
}
@@ -373,8 +386,8 @@ public class MyTracksProvider extends ContentProvider {
}
if (ApiFeatures.getInstance().canReuseSQLiteQueryBuilder()) {
Log.i(MyTracksConstants.TAG,
"Build query: " + qb.buildQuery(projection, selection, selectionArgs,
Log.i(Constants.TAG,
"Build query: " + qb.buildQuery(projection, selection, selectionArgs,
null, null, sortOrder, null));
}
Cursor c = qb.query(db, projection, selection, selectionArgs, null, null,
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,150 @@
/*
* Copyright 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.content;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint;
import android.location.Location;
/**
* Listener for track data, for both initial and incremental loading.
*
* @author Rodrigo Damazio
*/
public interface TrackDataListener {
/** States for the GPS location provider. */
public enum ProviderState {
DISABLED,
NO_FIX,
BAD_FIX,
GOOD_FIX;
}
/**
* Called when the location provider changes state.
*/
void onProviderStateChange(ProviderState state);
/**
* Called when the current location changes.
* This is meant for immediate location display only - track point data is
* delivered by other methods below, such as {@link #onNewTrackPoint}.
*
* @param loc the last known location
*/
void onCurrentLocationChanged(Location loc);
/**
* Called when the current heading changes.
*
* @param heading the current heading, already accounting magnetic declination
*/
void onCurrentHeadingChanged(double heading);
/**
* Called when the currently-selected track changes.
* This will be followed by calls to data methods such as
* {@link #onTrackUpdated}, {@link #clearTrackPoints},
* {@link #onNewTrackPoint(Location)}, etc., even if no track is currently
* selected (in which case you'll only get calls to clear the current data).
*
* @param track the selected track, or null if no track is selected
* @param isRecording whether we're currently recording the selected track
*/
void onSelectedTrackChanged(Track track, boolean isRecording);
/**
* Called when the track and/or its statistics have been updated.
*
* @param track the updated version of the track
*/
void onTrackUpdated(Track track);
/**
* Called to clear any previously-sent track points.
* This can be called at any time that we decide the data needs to be
* reloaded, such as when it needs to be resampled.
*/
void clearTrackPoints();
/**
* Called when a new interesting track point is read.
* In this case, interesting means that the point has already undergone
* sampling and invalid point filtering.
*
* @param loc the new track point
*/
void onNewTrackPoint(Location loc);
/**
* Called when a uninteresting track point is read.
* Uninteresting points are all points that get sampled out of the track.
*
* @param loc the new track point
*/
void onSampledOutTrackPoint(Location loc);
/**
* Called when an invalid point (representing a segment split) is read.
*/
void onSegmentSplit();
/**
* Called when we're done (for the time being) sending new points.
* This gets called after every batch of calls to {@link #onNewTrackPoint},
* {@link #onSampledOutTrackPoint} and {@link #onSegmentSplit}.
*/
void onNewTrackPointsDone();
/**
* Called to clear any previously-sent waypoints.
* This can be called at any time that we decide the data needs to be
* reloaded.
*/
void clearWaypoints();
/**
* Called when a new waypoint is read.
*
* @param wpt the new waypoint
*/
void onNewWaypoint(Waypoint wpt);
/**
* Called when we're done (for the time being) sending new waypoints.
* This gets called after every batch of calls to {@link #clearWaypoints} and
* {@link #onNewWaypoint}.
*/
void onNewWaypointsDone();
/**
* Called when the display units are changed by the user.
*
* @param metric true if the units are metric, false if imperial
* @return true to reload all the data, false otherwise
*/
boolean onUnitsChanged(boolean metric);
/**
* Called when the speed/pace display unit is changed by the user.
*
* @param reportSpeed true to report speed, false for pace
* @return true to reload all the data, false otherwise
*/
boolean onReportSpeedChanged(boolean reportSpeed);
}
@@ -0,0 +1,177 @@
/*
* Copyright 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.content;
import static com.google.android.apps.mytracks.Constants.TAG;
import com.google.android.apps.mytracks.content.TrackDataHub.ListenerDataType;
import android.util.Log;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
/**
* Manager for the external data listeners and their listening types.
*
* @author Rodrigo Damazio
*/
class TrackDataListeners {
/** Internal representation of a listener's registration. */
static class ListenerRegistration {
final TrackDataListener listener;
final EnumSet<ListenerDataType> types;
// State that was last notified to the listener, for resuming after a pause.
long lastTrackId;
long lastPointId;
int lastSamplingFrequency;
int numLoadedPoints;
public ListenerRegistration(TrackDataListener listener,
EnumSet<ListenerDataType> types) {
this.listener = listener;
this.types = types;
}
public boolean isInterestedIn(ListenerDataType type) {
return types.contains(type);
}
public void resetState() {
lastTrackId = 0L;
lastPointId = 0L;
lastSamplingFrequency = 0;
numLoadedPoints = 0;
}
@Override
public String toString() {
return "ListenerRegistration [listener=" + listener + ", types=" + types
+ ", lastTrackId=" + lastTrackId + ", lastPointId=" + lastPointId
+ ", lastSamplingFrequency=" + lastSamplingFrequency
+ ", numLoadedPoints=" + numLoadedPoints + "]";
}
}
/** Map of external listener to its registration details. */
private final Map<TrackDataListener, ListenerRegistration> registeredListeners =
new HashMap<TrackDataListener, ListenerRegistration>();
/**
* Map of external paused listener to its registration details.
* This will automatically discard listeners which are GCed.
*/
private final WeakHashMap<TrackDataListener, ListenerRegistration> oldListeners =
new WeakHashMap<TrackDataListener, ListenerRegistration>();
/** Map of data type to external listeners interested in it. */
private final Map<ListenerDataType, Set<TrackDataListener>> listenerSetsPerType =
new EnumMap<ListenerDataType, Set<TrackDataListener>>(ListenerDataType.class);
public TrackDataListeners() {
// Create sets for all data types at startup.
for (ListenerDataType type : ListenerDataType.values()) {
listenerSetsPerType.put(type, new LinkedHashSet<TrackDataListener>());
}
}
/**
* Registers a listener to send data to.
* It is ok to call this method before {@link start}, and in that case
* the data will only be passed to listeners when {@link start} is called.
*
* @param listener the listener to register
* @param dataTypes the type of data that the listener is interested in
*/
public ListenerRegistration registerTrackDataListener(final TrackDataListener listener, EnumSet<ListenerDataType> dataTypes) {
Log.d(TAG, "Registered track data listener: " + listener);
if (registeredListeners.containsKey(listener)) {
throw new IllegalStateException("Listener already registered");
}
ListenerRegistration registration = oldListeners.remove(listener);
if (registration == null) {
registration = new ListenerRegistration(listener, dataTypes);
}
registeredListeners.put(listener, registration);
for (ListenerDataType type : dataTypes) {
// This is guaranteed not to be null.
Set<TrackDataListener> typeSet = listenerSetsPerType.get(type);
typeSet.add(listener);
}
return registration;
}
/**
* Unregisters a listener to send data to.
*
* @param listener the listener to unregister
*/
public void unregisterTrackDataListener(TrackDataListener listener) {
Log.d(TAG, "Unregistered track data listener: " + listener);
// Remove and keep the corresponding registration.
ListenerRegistration match = registeredListeners.remove(listener);
if (match == null) {
Log.w(TAG, "Tried to unregister listener which is not registered.");
return;
}
// Remove it from the per-type sets
for (ListenerDataType type : match.types) {
listenerSetsPerType.get(type).remove(listener);
}
// Keep it around in case it's re-registered soon
oldListeners.put(listener, match);
}
public ListenerRegistration getRegistration(TrackDataListener listener) {
ListenerRegistration registration = registeredListeners.get(listener);
if (registration == null) {
registration = oldListeners.get(listener);
}
return registration;
}
public Set<TrackDataListener> getListenersFor(ListenerDataType type) {
return listenerSetsPerType.get(type);
}
public EnumSet<ListenerDataType> getAllRegisteredTypes() {
EnumSet<ListenerDataType> listeners = EnumSet.noneOf(ListenerDataType.class);
for (ListenerRegistration registration : this.registeredListeners.values()) {
listeners.addAll(registration.types);
}
return listeners;
}
public boolean hasListeners() {
return !registeredListeners.isEmpty();
}
public int getNumListeners() {
return registeredListeners.size();
}
}
@@ -1,12 +1,12 @@
/*
* Copyright 2010 Google Inc.
*
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -20,21 +20,32 @@ import android.content.Intent;
/**
* This interface describes a class that will fetch and maintain a Google
* authentication token.
*
*
* @author Sandor Dornbush
*/
public interface AuthManager {
/**
* Callback for authentication token retrieval operations.
*/
public interface AuthCallback {
/**
* Indicates that we're done fetching an auth token.
*
* @param success if true, indicates we have the requested auth token available
* to be retrieved using {@link AuthManager#getAuthToken}
*/
void onAuthResult(boolean success);
}
/**
* Initializes the login process. The user should be asked to login if they
* haven't already. The {@link Runnable} provided will be executed when the
* auth token is successfully fetched.
* haven't already. The {@link AuthCallback} provided will be executed when the
* auth token fetching is done (successfully or not).
*
* @param whenFinished A {@link Runnable} to execute when the auth token
* has been successfully fetched and is available via
* {@link #getAuthToken()}
* @param whenFinished A {@link AuthCallback} to execute when the auth token
* fetching is done
*/
public abstract void doLogin(Runnable whenFinished, Object o);
void doLogin(AuthCallback whenFinished, Object o);
/**
* The {@link android.app.Activity} owner of this class should call this
@@ -49,11 +60,8 @@ public interface AuthManager {
* {@link android.app.Activity#onActivityResult} function
* @param results The data passed in to the {@link android.app.Activity}'s
* {@link android.app.Activity#onActivityResult} function
* @return True if the auth token was fetched or we aren't done fetching
* the auth token, or False if there was an error or the request was
* canceled
*/
public abstract boolean authResult(int resultCode, Intent results);
void authResult(int resultCode, Intent results);
/**
* Returns the current auth token. Response may be null if no valid auth
@@ -62,7 +70,7 @@ public interface AuthManager {
* @return The current auth token or null if no auth token has been
* fetched
*/
public abstract String getAuthToken();
String getAuthToken();
/**
* Invalidates the existing auth token and request a new one. The
@@ -72,6 +80,14 @@ public interface AuthManager {
* @param whenFinished A {@link Runnable} to execute when a new auth token
* is successfully fetched
*/
public abstract void invalidateAndRefresh(Runnable whenFinished);
void invalidateAndRefresh(AuthCallback whenFinished);
/**
* Returns an object that represents the given account, if possible.
*
* @param accountName the name of the account
* @param accountType the type of the account
* @return the account object
*/
Object getAccountObject(String accountName, String accountType);
}
@@ -1,12 +1,12 @@
/*
* Copyright 2010 Google Inc.
*
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -15,7 +15,7 @@
*/
package com.google.android.apps.mytracks.io;
import com.google.android.apps.mytracks.MyTracksConstants;
import static com.google.android.apps.mytracks.Constants.TAG;
import android.app.Activity;
import android.os.Build;
@@ -24,7 +24,7 @@ import android.util.Log;
/**
* A factory for getting the platform specific AuthManager.
*
*
* @author Sandor Dornbush
*/
public class AuthManagerFactory {
@@ -46,12 +46,10 @@ public class AuthManagerFactory {
public static AuthManager getAuthManager(Activity activity, int code,
Bundle extras, boolean requireGoogle, String service) {
if (useModernAuthManager()) {
Log.i(MyTracksConstants.TAG,
"Creating modern auth manager: " + service);
return new ModernAuthManager(activity, code, extras, requireGoogle, service);
Log.i(TAG, "Creating modern auth manager: " + service);
return new ModernAuthManager(activity, service);
} else {
Log.i(MyTracksConstants.TAG,
"Creating legacy auth manager: " + service);
Log.i(TAG, "Creating legacy auth manager: " + service);
return new AuthManagerOld(activity, code, extras, requireGoogle, service);
}
}
@@ -22,9 +22,6 @@ import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import java.util.Iterator;
import java.util.Vector;
/**
* AuthManager keeps track of the current auth token for a user. The advantage
* over just passing around a String is that this class can renew the auth
@@ -47,18 +44,12 @@ public class AuthManagerOld implements AuthManager {
/** The name of the service to authorize for. */
private final String service;
/** A list of handlers to call when a new auth token is fetched. */
private final Vector<Runnable> newTokenListeners = new Vector<Runnable>();
/** The handler to call when a new auth token is fetched. */
private AuthCallback authCallback;
/** The most recently fetched auth token or null if none is available. */
private String authToken;
/**
* The number of handlers at the beginning of the above list that shouldn't
* be removed after they are called.
*/
private int stickyNewTokenListenerCount;
/**
* AuthManager requires many of the same parameters as
* {@link GoogleLoginServiceHelper#getCredentials(Activity, int, Bundle,
@@ -88,15 +79,9 @@ public class AuthManagerOld implements AuthManager {
this.service = service;
}
/* (non-Javadoc)
* @see com.google.android.apps.mytracks.io.AuthManager#doLogin(java.lang.Runnable)
*/
public void doLogin(Runnable whenFinished, Object o) {
synchronized (newTokenListeners) {
if (whenFinished != null) {
newTokenListeners.add(whenFinished);
}
}
@Override
public void doLogin(AuthCallback callback, Object o) {
authCallback = callback;
activity.runOnUiThread(new LoginRunnable());
}
@@ -111,50 +96,37 @@ public class AuthManagerOld implements AuthManager {
}
}
/* (non-Javadoc)
* @see com.google.android.apps.mytracks.io.AuthManager#authResult(int, android.content.Intent)
*/
public boolean authResult(int resultCode, Intent results) {
if (resultCode == Activity.RESULT_OK) {
authToken = results.getStringExtra(
GoogleLoginServiceConstants.AUTHTOKEN_KEY);
if (authToken == null) {
GoogleLoginServiceHelper.getCredentials(
activity, code, extras, requireGoogle, service, false);
return true;
} else {
// Notify all active listeners that we have a new auth token.
synchronized (newTokenListeners) {
Iterator<Runnable> iter = newTokenListeners.iterator();
while (iter.hasNext()) {
iter.next().run();
}
iter = null;
// Remove anything not in the sticky part of the list.
newTokenListeners.setSize(stickyNewTokenListenerCount);
}
return true;
}
@Override
public void authResult(int resultCode, Intent results) {
if (resultCode != Activity.RESULT_OK) {
runAuthCallback(false);
return;
}
authToken = results.getStringExtra(GoogleLoginServiceConstants.AUTHTOKEN_KEY);
if (authToken == null) {
// Retry, without prompting the user.
GoogleLoginServiceHelper.getCredentials(
activity, code, extras, requireGoogle, service, false);
} else {
// Notify all active listeners that we have a new auth token.
runAuthCallback(true);
}
return false;
}
/* (non-Javadoc)
* @see com.google.android.apps.mytracks.io.AuthManager#getAuthToken()
*/
private void runAuthCallback(boolean success) {
authCallback.onAuthResult(success);
authCallback = null;
}
@Override
public String getAuthToken() {
return authToken;
}
/* (non-Javadoc)
* @see com.google.android.apps.mytracks.io.AuthManager#invalidateAndRefresh(java.lang.Runnable)
*/
public void invalidateAndRefresh(Runnable whenFinished) {
synchronized (newTokenListeners) {
if (whenFinished != null) {
newTokenListeners.add(whenFinished);
}
}
@Override
public void invalidateAndRefresh(AuthCallback callback) {
authCallback = callback;
activity.runOnUiThread(new Runnable() {
public void run() {
GoogleLoginServiceHelper.invalidateAuthToken(activity, code, authToken);
@@ -162,37 +134,8 @@ public class AuthManagerOld implements AuthManager {
});
}
/**
* Adds a {@link Runnable} to be executed every time the auth token is
* updated. The {@link Runnable} will not be removed until manually removed
* with {@link #removeStickyNewTokenListener(Runnable)}.
*
* @param listener The {@link Runnable} to execute every time a new auth
* token is fetched
*/
public void addStickyNewTokenListener(Runnable listener) {
synchronized (newTokenListeners) {
newTokenListeners.add(0, listener);
stickyNewTokenListenerCount++;
}
}
/**
* Stops executing the given {@link Runnable} every time the auth token is
* updated. This {@link Runnable} must have been added with
* {@link #addStickyNewTokenListener(Runnable)} above. If the
* {@link Runnable} was added more than once, only the first occurrence
* will be removed.
*
* @param listener The {@link Runnable} to stop executing every time a new
* auth token is fetched
*/
public void removeStickyNewTokenListener(Runnable listener) {
synchronized (newTokenListeners) {
if (stickyNewTokenListenerCount > 0
&& newTokenListeners.remove(listener)) {
stickyNewTokenListenerCount--;
}
}
@Override
public Object getAccountObject(String accountName, String accountType) {
throw new UnsupportedOperationException("Legacy auth manager knows nothing about accounts");
}
}
@@ -15,16 +15,17 @@
*/
package com.google.android.apps.mytracks.io;
import com.google.android.accounts.Account;
import com.google.android.accounts.AccountManager;
import com.google.android.accounts.AccountManagerCallback;
import com.google.android.accounts.AccountManagerFuture;
import com.google.android.accounts.AuthenticatorException;
import com.google.android.accounts.OperationCanceledException;
import com.google.android.apps.mytracks.AccountChooser;
import com.google.android.apps.mytracks.MyTracks;
import com.google.android.apps.mytracks.MyTracksConstants;
import static com.google.android.apps.mytracks.Constants.ACCOUNT_TYPE;
import static com.google.android.apps.mytracks.Constants.TAG;
import com.google.android.apps.mytracks.AccountChooser;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
@@ -50,7 +51,9 @@ public class ModernAuthManager implements AuthManager {
private final AccountManager accountManager;
private Runnable whenFinished;
private AuthCallback authCallback;
private Account lastAccount;
/**
* AuthManager requires many of the same parameters as
@@ -64,16 +67,9 @@ public class ModernAuthManager implements AuthManager {
* {@link Activity#onActivityResult} that calls
* {@link #authResult(int, Intent)} when {@literal code} is the request
* code
* @param code The request code to pass to
* {@link Activity#onActivityResult} when
* {@link #authResult(int, Intent)} should be called
* @param extras A {@link Bundle} of extras for
* {@link com.google.android.googlelogindist.GoogleLoginServiceHelper}
* @param requireGoogle True if the account must be a Google account
* @param service The name of the service to authenticate as
*/
public ModernAuthManager(Activity activity, int code, Bundle extras,
boolean requireGoogle, String service) {
public ModernAuthManager(Activity activity, String service) {
this.activity = activity;
this.service = service;
this.accountManager = AccountManager.get(activity);
@@ -88,47 +84,45 @@ public class ModernAuthManager implements AuthManager {
* has been successfully fetched and is available via
* {@link #getAuthToken()}
*/
public void doLogin(final Runnable runnable, Object o) {
this.whenFinished = runnable;
public void doLogin(AuthCallback runnable, Object o) {
this.authCallback = runnable;
if (!(o instanceof Account)) {
throw new IllegalArgumentException("FroyoAuthManager requires an account.");
throw new IllegalArgumentException("ModernAuthManager requires an account.");
}
Account account = (Account) o;
accountManager.getAuthToken(account, service, true,
doLogin(account);
}
private void doLogin(Account account) {
// Keep the account in case we need to retry.
this.lastAccount = account;
// NOTE: Many Samsung phones have a crashing bug in
// AccountManager#getAuthToken(Account, String, boolean, AccountManagerCallback<Bundle>)
// so we use the other version of the method.
// More details here:
// http://forum.xda-developers.com/showthread.php?p=15155487
// http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=core/java/android/accounts/AccountManagerService.java
accountManager.getAuthToken(account, service, null, activity,
new AccountManagerCallback<Bundle>() {
public void run(AccountManagerFuture<Bundle> future) {
try {
Bundle result = future.getResult();
// AccountManager needs user to grant permission
if (result.containsKey(AccountManager.KEY_INTENT)) {
Intent intent = (Intent) result.get(AccountManager.KEY_INTENT);
clearNewTaskFlag(intent);
activity.startActivityForResult(intent, MyTracksConstants.GET_LOGIN);
return;
}
authToken = result.getString(
authToken = future.getResult().getString(
AccountManager.KEY_AUTHTOKEN);
Log.e(MyTracksConstants.TAG, "Got auth token.");
runWhenFinished();
Log.i(TAG, "Got auth token");
} catch (OperationCanceledException e) {
Log.e(MyTracksConstants.TAG, "Operation Canceled", e);
Log.e(TAG, "Auth token operation Canceled", e);
} catch (IOException e) {
Log.e(MyTracksConstants.TAG, "IOException", e);
Log.e(TAG, "Auth token IO exception", e);
} catch (AuthenticatorException e) {
Log.e(MyTracksConstants.TAG, "Authentication Failed", e);
Log.e(TAG, "Authentication Failed", e);
}
runAuthCallback();
}
}, null /* handler */);
}
private static void clearNewTaskFlag(Intent intent) {
int flags = intent.getFlags();
flags &= ~Intent.FLAG_ACTIVITY_NEW_TASK;
intent.setFlags(flags);
}
/**
* The {@link Activity} passed into the constructor should call this
* function when it gets {@link Activity#onActivityResult} with the request
@@ -145,16 +139,22 @@ public class ModernAuthManager implements AuthManager {
* the auth token, or False if there was an error or the request was
* canceled
*/
public boolean authResult(int resultCode, Intent results) {
if (results != null) {
authToken = results.getStringExtra(
AccountManager.KEY_AUTHTOKEN);
Log.w(MyTracksConstants.TAG, "authResult: " + authToken);
public void authResult(int resultCode, Intent results) {
boolean retry = false;
if (results == null) {
Log.e(TAG, "No auth token!!");
} else {
Log.e(MyTracksConstants.TAG, "No auth result results!!");
authToken = results.getStringExtra(AccountManager.KEY_AUTHTOKEN);
retry = results.getBooleanExtra("retry", false);
}
runWhenFinished();
return authToken != null;
if (authToken == null && retry) {
Log.i(TAG, "Retrying to get auth result");
doLogin(lastAccount);
return;
}
runAuthCallback();
}
/**
@@ -176,21 +176,23 @@ public class ModernAuthManager implements AuthManager {
* @param runnable A {@link Runnable} to execute when a new auth token
* is successfully fetched
*/
public void invalidateAndRefresh(final Runnable runnable) {
this.whenFinished = runnable;
public void invalidateAndRefresh(final AuthCallback callback) {
this.authCallback = callback;
activity.runOnUiThread(new Runnable() {
public void run() {
accountManager.invalidateAuthToken(MyTracksConstants.ACCOUNT_TYPE,
authToken);
MyTracks.getInstance().getAccountChooser().chooseAccount(activity,
accountManager.invalidateAuthToken(ACCOUNT_TYPE, authToken);
authToken = null;
AccountChooser accountChooser = new AccountChooser();
accountChooser.chooseAccount(activity,
new AccountChooser.AccountHandler() {
@Override
public void handleAccountSelected(Account account) {
public void onAccountSelected(Account account) {
if (account != null) {
doLogin(whenFinished, account);
doLogin(account);
} else {
runWhenFinished();
runAuthCallback();
}
}
});
@@ -198,14 +200,22 @@ public class ModernAuthManager implements AuthManager {
});
}
private void runWhenFinished() {
if (whenFinished != null) {
private void runAuthCallback() {
lastAccount = null;
if (authCallback != null) {
(new Thread() {
@Override
public void run() {
whenFinished.run();
authCallback.onAuthResult(authToken != null);
authCallback = null;
}
}).start();
}
}
@Override
public Object getAccountObject(String accountName, String accountType) {
return new Account(accountName, accountType);
}
}
@@ -1,68 +0,0 @@
package com.google.android.apps.mytracks.io;
import com.google.android.apps.mytracks.io.gdata.GDataClientFactory;
import com.google.android.apps.mytracks.io.mymaps.MapsFacade;
import com.google.android.apps.mytracks.io.mymaps.MapsService;
import com.google.android.apps.mytracks.io.mymaps.MapsStringsProvider;
import com.google.android.apps.mytracks.io.mymaps.MapsFacade.AuthenticationRefresher;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.content.Context;
/**
* Factory to easily instantiate a {@link MapsFacade}.
*
* @author Rodrigo Damazio
*/
public class MyMapsFactory {
/**
* Simple provider for reading strings from resources.
*/
private static class MyMapsStringProvider implements MapsStringsProvider {
private final Context context;
public MyMapsStringProvider(Context context) {
this.context = context;
}
@Override
public String getNewMapDescription() {
return context.getString(R.string.new_map_description);
}
@Override
public String getStart() {
return context.getString(R.string.start);
}
@Override
public String getEnd() {
return context.getString(R.string.end);
}
}
/**
* Creates a new Maps fa�ade interface instance.
*
* @param context current context
* @param auth a valid authentication manager
* @return the fa�ade
*/
public static MapsFacade newMapsClient(Activity context, final AuthManager auth) {
MapsFacade client = MapsService.newClient(context,
GDataClientFactory.getGDataClient(context),
new MyMapsStringProvider(context),
auth.getAuthToken());
client.setAuthenticationRefresher(new AuthenticationRefresher() {
@Override
public void invalidateAndRefresh(Runnable done) {
auth.invalidateAndRefresh(done);
}
});
return client;
}
private MyMapsFactory() {}
}
@@ -15,9 +15,8 @@
*/
package com.google.android.apps.mytracks.io;
import com.google.android.apps.mytracks.MyTracks;
import com.google.android.apps.mytracks.MyTracksConstants;
import com.google.android.apps.mytracks.MyTracksSettings;
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.ProgressIndicator;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.io.docs.DocsHelper;
@@ -26,15 +25,13 @@ import com.google.android.apps.mytracks.io.gdata.GDataWrapper;
import com.google.android.common.gdata.AndroidXmlParserFactory;
import com.google.android.maps.mytracks.R;
import com.google.wireless.gdata.client.GDataClient;
import com.google.wireless.gdata.client.GDataServiceClient;
import com.google.wireless.gdata.docs.DocumentsClient;
import com.google.wireless.gdata.docs.SpreadsheetsClient;
import com.google.wireless.gdata.docs.XmlDocsGDataParserFactory;
import com.google.wireless.gdata.client.GDataServiceClient;
import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import java.io.IOException;
@@ -47,17 +44,15 @@ import java.io.IOException;
public class SendToDocs {
/** The GData service name for Google Spreadsheets (aka Trix) */
public static final String GDATA_SERVICE_NAME_TRIX = "wise";
/** The GData service name for the Google Docs Document List */
public static final String GDATA_SERVICE_NAME_DOCLIST = "writely";
private final Activity activity;
private final AuthManager trixAuth;
private final AuthManager docListAuth;
private final long trackId;
private final ProgressIndicator progressIndicator;
private final boolean metricUnits;
private final HandlerThread handlerThread;
private final Handler handler;
private boolean createdNewSpreadSheet = false;
@@ -65,15 +60,16 @@ public class SendToDocs {
private String statusMessage = "";
private Runnable onCompletion = null;
public SendToDocs(Activity activity, AuthManager trixAuth,
AuthManager docListAuth, long trackId) {
AuthManager docListAuth, ProgressIndicator progressIndicator) {
this.activity = activity;
this.trixAuth = trixAuth;
this.docListAuth = docListAuth;
this.trackId = trackId;
this.progressIndicator = progressIndicator;
SharedPreferences preferences = activity.getSharedPreferences(
MyTracksSettings.SETTINGS_NAME, 0);
Constants.SETTINGS_NAME, 0);
if (preferences != null) {
metricUnits =
preferences.getBoolean(activity.getString(R.string.metric_units_key),
@@ -81,31 +77,27 @@ public class SendToDocs {
} else {
metricUnits = true;
}
Log.d(MyTracksConstants.TAG,
"Sending to Google Docs: trackId = " + trackId);
handlerThread = new HandlerThread("SendToGoogleDocs");
handlerThread.start();
handler = new Handler(handlerThread.getLooper());
}
public void run() {
handler.post(new Runnable() {
public void sendToDocs(final long trackId) {
Log.d(Constants.TAG,
"Sending to Google Docs: trackId = " + trackId);
new Thread("SendToGoogleDocs") {
@Override
public void run() {
doUpload();
doUpload(trackId);
}
});
}.start();
}
private void doUpload() {
private void doUpload(long trackId) {
// TODO
statusMessage = activity.getString(R.string.error_sending_to_fusiontables);
success = false;
try {
if (trackId == -1) {
Log.w(MyTracksConstants.TAG, "Cannot get track id.");
Log.w(Constants.TAG, "Cannot get track id.");
return;
}
@@ -113,14 +105,14 @@ public class SendToDocs {
Track track =
MyTracksProviderUtils.Factory.get(activity).getTrack(trackId);
if (track == null) {
Log.w(MyTracksConstants.TAG, "Cannot get track.");
Log.w(Constants.TAG, "Cannot get track.");
return;
}
// Transmit track stats via GData feed:
// -------------------------------
Log.d(MyTracksConstants.TAG, "SendToDocs: Uploading to spreadsheet");
Log.d(Constants.TAG, "SendToDocs: Uploading to spreadsheet");
success = uploadToDocs(track);
if (success) {
if (createdNewSpreadSheet) {
@@ -133,7 +125,7 @@ public class SendToDocs {
} else {
statusMessage = activity.getString(R.string.error_sending_to_docs);
}
Log.d(MyTracksConstants.TAG, "SendToDocs: Done.");
Log.d(Constants.TAG, "SendToDocs: Done.");
} finally {
if (onCompletion != null) {
activity.runOnUiThread(onCompletion);
@@ -163,7 +155,7 @@ public class SendToDocs {
GDataWrapper<GDataServiceClient> docListWrapper = new GDataWrapper<GDataServiceClient>();
docListWrapper.setAuthManager(docListAuth);
docListWrapper.setRetryOnAuthFailure(true);
GDataWrapper<GDataServiceClient> trixWrapper = new GDataWrapper<GDataServiceClient>();
trixWrapper.setAuthManager(trixAuth);
trixWrapper.setRetryOnAuthFailure(true);
@@ -176,7 +168,7 @@ public class SendToDocs {
SpreadsheetsClient gdataClient = new SpreadsheetsClient(androidClient,
new XmlDocsGDataParserFactory(new AndroidXmlParserFactory()));
trixWrapper.setClient(gdataClient);
Log.d(MyTracksConstants.TAG,
Log.d(Constants.TAG,
"GData connection prepared: " + this.docListAuth);
String sheetTitle = "My Tracks";
@@ -191,89 +183,89 @@ public class SendToDocs {
// First try to find the spreadsheet:
String spreadsheetId = null;
try {
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
sheetTitle);
} catch (IOException e) {
Log.i(MyTracksConstants.TAG, "Spreadsheet lookup failed.", e);
Log.i(Constants.TAG, "Spreadsheet lookup failed.", e);
return false;
}
if (spreadsheetId == null) {
MyTracks.getInstance().setProgressValue(65);
progressIndicator.setProgressValue(65);
// Waiting a few seconds and trying again. Maybe the server just had a
// hickup (unfortunately that happens quite a lot...).
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Log.e(MyTracksConstants.TAG, "Sleep interrupted", e);
Log.e(Constants.TAG, "Sleep interrupted", e);
}
try {
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
sheetTitle);
} catch (IOException e) {
Log.i(MyTracksConstants.TAG, "2nd spreadsheet lookup failed.", e);
Log.i(Constants.TAG, "2nd spreadsheet lookup failed.", e);
return false;
}
}
// We were unable to find an existing spreadsheet, so create a new one.
MyTracks.getInstance().setProgressValue(70);
progressIndicator.setProgressValue(70);
if (spreadsheetId == null) {
Log.i(MyTracksConstants.TAG, "Creating new spreadsheet: " + sheetTitle);
Log.i(Constants.TAG, "Creating new spreadsheet: " + sheetTitle);
try {
spreadsheetId = docsHelper.createSpreadsheet(activity, docListWrapper,
sheetTitle);
} catch (IOException e) {
Log.i(MyTracksConstants.TAG, "Failed to create new spreadsheet "
Log.i(Constants.TAG, "Failed to create new spreadsheet "
+ sheetTitle, e);
return false;
}
MyTracks.getInstance().setProgressValue(80);
progressIndicator.setProgressValue(80);
createdNewSpreadSheet = true;
if (spreadsheetId == null) {
MyTracks.getInstance().setProgressValue(85);
progressIndicator.setProgressValue(85);
// The previous creation might have succeeded even though GData
// reported an error. Seems to be a know bug,
// see http://code.google.com/p/gdata-issues/issues/detail?id=929
// Try to find the created spreadsheet:
Log.w(MyTracksConstants.TAG,
Log.w(Constants.TAG,
"Create might have failed. Trying to find created document.");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Log.e(MyTracksConstants.TAG, "Sleep interrupted", e);
Log.e(Constants.TAG, "Sleep interrupted", e);
}
try {
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
sheetTitle);
} catch (IOException e) {
Log.i(MyTracksConstants.TAG, "Failed create-failed lookup", e);
Log.i(Constants.TAG, "Failed create-failed lookup", e);
return false;
}
if (spreadsheetId == null) {
MyTracks.getInstance().setProgressValue(87);
progressIndicator.setProgressValue(87);
// Re-try
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Log.e(MyTracksConstants.TAG, "Sleep interrupted", e);
Log.e(Constants.TAG, "Sleep interrupted", e);
}
try {
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
sheetTitle);
} catch (IOException e) {
Log.i(MyTracksConstants.TAG, "Failed create-failed relookup", e);
Log.i(Constants.TAG, "Failed create-failed relookup", e);
return false;
}
}
if (spreadsheetId == null) {
Log.i(MyTracksConstants.TAG,
Log.i(Constants.TAG,
"Creating new spreadsheet really failed.");
return false;
}
@@ -287,17 +279,17 @@ public class SendToDocs {
throw new IOException("Worksheet ID lookup returned empty");
}
} catch (IOException e) {
Log.i(MyTracksConstants.TAG, "Looking up worksheet id failed.", e);
Log.i(Constants.TAG, "Looking up worksheet id failed.", e);
return false;
}
MyTracks.getInstance().setProgressValue(90);
progressIndicator.setProgressValue(90);
docsHelper.addTrackRow(activity, trixAuth, spreadsheetId, worksheetId,
docsHelper.addTrackRow(activity, trixAuth, spreadsheetId, worksheetId,
track, metricUnits);
Log.i(MyTracksConstants.TAG, "Done uploading to docs.");
Log.i(Constants.TAG, "Done uploading to docs.");
} catch (IOException e) {
Log.e(MyTracksConstants.TAG, "Unable to upload docs.", e);
Log.e(Constants.TAG, "Unable to upload docs.", e);
return false;
} finally {
if (androidClient != null) {
@@ -15,8 +15,8 @@
*/
package com.google.android.apps.mytracks.io;
import com.google.android.apps.mytracks.MyTracksConstants;
import com.google.android.apps.mytracks.MyTracksSettings;
import static com.google.android.apps.mytracks.Constants.TAG;
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.ProgressIndicator;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track;
@@ -25,8 +25,9 @@ import com.google.android.apps.mytracks.io.gdata.GDataWrapper;
import com.google.android.apps.mytracks.io.gdata.GDataWrapper.QueryFunction;
import com.google.android.apps.mytracks.stats.DoubleBuffer;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.MyTracksUtils;
import com.google.android.apps.mytracks.util.LocationUtils;
import com.google.android.apps.mytracks.util.StringUtils;
import com.google.android.apps.mytracks.util.SystemUtils;
import com.google.android.apps.mytracks.util.UnitConversions;
import com.google.android.maps.mytracks.R;
import com.google.api.client.googleapis.GoogleHeaders;
@@ -49,6 +50,7 @@ import android.util.Log;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@@ -141,7 +143,7 @@ public class SendToFusionTables implements Runnable {
this.providerUtils = MyTracksProviderUtils.Factory.get(context);
GoogleHeaders headers = new GoogleHeaders();
headers.setApplicationName("Google-MyTracks-" + MyTracksUtils.getMyTracksVersion(context));
headers.setApplicationName("Google-MyTracks-" + SystemUtils.getMyTracksVersion(context));
headers.gdataVersion = GDATA_VERSION;
transport = new HttpTransport();
@@ -151,11 +153,16 @@ public class SendToFusionTables implements Runnable {
@Override
public void run() {
Log.d(MyTracksConstants.TAG, "Sending to Fusion tables: trackId = " + trackId);
Log.d(Constants.TAG, "Sending to Fusion tables: trackId = " + trackId);
doUpload();
}
public static String getMapVisualizationUrl(Track track) {
if (track == null || track.getStatistics() == null || track.getTableId() == null) {
Log.w(TAG, "Unable to get track URL");
return null;
}
// TODO(leifhendrik): Determine correct bounding box and zoom level that will show the entire track.
TripStatistics stats = track.getStatistics();
double latE6 = stats.getBottom() + (stats.getTop() - stats.getBottom()) / 2;
@@ -179,12 +186,17 @@ public class SendToFusionTables implements Runnable {
// Get the track meta-data
Track track = providerUtils.getTrack(trackId);
if (track == null) {
Log.w(Constants.TAG, "Cannot get track.");
return;
}
String originalDescription = track.getDescription();
// Create a new table:
progressIndicator.setProgressValue(PROGRESS_FUSION_TABLE_CREATE);
progressIndicator.setProgressMessage(R.string.progress_message_creating_fusiontable);
if (!createNewTable(track) || !makeTableUnlisted(tableId)) {
if (!createNewTable(track) || !makeTableUnlisted()) {
return;
}
@@ -204,10 +216,9 @@ public class SendToFusionTables implements Runnable {
}
statusMessageId = R.string.status_new_fusiontable_has_been_created;
Log.d(MyTracksConstants.TAG, "SendToFusionTables: Done: " + success);
Log.d(Constants.TAG, "SendToFusionTables: Done: " + success);
progressIndicator.setProgressValue(PROGRESS_COMPLETE);
} finally {
final boolean finalSuccess = success;
final int finalStatusMessageId = statusMessageId;
context.runOnUiThread(new Runnable() {
@@ -228,14 +239,14 @@ public class SendToFusionTables implements Runnable {
* @return true in case of success.
*/
private boolean createNewTable(Track track) {
Log.d(MyTracksConstants.TAG, "Creating a new fusion table.");
Log.d(Constants.TAG, "Creating a new fusion table.");
String query = "CREATE TABLE '" + sqlEscape(track.getName()) +
"' (name:STRING,description:STRING,geometry:LOCATION,marker:STRING)";
return runUpdate(query);
}
private boolean makeTableUnlisted(String tableId) {
Log.d(MyTracksConstants.TAG, "Setting visibility to unlisted.");
private boolean makeTableUnlisted() {
Log.d(Constants.TAG, "Setting visibility to unlisted.");
String query = "UPDATE TABLE " + tableId + " SET VISIBILITY = UNLISTED";
return runUpdate(query);
}
@@ -274,7 +285,7 @@ public class SendToFusionTables implements Runnable {
*/
private boolean createNewPoint(String name, String description, Location location,
String marker) {
Log.d(MyTracksConstants.TAG, "Creating a new row with a point.");
Log.d(Constants.TAG, "Creating a new row with a point.");
String query = "INSERT INTO " + tableId + " (name,description,geometry,marker) VALUES "
+ values(name, description, getKmlPoint(location), marker);
return runUpdate(query);
@@ -287,7 +298,7 @@ public class SendToFusionTables implements Runnable {
* @return true in case of success.
*/
private boolean createNewLineString(Track track) {
Log.d(MyTracksConstants.TAG, "Creating a new row with a point.");
Log.d(Constants.TAG, "Creating a new row with a point.");
String query = "INSERT INTO " + tableId
+ " (name,description,geometry) VALUES "
+ values(track.getName(), track.getDescription(), getKmlLineString(track));
@@ -296,7 +307,7 @@ public class SendToFusionTables implements Runnable {
private boolean uploadAllTrackPoints(final Track track, String originalDescription) {
SharedPreferences preferences = context.getSharedPreferences(MyTracksSettings.SETTINGS_NAME, 0);
SharedPreferences preferences = context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
boolean metricUnits = true;
if (preferences != null) {
metricUnits = preferences.getBoolean(context.getString(R.string.metric_units_key), true);
@@ -304,8 +315,8 @@ public class SendToFusionTables implements Runnable {
Cursor locationsCursor = providerUtils.getLocationsCursor(track.getId(), 0, -1, false);
try {
if (!locationsCursor.moveToFirst()) {
Log.w(MyTracksConstants.TAG, "Unable to get any points to upload");
if (locationsCursor == null || !locationsCursor.moveToFirst()) {
Log.w(Constants.TAG, "Unable to get any points to upload");
return false;
}
@@ -318,14 +329,14 @@ public class SendToFusionTables implements Runnable {
// Limit the number of elevation readings. Ideally we would want around 250.
int elevationSamplingFrequency =
Math.max(1, (int) (totalLocations / 250.0));
Log.d(MyTracksConstants.TAG,
Log.d(Constants.TAG,
"Using elevation sampling factor: " + elevationSamplingFrequency
+ " on " + totalLocations);
double totalDistance = 0;
Vector<Double> distances = new Vector<Double>();
Vector<Double> elevations = new Vector<Double>();
DoubleBuffer elevationBuffer = new DoubleBuffer(MyTracksConstants.ELEVATION_SMOOTHING_FACTOR);
DoubleBuffer elevationBuffer = new DoubleBuffer(Constants.ELEVATION_SMOOTHING_FACTOR);
List<Location> locations = new ArrayList<Location>(MAX_POINTS_PER_UPLOAD);
Location lastLocation = null;
@@ -344,7 +355,7 @@ public class SendToFusionTables implements Runnable {
}
// Add to the elevation profile.
if (loc != null && MyTracksUtils.isValidLocation(loc)) {
if (loc != null && LocationUtils.isValidLocation(loc)) {
// All points go into the smoothing buffer...
elevationBuffer.setNext(metricUnits ? loc.getAltitude()
: loc.getAltitude() * UnitConversions.M_TO_FT);
@@ -391,7 +402,9 @@ public class SendToFusionTables implements Runnable {
return true;
} finally {
locationsCursor.close();
if (locationsCursor != null) {
locationsCursor.close();
}
}
}
@@ -420,10 +433,10 @@ public class SendToFusionTables implements Runnable {
* @return the kml.
*/
private String getKmlPoint(Location location) {
StringBuilder builder = new StringBuilder("<Point><coordinates>");
appendCoordinate(location, builder);
builder.append("</coordinates></Point>");
return builder.toString();
StringBuilder builder = new StringBuilder("<Point><coordinates>");
appendCoordinate(location, builder);
builder.append("</coordinates></Point>");
return builder.toString();
}
/**
@@ -447,7 +460,7 @@ public class SendToFusionTables implements Runnable {
int numLocations = locations.size();
if (numLocations < 2) {
Log.d(MyTracksConstants.TAG, "Not preparing/uploading too few points");
Log.d(Constants.TAG, "Not preparing/uploading too few points");
totalLocationsUploaded += numLocations;
return true;
}
@@ -463,16 +476,16 @@ public class SendToFusionTables implements Runnable {
context.getString(R.string.part), totalSegmentsUploaded));
}
totalSegmentsUploaded++;
Log.d(MyTracksConstants.TAG,
Log.d(Constants.TAG,
"SendToFusionTables: Prepared feature for upload w/ "
+ splitTrack.getLocations().size() + " points.");
// Transmit tracks via GData feed:
// -------------------------------
Log.d(MyTracksConstants.TAG,
Log.d(Constants.TAG,
"SendToFusionTables: Uploading to table " + tableId + " w/ auth " + auth);
if (!uploadTrackPoints(splitTrack)) {
Log.e(MyTracksConstants.TAG, "Uploading failed");
Log.e(Constants.TAG, "Uploading failed");
return false;
}
}
@@ -518,7 +531,7 @@ public class SendToFusionTables implements Runnable {
// Close up the last segment.
prepareTrackSegment(segment, splitTracks);
Log.d(MyTracksConstants.TAG,
Log.d(Constants.TAG,
"MyTracksSendToFusionTables: Starting new track segment...");
startNewTrackSegment = false;
segment = new Track();
@@ -566,12 +579,12 @@ public class SendToFusionTables implements Runnable {
* Decimate to 2 meter precision. Fusion tables doesn't like too many
* points:
*/
MyTracksUtils.decimate(segment, 2.0);
LocationUtils.decimate(segment, 2.0);
/* If the track still has > 2500 points, split it in pieces: */
final int maxPoints = 2500;
if (segment.getLocations().size() > maxPoints) {
splitTracks.addAll(MyTracksUtils.split(segment, maxPoints));
splitTracks.addAll(LocationUtils.split(segment, maxPoints));
} else if (segment.getLocations().size() >= 2) {
splitTracks.add(segment);
}
@@ -581,7 +594,7 @@ public class SendToFusionTables implements Runnable {
int numLocations = splitTrack.getLocations().size();
if (numLocations < 2) {
// Need at least two points for a polyline:
Log.w(MyTracksConstants.TAG, "Not uploading too few points");
Log.w(Constants.TAG, "Not uploading too few points");
return true;
}
return createNewLineString(splitTrack);
@@ -599,29 +612,29 @@ public class SendToFusionTables implements Runnable {
// I am leaving the number of waypoints very high which should not be a
// problem because we don't try to load them into objects all at the
// same time.
boolean success = true;
boolean success = true;
Cursor c = null;
try {
c = providerUtils.getWaypointsCursor(
track.getId(), 0,
MyTracksConstants.MAX_LOADED_WAYPOINTS_POINTS);
Constants.MAX_LOADED_WAYPOINTS_POINTS);
if (c != null) {
if (c.moveToFirst()) {
// This will skip the 1st waypoint (it carries the stats for the
// last segment).
while (c.moveToNext()) {
Waypoint wpt = providerUtils.createWaypoint(c);
Log.d(MyTracksConstants.TAG, "SendToFusionTables: Creating waypoint.");
Log.d(Constants.TAG, "SendToFusionTables: Creating waypoint.");
success = createNewPoint(wpt.getName(), wpt.getDescription(), wpt.getLocation(),
MARKER_TYPE_WAYPOINT);
MARKER_TYPE_WAYPOINT);
if (!success) {
break;
break;
}
}
}
}
if (!success) {
Log.w(MyTracksConstants.TAG, "SendToFusionTables: upload waypoints failed.");
Log.w(Constants.TAG, "SendToFusionTables: upload waypoints failed.");
}
return success;
} finally {
@@ -637,7 +650,7 @@ public class SendToFusionTables implements Runnable {
// to fit the completion percentage range alloted to track data upload.
double totalPercentage =
(totalLocationsRead + totalLocationsPrepared + totalLocationsUploaded)
/ (totalLocations * 3);
/ (totalLocations * 3.0);
double scaledPercentage = totalPercentage
* (PROGRESS_UPLOAD_DATA_MAX - PROGRESS_UPLOAD_DATA_MIN) + PROGRESS_UPLOAD_DATA_MIN;
@@ -656,7 +669,7 @@ public class SendToFusionTables implements Runnable {
wrapper.setAuthManager(auth);
wrapper.setRetryOnAuthFailure(true);
wrapper.setClient(transport);
Log.d(MyTracksConstants.TAG, "GData connection prepared: " + this.auth);
Log.d(Constants.TAG, "GData connection prepared: " + this.auth);
wrapper.runQuery(new QueryFunction<HttpTransport>() {
@Override
public void query(HttpTransport client)
@@ -671,7 +684,7 @@ public class SendToFusionTables implements Runnable {
isc.inputStream = new ByteArrayInputStream(Strings.toBytesUtf8(sql));
request.content = isc;
Log.d(MyTracksConstants.TAG, "Running update query " + url.toString() + ": " + sql);
Log.d(Constants.TAG, "Running update query " + url.toString() + ": " + sql);
HttpResponse response;
try {
response = request.execute();
@@ -681,17 +694,17 @@ public class SendToFusionTables implements Runnable {
boolean success = response.isSuccessStatusCode;
if (success) {
byte[] result = new byte[1024];
response.getContent().read(result);
String s = Strings.fromBytesUtf8(result);
int read = response.getContent().read(result);
String s = new String(result, 0, read, Charset.forName("UTF8"));
String[] lines = s.split(Strings.LINE_SEPARATOR);
if (lines[0].equals("tableid")) {
tableId = lines[1];
Log.d(MyTracksConstants.TAG, "tableId = " + tableId);
Log.d(Constants.TAG, "tableId = " + tableId);
} else {
Log.w(MyTracksConstants.TAG, "Unrecognized response: " + lines[0]);
Log.w(Constants.TAG, "Unrecognized response: " + lines[0]);
}
} else {
Log.d(MyTracksConstants.TAG, "Query failed: " + response.statusMessage + " (" +
Log.d(Constants.TAG, "Query failed: " + response.statusMessage + " (" +
response.statusCode + ")");
throw new GDataWrapper.HttpException(response.statusCode, response.statusMessage);
}

Some files were not shown because too many files have changed in this diff Show More