forked from upstream-mirrors/OpenTracks
Compare commits
889 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 008fa88012 | |||
| 4c49497577 | |||
| 8dd3741fa7 | |||
| 5572e07b34 | |||
| 3f5589b655 | |||
| 48abfdd621 | |||
| 06088b807b | |||
| 21e47d8ce0 | |||
| c39ab2fda2 | |||
| 4197120d92 | |||
| da7bd0f4ea | |||
| 21ac283355 | |||
| 153f638e03 | |||
| 9156735aa0 | |||
| b8ad90a4cb | |||
| 36f7ba71f9 | |||
| b1af2089a4 | |||
| 2b50a314a5 | |||
| 376d02cce2 | |||
| 9e5204934f | |||
| 1ffd77595d | |||
| dac6a362f2 | |||
| 6d29b5140b | |||
| 2c5414a8e7 | |||
| 2fa325dbf3 | |||
| 969a677d7d | |||
| 90470342e7 | |||
| a4e762fb01 | |||
| da2d732041 | |||
| 6a5acee438 | |||
| 49cd5014d2 | |||
| 522882c0cc | |||
| 7e8b4dc4b9 | |||
| 8e673f6634 | |||
| 05e6018bd1 | |||
| e1a845d49f | |||
| 2deded2d88 | |||
| af550a7104 | |||
| e68d7eb12d | |||
| a186e68ca0 | |||
| 81c60ca6f2 | |||
| bd9347afd7 | |||
| 9023cdf726 | |||
| 9caef87899 | |||
| c9d9c065a2 | |||
| c024c8d87b | |||
| 850a0d988a | |||
| 7bd3128e8f | |||
| 43a1ec60ce | |||
| d04d83b972 | |||
| 89516c41e3 | |||
| 4f9b6535fb | |||
| 6ab1f6158a | |||
| bb8e6a51f4 | |||
| 7a8ea2666b | |||
| 3029c6d10c | |||
| 9bb0ba2953 | |||
| 0e22eaf7c3 | |||
| 53ee9d31bc | |||
| 7134edf2f2 | |||
| e4da671cbc | |||
| 8cde2420e7 | |||
| 3c4c215931 | |||
| eb6cdd0fc0 | |||
| 0b1c24e55c | |||
| 057c2d69a9 | |||
| 79c2cf90cf | |||
| 20cbdccbf6 | |||
| 5d05d71210 | |||
| 08294e8ada | |||
| 41f7262280 | |||
| 6aa361b801 | |||
| 9281e0adf3 | |||
| ace10fc511 | |||
| 0ac923e104 | |||
| 082aa0a34a | |||
| acf5c0931f | |||
| ee204f35ef | |||
| e885224855 | |||
| d48eccc0e4 | |||
| 21012b305f | |||
| a79e322eff | |||
| b5a1cf1b10 | |||
| 40ebd7bc2c | |||
| ef37ee0f38 | |||
| 49033bf952 | |||
| d9725240a6 | |||
| cb5518a261 | |||
| ac71d8aa2a | |||
| 62c9af5cba | |||
| a4f16a1f30 | |||
| 1b595ee7fe | |||
| fa556e4e33 | |||
| 391d718909 | |||
| 2ce14e443d | |||
| cdf0a3a3e7 | |||
| f00f9a5277 | |||
| 7112642e89 | |||
| 3714c21f97 | |||
| 24c49b7f2f | |||
| b16429f3f8 | |||
| 27734495f4 | |||
| 097b338d19 | |||
| cbb8450435 | |||
| 3b7e0a91bd | |||
| d9a1e56282 | |||
| b63e74369c | |||
| 4d0ba06cba | |||
| c4369dc237 | |||
| 99dd212496 | |||
| 6e41033ed6 | |||
| 90a5cb7aae | |||
| bccfbaa03b | |||
| e32ff7116d | |||
| 00214843cb | |||
| dd4054c4fc | |||
| 0b40b92340 | |||
| 60a3c41003 | |||
| f501c60de1 | |||
| b985a935b0 | |||
| a2f1790db2 | |||
| 5784ab63cc | |||
| fd857c2586 | |||
| 29df8762e2 | |||
| 32e13c3495 | |||
| e6151b3b71 | |||
| 6823b08651 | |||
| b588bb02f4 | |||
| faf7b6efa2 | |||
| 03492da2cd | |||
| 8abfc2ada0 | |||
| a262a2ef71 | |||
| 435a38f1d1 | |||
| 91d7db7c01 | |||
| e298c88728 | |||
| d58e7a58d0 | |||
| e530412ef0 | |||
| 1d5e2dc4d5 | |||
| d0b5faf266 | |||
| 76e8a39276 | |||
| 66fe8e694f | |||
| abd8a230b4 | |||
| 565662a8aa | |||
| 0f00e71b5e | |||
| 44fea0117d | |||
| b9b39a24f7 | |||
| 358fb87683 | |||
| f0ef73d150 | |||
| 1d2297a5fc | |||
| 862736bba4 | |||
| e30dac7cc2 | |||
| f97d5fa232 | |||
| e909616aff | |||
| be219bbee6 | |||
| 17c1c81b4e | |||
| bf0a16c707 | |||
| 86a54feb41 | |||
| 2c923470f8 | |||
| 5d26250b45 | |||
| 6d90e0bf51 | |||
| 51df795a8c | |||
| 9ee053e4f9 | |||
| 4044185ab3 | |||
| f4fe825162 | |||
| cb785b89f0 | |||
| 8289128399 | |||
| e9146f5fc1 | |||
| bc7de458d3 | |||
| 4aa44331f0 | |||
| eada19f516 | |||
| 63677b1451 | |||
| 5789d96a3d | |||
| 0afdeb9bcc | |||
| 79dd8f4e49 | |||
| 93f204ba22 | |||
| 98ad96115a | |||
| ae4ce12c17 | |||
| b8767042b4 | |||
| 200e5f3373 | |||
| ebb68cccfe | |||
| cc4be23802 | |||
| 9f44b1695d | |||
| 94344deff3 | |||
| a41994cb41 | |||
| eee6a713fa | |||
| aed28fe503 | |||
| 7bc72e683b | |||
| 31e386de44 | |||
| 31737efd87 | |||
| be096b9657 | |||
| 3e773ef94b | |||
| 111adc917b | |||
| 6a1b2861f3 | |||
| ed3ff01c22 | |||
| 73e4af98cc | |||
| 84835428ba | |||
| 9f3099ef2b | |||
| 412eed51cd | |||
| bd20d1af02 | |||
| a15932cc7f | |||
| 8942c31a5c | |||
| 90fe6921e2 | |||
| e8a872d351 | |||
| a16ae846ae | |||
| eeaa50ddcb | |||
| 16b0d4eb24 | |||
| e926180605 | |||
| 958b62f8c7 | |||
| d238a9e9dd | |||
| fb993a7060 | |||
| 6b375614ca | |||
| 594cc0f06d | |||
| d712bb1988 | |||
| 59a30238eb | |||
| 8056b66714 | |||
| e09501d779 | |||
| 70192222ad | |||
| cc253d4b33 | |||
| 7d3918a1c6 | |||
| e759a14909 | |||
| fd5a1c5b4b | |||
| c95dc12a96 | |||
| 70ef5912c2 | |||
| 79bb9db3b9 | |||
| d3791ea99b | |||
| 5982fed0b8 | |||
| 1254df2db1 | |||
| 8a23af8581 | |||
| 9cabb27c39 | |||
| 5c17437ba6 | |||
| 520c3659d2 | |||
| 962374b765 | |||
| 8fcc809299 | |||
| 8eac101082 | |||
| b1605ac44e | |||
| 90afc1e221 | |||
| adeba81340 | |||
| 8c10b7ba04 | |||
| 8aae77ff70 | |||
| 7eeacc6268 | |||
| 06e02781d2 | |||
| 3b5625c663 | |||
| ea47f93bc1 | |||
| c33c2de18b | |||
| f125a798bf | |||
| 84d7281002 | |||
| d98a53ec43 | |||
| ee3026233e | |||
| 8fb0b69a79 | |||
| 03ce6c05a9 | |||
| 1d3a03909b | |||
| 7020b78faa | |||
| f1746b41a2 | |||
| 22b96e4b24 | |||
| ddf684f6c6 | |||
| cc9d327ea0 | |||
| 47e23e3463 | |||
| 8feb903021 | |||
| 124172e4d7 | |||
| 9d4367cfac | |||
| 6cd9dfce8c | |||
| 4a3dbe4d60 | |||
| 062ab5045a | |||
| ba472d3b7b | |||
| 82adcf37f4 | |||
| 4f23690ab4 | |||
| 17481aeb38 | |||
| 26adbb1717 | |||
| ffd2785499 | |||
| 5c6d160cbf | |||
| 28a5c5b343 | |||
| 3501fff7fc | |||
| 1988337598 | |||
| be2fdd5cfa | |||
| ef0837c514 | |||
| 252f88e362 | |||
| 8ba9b47141 | |||
| f984339b13 | |||
| a1ff1d2585 | |||
| 3bbe7d0322 | |||
| 3fd729f1a2 | |||
| 375b75c422 | |||
| 340a1e3e3a | |||
| 8d3ab8f93b | |||
| 8dc52de871 | |||
| 6ff39be4bf | |||
| e2548ac9e2 | |||
| 0ce94ada82 | |||
| 77a4c4be70 | |||
| 9616084769 | |||
| 163a246c58 | |||
| 31efcb4a86 | |||
| 1faea596f8 | |||
| cd5cb9093c | |||
| 9f1bd89a0c | |||
| 0908053881 | |||
| 910068bcf5 | |||
| d9ae0ff1bf | |||
| 4bea1a6e70 | |||
| e7873b0fa0 | |||
| c892704ee3 | |||
| 7cd44c853a | |||
| 818b42b97e | |||
| 5870ba98b4 | |||
| 19939c985a | |||
| 7d65a9ef22 | |||
| eb45f7c3bc | |||
| 90a89c9224 | |||
| e59b52dcac | |||
| 07d4edef4e | |||
| b76c2f7b8d | |||
| be414510a4 | |||
| e4b2052231 | |||
| 5066b23603 | |||
| 86de9830b4 | |||
| 758b5e4810 | |||
| 79e2c55c34 | |||
| 802cf51cf9 | |||
| 55d4a90041 | |||
| cf535a2f8f | |||
| ba38964e8a | |||
| c943e5dd43 | |||
| 65f44da4c9 | |||
| 24c51afa40 | |||
| e6739adb35 | |||
| 06fceb07cc | |||
| c87029254c | |||
| d52aca1d3d | |||
| 26af05cd01 | |||
| f7750f2a2c | |||
| 675b4f55c1 | |||
| a322439a83 | |||
| f7a1046c67 | |||
| c17593d932 | |||
| 109d2969a5 | |||
| 2d3c463bf3 | |||
| 74073b641f | |||
| 426033f835 | |||
| a9ad1e22d6 | |||
| 903aa014e4 | |||
| e058854c3f | |||
| c16ce866dc | |||
| f9eba950e0 | |||
| 3eb53d3195 | |||
| 2a5921d3d0 | |||
| 440c711335 | |||
| 7ea573123b | |||
| 7f5ce45fad | |||
| bd16542e25 | |||
| b95a696a5a | |||
| b8f40e8314 | |||
| 0bbeff0b5b | |||
| 5828e16421 | |||
| 8497d2efba | |||
| b578d2ced0 | |||
| 239b461f75 | |||
| c7db7c0926 | |||
| e107766a61 | |||
| 05a0b6c615 | |||
| 7ada8f18fb | |||
| 887a77f4a3 | |||
| 97bde67b1d | |||
| 33c3668175 | |||
| 0158fc3a7a | |||
| 72bb2ddb08 | |||
| 01c1a37fa2 | |||
| 35aa51d6a9 | |||
| ada42ee57d | |||
| fe9b27ecf2 | |||
| e03f120a00 | |||
| 59344f540d | |||
| e829f1fc1b | |||
| d9904eb5f1 | |||
| 10cd26af5e | |||
| c1f649fc83 | |||
| a4865f860d | |||
| 14fce8edfe | |||
| 6826e3567d | |||
| 250e8625a7 | |||
| 58530d6f72 | |||
| 823fb3fca7 | |||
| 29302c0891 | |||
| 03570ebd43 | |||
| 2a4a0d38e3 | |||
| 9be9127ad1 | |||
| 66dd1c01f0 | |||
| d8dce7938d | |||
| 0701f5885e | |||
| ea3f660999 | |||
| 95a21ffe8a | |||
| 89d2cf8340 | |||
| 0eb676d3cd | |||
| ac1a762fa8 | |||
| 59a05262a1 | |||
| 5f91d187c8 | |||
| 8d8bf311ed | |||
| 69545c8a56 | |||
| a1868c0205 | |||
| 12bc4f0da8 | |||
| 510b887042 | |||
| ff7171daa2 | |||
| 5b0dbd5d30 | |||
| 9c7fb25a94 | |||
| 2e24eab5ad | |||
| 8135ad4424 | |||
| 6ffa40e40d | |||
| bc120176ca | |||
| d50d4ae1c9 | |||
| d34aa61e95 | |||
| 04578a4ed1 | |||
| 3e5282a06d | |||
| f86cadb802 | |||
| c4fe4d87db | |||
| 7e5deeaab3 | |||
| 36c425d699 | |||
| a2c69c6144 | |||
| 58e3c0604d | |||
| 7408849eb5 | |||
| b42142f692 | |||
| ddafdcf392 | |||
| 95cbaf1993 | |||
| 43aa3c857d | |||
| 964e0d6f41 | |||
| 5a1c52d3b5 | |||
| 02c374b61e | |||
| f2094e049a | |||
| 8ff2b3b090 | |||
| eeaa363132 | |||
| 43e51848fc | |||
| 8b17117220 | |||
| a4e06a4ce0 | |||
| 4d55f5ebdb | |||
| 268f3c77c2 | |||
| ce73718620 | |||
| d307c58f87 | |||
| e7ec021da8 | |||
| ca94fc7a96 | |||
| 9d650c4885 | |||
| c6d9be499c | |||
| 0e78e8b3f9 | |||
| 2a99278b52 | |||
| 4a47c096f7 | |||
| bd961be055 | |||
| 525fea80b8 | |||
| 6f92ae6a59 | |||
| 8bad6c0f54 | |||
| 91cca16f40 | |||
| a0697a048d | |||
| d22c6aae79 | |||
| 83997980ba | |||
| 4d9bdd1c12 | |||
| 163a73722e | |||
| 65d17decb8 | |||
| 1aa300f97e | |||
| 8fbb30bded | |||
| 6b0f1a0c10 | |||
| 1cee590eca | |||
| 9ff370ee27 | |||
| cd0057ea5a | |||
| 2c0a294b6a | |||
| 3e09bd5c60 | |||
| 0a99d7cebb | |||
| 3138e3edc7 | |||
| 99ab34ad0b | |||
| 9b7923f8f5 | |||
| cfcbe7f107 | |||
| 5fb27ab186 | |||
| 36b1a3c020 | |||
| baccb5d12e | |||
| adc4621711 | |||
| a8d78664e9 | |||
| 9fab4eb088 | |||
| 0d0f1315ff | |||
| 555598c155 | |||
| f49fa23f69 | |||
| b732064f88 | |||
| 1f99a381eb | |||
| 81b610cc4c | |||
| b0a0bfc888 | |||
| 6221ccb53b | |||
| cbe1da2d68 | |||
| 24297e373c | |||
| 99d14a559c | |||
| 08339a1f65 | |||
| 4e3ad38087 | |||
| 63c97fadc6 | |||
| 45633ad7e8 | |||
| 8508decd5c | |||
| 315f47bf30 | |||
| 12f8d79d84 | |||
| 710690e2d2 | |||
| 03bfbe81d0 | |||
| c990fb6fe7 | |||
| 9b31cd63a4 | |||
| dee3ccdf77 | |||
| de23a32c96 | |||
| 2beb840a5c | |||
| f748d76549 | |||
| 9d9a326c2b | |||
| 9184827195 | |||
| cb533c954b | |||
| ead876036d | |||
| cfa25eccb1 | |||
| b0d6233de6 | |||
| b07b8a1aaa | |||
| a68cdaf2ba | |||
| 16641b9193 | |||
| 0469a90992 | |||
| 6dc3e5ab7a | |||
| 82012fa623 | |||
| 7ddd254bb1 | |||
| 464858cfdf | |||
| 30db23255d | |||
| 868c1ef891 | |||
| b961356b7b | |||
| 2e32d6c574 | |||
| a31e5aab79 | |||
| ae4f9565bd | |||
| f33ba10b96 | |||
| 904c519091 | |||
| a0db837910 | |||
| 51cb5db8b4 | |||
| c328728e0c | |||
| 3384ef67a6 | |||
| e89c549706 | |||
| 3c67ac73da | |||
| 656349e6c5 | |||
| df2af0185c | |||
| 913d30f2de | |||
| e96172b698 | |||
| 0c241f683d | |||
| a19097de2b | |||
| f6feeb9d1e | |||
| f205e6f9cc | |||
| 4e543e6068 | |||
| 176062f11c | |||
| 4d88191171 | |||
| 025ea1d094 | |||
| a4283d545a | |||
| 52fa2aace9 | |||
| fa711cf142 | |||
| 70bc7e53fe | |||
| 56f22aa073 | |||
| 878a87278d | |||
| c4a539d2ba | |||
| 4225e81080 | |||
| 8fd4887f10 | |||
| 0e397797b4 | |||
| e6c8458ce7 | |||
| 50ea9919af | |||
| 67f62df894 | |||
| 0da0280156 | |||
| fa713eac4a | |||
| 2c7d56ab34 | |||
| e340268dd0 | |||
| affec6720b | |||
| 5047826a74 | |||
| 33d9230442 | |||
| 607b174c5f | |||
| 6b4ea71404 | |||
| 014322c240 | |||
| b789f84151 | |||
| 19d5fe1ba6 | |||
| 93b95954c4 | |||
| fb7a2aaa32 | |||
| 3105eacd4d | |||
| 215893214f | |||
| 30e01d6700 | |||
| 94cfc5d7d6 | |||
| 471b32cce1 | |||
| 036b34e91d | |||
| 77f7f8c1ed | |||
| e6fc991d2a | |||
| 060881777d | |||
| 6e567fa725 | |||
| 7e4c01937f | |||
| 06a00e6482 | |||
| 242df42f55 | |||
| 8d78c16c8a | |||
| db2b05eb7f | |||
| 282b1090ba | |||
| 4f6c9fa866 | |||
| 9375842c71 | |||
| ea3fca0f1b | |||
| 5971d67a66 | |||
| 9f5fa880d6 | |||
| 357b68dd4f | |||
| 384f3f5698 | |||
| 4577ff9628 | |||
| e6cd9f524d | |||
| 3dad56621f | |||
| 6c9a225b64 | |||
| 3bbb9bd95d | |||
| a4f855ccd8 | |||
| 4d80af4e06 | |||
| 7abce12499 | |||
| 7b1302c011 | |||
| 66d23b7eac | |||
| dc0255509b | |||
| 6661f91eb5 | |||
| 2eb36aedeb | |||
| 0e623ebfeb | |||
| ffb73569e9 | |||
| 713cda9455 | |||
| 223721cca8 | |||
| e7479c8a93 | |||
| 224fe0069b | |||
| cb97847392 | |||
| 6a29531467 | |||
| 262e249d2c | |||
| 77479efaef | |||
| 898863a8d9 | |||
| 05d555f98d | |||
| 868092db10 | |||
| 7a738c2eca | |||
| b304dbcba6 | |||
| 6e28a5daa4 | |||
| 8f4f9660ed | |||
| 2d01535651 | |||
| e57d4669fc | |||
| f47c599dea | |||
| 7a693a90f7 | |||
| 9cf51de3f7 | |||
| 5089c20cd6 | |||
| a0da23f86a | |||
| 44d24b57c6 | |||
| c143d774d4 | |||
| 9e92240dd0 | |||
| d2c586b096 | |||
| fbfbb9408a | |||
| fb56665dec | |||
| 5b65c216b6 | |||
| 9ad98c5970 | |||
| cae9d0f2e5 | |||
| c0d267c63e | |||
| 70704b0a5e | |||
| b135275201 | |||
| 7e1eae6681 | |||
| 30f5d6dc85 | |||
| a50dd1168b | |||
| 62fa1620aa | |||
| a0d42c8b59 | |||
| a21663da61 | |||
| 67a0382942 | |||
| f5c2467d01 | |||
| a3abcc8094 | |||
| edf439f301 | |||
| 2245563250 | |||
| bca21d5515 | |||
| 89cae2e7c9 | |||
| 26c381a4c4 | |||
| 4bc5aa050c | |||
| cd44b0d180 | |||
| 59ee91ca5d | |||
| 59165a7033 | |||
| 93d242c05f | |||
| 4bbb6591e3 | |||
| 7df8025f6a | |||
| f19c52f40e | |||
| b7840779fe | |||
| 28042a8cc9 | |||
| b2907226bf | |||
| a2f46821f5 | |||
| b7385cd4cc | |||
| 718c65818c | |||
| 91e2293606 | |||
| 3c4a921f9a | |||
| d04b333126 | |||
| 0a4bef4d9a | |||
| a0f090a83a | |||
| dc8ee5943c | |||
| 9132c36aa7 | |||
| 224c0d759f | |||
| ffcaca2db1 | |||
| 409fc4a43b | |||
| 16968f3f2b | |||
| e3fd0dce21 | |||
| 53b6b6deca | |||
| 26f47a50d0 | |||
| 3cf77374c4 | |||
| a1129c3f0f | |||
| 2fe74603a3 | |||
| 54d517363d | |||
| 948fe0c0e6 | |||
| dbd8e6c0e9 | |||
| 02b5601933 | |||
| 3ed40608a2 | |||
| 36d7c2dd91 | |||
| fa7ef68851 | |||
| f84877a4fc | |||
| 261fb62e24 | |||
| 48d8aa4cd8 | |||
| 95ff0d3db6 | |||
| 2dc1d914c0 | |||
| fc06701009 | |||
| ee4f334296 | |||
| cac2395237 | |||
| 5afc3f13cf | |||
| 9030917c14 | |||
| 9905def352 | |||
| a3793aa92b | |||
| 76c8498956 | |||
| 75bd8ea5a2 | |||
| 50a5e864ac | |||
| 352fc26f7e | |||
| 44afa1623e | |||
| 14acafabfc | |||
| 773af58d03 | |||
| 352b851e9c | |||
| 8353a01082 | |||
| b70e001206 | |||
| a741bb4d55 | |||
| 24adee3d54 | |||
| 09203ffb95 | |||
| e94338f4c6 | |||
| dd9dd8ee81 | |||
| 01d6dcac59 | |||
| ad0ee6b0d6 | |||
| 769c8c228e | |||
| 50fcd67085 | |||
| 52d03e6b7d | |||
| b949cd0039 | |||
| e527170315 | |||
| ec7d210c36 | |||
| 74a4089464 | |||
| fa9e14f574 | |||
| cdbeefcd16 | |||
| ffdd5f4091 | |||
| bb60525780 | |||
| 82634af649 | |||
| 3643ed9f13 | |||
| fac59ab705 | |||
| 1e343b0d12 | |||
| 34bb467b97 | |||
| b092525c10 | |||
| 256dac3a82 | |||
| dfe947f54d | |||
| ce09407816 | |||
| beee6af79d | |||
| c282562867 | |||
| 2aed9b3a33 | |||
| 210910f21e | |||
| 1d666318ae | |||
| 4df6095089 | |||
| d4edcce224 | |||
| d7c6761841 | |||
| 5733224f8d | |||
| 22fd5042bc | |||
| 44a6f2d448 | |||
| cd9c17f9b3 | |||
| dc07bcf0fa | |||
| 248b8fb4fd | |||
| d5ec7c3001 | |||
| 35182a1483 | |||
| 21b0a517a9 | |||
| 19a770445e | |||
| c6512f1376 | |||
| 2cb3963138 | |||
| d05c394c68 | |||
| 797de31960 | |||
| a0af1a811a | |||
| 4933b9ce54 | |||
| e81c4eb155 | |||
| b284c8bc56 | |||
| 872d2d4337 | |||
| 525f1b7781 | |||
| 2f99d8ca62 | |||
| 7781014cf7 | |||
| 2432b36f5d | |||
| 288aa015fa | |||
| 1cb8b922c3 | |||
| 41cec64bf6 | |||
| d82bda9d00 | |||
| b84da40365 | |||
| d02c947b84 | |||
| 7167a5a71e | |||
| f13c2455ea | |||
| b200b66612 | |||
| b811df8cda | |||
| 1e239b78c3 | |||
| 3a8daadd92 | |||
| f605d6fca5 | |||
| cd85e43624 | |||
| 2b94d09539 | |||
| ab82da5c75 | |||
| 8a467aa537 | |||
| 742e6b1e3e | |||
| e35e8bcdce | |||
| 5f953aa47f | |||
| e550e9aa1d | |||
| 26e2defd9e | |||
| 3b3641c69e | |||
| 56ccd518d6 | |||
| 59846280a8 | |||
| aa95e3abcd | |||
| ad6340c1a7 | |||
| 62a54aab58 | |||
| 23f1e81cf0 | |||
| d014f422d2 | |||
| 68a9f1bc46 | |||
| 798637d465 | |||
| 60ea4c5f77 | |||
| 0e119950c2 | |||
| 4be4467fc6 | |||
| 06636b2a28 | |||
| 71a36d1b25 | |||
| 9ba93ff8d2 | |||
| 4059308dd7 | |||
| 9befe8ae5f | |||
| 20e01f3b2c | |||
| 98b894ed8e | |||
| ac8b7264b3 | |||
| bf7b24ecc0 | |||
| 9f43dd2db5 | |||
| 28d868985e | |||
| cf1be26da2 | |||
| 1de9b73aa0 | |||
| 3532a6360b | |||
| beddc8e1ea | |||
| df81fba565 | |||
| 25da0d26ef | |||
| e0c34d20a8 | |||
| cc6db5b5cc | |||
| c38df03add | |||
| 63402358d1 | |||
| 3ae1de735e | |||
| a701eb0e4f | |||
| 09caf017a9 | |||
| 32b8b2093d | |||
| c84a4f1aa8 | |||
| d90c0b5431 | |||
| 94f6785f0d | |||
| f01c382807 | |||
| 6d42803dd8 | |||
| 61e908ccb5 | |||
| 236bcba2bd | |||
| 7bae8c34a7 | |||
| 3960341640 | |||
| 06e453dd05 | |||
| 0347877290 | |||
| b464526d5e | |||
| 361b1cbad4 | |||
| 56a866fca7 | |||
| 49e0d68374 | |||
| 0ccd05e605 | |||
| 916e4586c5 | |||
| c9ffd0b4bb | |||
| 1d2f6f46a4 | |||
| 4af6d856b9 | |||
| 6fd4294391 | |||
| 88b2b85f2a | |||
| 2c1dff6ac8 | |||
| 481b42f563 | |||
| 597c321009 | |||
| 76651f75d8 | |||
| 3d8bae55a1 | |||
| 4b6869e367 | |||
| 477ba7c081 | |||
| 5b6d9725b8 | |||
| 25c3cea115 | |||
| d90601276f | |||
| 4f692bc698 | |||
| d8dd02eef0 | |||
| 8ad65ae233 | |||
| eabbb4569b | |||
| 49888b771d | |||
| 2b1c1cd052 | |||
| 61884e67ec | |||
| 9a2f028843 | |||
| 2b56acf164 | |||
| 98b67dcc28 | |||
| 500dfa3107 | |||
| c4efcfd2db | |||
| 81ee6bbcf6 | |||
| e4e2e76e06 | |||
| f847862e84 | |||
| 427dbeafde | |||
| 99ac85b40e | |||
| 020388baed | |||
| 4ade79de4f | |||
| 870dda9b8b | |||
| 27dd5298f7 | |||
| 6d5d406ce9 | |||
| ffb5e7e6f7 | |||
| 0de101c89f | |||
| bd3a0766e1 | |||
| f536cc8f8a | |||
| 826c0495fc | |||
| 9eac541ce5 |
@@ -7,3 +7,5 @@ syntax:glob
|
||||
MyTracksTest/annotations.log
|
||||
**/*.pyc
|
||||
**/*.pyo
|
||||
syntax: glob
|
||||
MyTracksTest/hs_err_pid*.log
|
||||
|
||||
+10
-2
@@ -3,8 +3,16 @@
|
||||
<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="lib" path="libs/google-api-client/commons-codec-1.3.jar"/>
|
||||
<classpathentry kind="lib" path="libs/google-api-client/commons-logging-1.1.1.jar"/>
|
||||
<classpathentry kind="lib" path="libs/google-api-client/google-api-client-1.5.0-beta.jar"/>
|
||||
<classpathentry kind="lib" path="libs/google-api-client/google-http-client-1.5.0-beta.jar"/>
|
||||
<classpathentry kind="lib" path="libs/google-api-client/google-oauth-client-1.5.0-beta.jar"/>
|
||||
<classpathentry kind="lib" path="libs/google-api-client/gson-1.6.jar"/>
|
||||
<classpathentry kind="lib" path="libs/google-api-client/guava-r09.jar"/>
|
||||
<classpathentry kind="lib" path="libs/google-api-client/jackson-core-asl-1.6.7.jar"/>
|
||||
<classpathentry kind="lib" path="libs/google-api-client/jsr305-1.3.9.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"/>
|
||||
|
||||
+41
-40
@@ -1,40 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>MyTracks</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
<linkedResources>
|
||||
<link>
|
||||
<name>MyTracksLib_src</name>
|
||||
<type>2</type>
|
||||
<locationURI>_android_MyTracksLib_e2802071/src</locationURI>
|
||||
</link>
|
||||
</linkedResources>
|
||||
</projectDescription>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>MyTracks</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
<project>MyTracksLib</project>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
<linkedResources>
|
||||
<link>
|
||||
<name>MyTracksLib_src</name>
|
||||
<type>2</type>
|
||||
<locationURI>_android_MyTracksLib_e2802071/src</locationURI>
|
||||
</link>
|
||||
</linkedResources>
|
||||
</projectDescription>
|
||||
|
||||
@@ -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
|
||||
+141
-43
@@ -17,10 +17,11 @@ 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="28"
|
||||
android:versionName="1.1.5">
|
||||
android:versionCode="33"
|
||||
android:versionName="1.1.10">
|
||||
<application android:icon="@drawable/arrow_icon"
|
||||
android:label="@string/app_name"
|
||||
android:name="com.google.android.apps.mytracks.MyTracksApplication"
|
||||
android:backupAgent="com.google.android.apps.mytracks.io.backup.MyTracksBackupAgent">
|
||||
<uses-library android:name="com.google.android.maps" />
|
||||
|
||||
@@ -44,6 +45,120 @@ 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.DeleteTrack"
|
||||
android:label="@string/deletetrack_title"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar"
|
||||
android:noHistory="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.DELETE" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<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 +167,6 @@ limitations under the License.
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name="com.google.android.apps.mytracks.MapActivity"
|
||||
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.TrackList"
|
||||
android:label="Recorded Tracks" />
|
||||
|
||||
<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" />
|
||||
|
||||
<activity android:name="com.google.android.apps.mytracks.WaypointDetails"
|
||||
android:label="@string/waypointdetails_title" />
|
||||
|
||||
<activity android:name="com.google.android.apps.mytracks.SettingsActivity"
|
||||
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,10 +178,23 @@ limitations under the License.
|
||||
android:exported="true"
|
||||
android:permission="com.google.android.apps.mytracks.WRITE_TRACK_DATA" />
|
||||
|
||||
<service android:name="com.google.android.apps.mytracks.services.ControlRecordingService"
|
||||
android:exported="false" />
|
||||
|
||||
<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" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="android.appwidget.provider"
|
||||
android:resource="@xml/track_widget_info" />
|
||||
</receiver>
|
||||
</application>
|
||||
|
||||
@@ -114,6 +204,7 @@ limitations under the License.
|
||||
<!-- 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" />
|
||||
@@ -142,7 +233,7 @@ limitations under the License.
|
||||
android:permissionGroup="android.permission-group.LOCATION"
|
||||
android:label="@string/notification_permission_label"
|
||||
android:description="@string/notification_permission_description"
|
||||
android:protectionLevel="normal" />
|
||||
android:protectionLevel="dangerous" />
|
||||
<!-- Permission to read raw track data (points, etc.) -->
|
||||
<permission android:name="com.google.android.apps.mytracks.READ_TRACK_DATA"
|
||||
android:permissionGroup="android.permission-group.LOCATION"
|
||||
@@ -156,10 +247,17 @@ limitations under the License.
|
||||
android:description="@string/write_tracks_permission_description"
|
||||
android:protectionLevel="dangerous" />
|
||||
|
||||
<!-- Permission to get MyTracks broadcasts. For internal MyTracks communication. -->
|
||||
<permission android:name="com.google.android.apps.mytracks.MYTRACKS_NOTIFICATIONS"
|
||||
android:permissionGroup="android.permission-group.LOCATION"
|
||||
android:label="@string/mytracks_notifications_permission_label"
|
||||
android:description="@string/mytracks_notifications_permission_description"
|
||||
android:protectionLevel="signature" />
|
||||
|
||||
<!-- We read and write raw track data, obviously. -->
|
||||
<uses-permission android:name="com.google.android.apps.mytracks.READ_TRACK_DATA" />
|
||||
<uses-permission android:name="com.google.android.apps.mytracks.WRITE_TRACK_DATA" />
|
||||
<uses-permission android:name="com.google.android.apps.mytracks.TRACK_NOTIFICATIONS" />
|
||||
<uses-permission android:name="com.google.android.apps.mytracks.MYTRACKS_NOTIFICATIONS" />
|
||||
|
||||
<!-- Features required -->
|
||||
<uses-feature android:name="android.hardware.location" android:required="true"/>
|
||||
|
||||
@@ -10,10 +10,8 @@
|
||||
# Indicates whether an apk should be generated for each density.
|
||||
split.density=false
|
||||
# Project target.
|
||||
target=Google Inc.:Google APIs:11
|
||||
target=Google Inc.:Google APIs:13
|
||||
android.library.reference.1=../MyTracksLib/
|
||||
|
||||
# ProGuard is turned off while we investigate the removal of code that
|
||||
# isn't actually dead from Fusion Tables. See issue 303 for an example of
|
||||
# the result of that removal.
|
||||
#proguard.config=proguard.cfg
|
||||
# Enable proguard.
|
||||
proguard.config=proguard.cfg
|
||||
|
||||
@@ -3,15 +3,20 @@ own licenses, which allow their usage for the My Tracks application. Any other
|
||||
applications that wish to use these files should consult the appropriate
|
||||
licenses or the JAR's authors.
|
||||
|
||||
References are provided to the libraries:
|
||||
google-api-client/
|
||||
- see http://code.google.com/p/google-api-java-client/.
|
||||
- contains Google API client library, google-api-client-1.5.0-beta.jar, and its
|
||||
dependencies.
|
||||
- google-api-client-1.5.0-beta.jar depends on protobuf-java-2.2.0.jar, however,
|
||||
MyTracksLib already includes protobuf-java.2.3.0-lite.jar. Thus using the
|
||||
newer version, protobuf-java.2.3.0-lite.jar.
|
||||
- google-api-client-1.5.0-beta.jar also depends on xpp3-1.1.4c.jar, however,
|
||||
some of its classes are already included in the android framework, thus not
|
||||
including xpp3-1.1.4c.jar.
|
||||
|
||||
accounts.jar (Android accounts library):
|
||||
http://code.google.com/p/libs-for-android/wiki/AccountsLibrary
|
||||
google-common.jar
|
||||
|
||||
google-api-client-*.jar (GData client):
|
||||
http://code.google.com/p/google-api-java-client/
|
||||
googleloginclient-helper.jar
|
||||
|
||||
google-common.jar,
|
||||
googleloginclient-helper.jar,
|
||||
libmymaps.jar (Google My Maps upload library):
|
||||
Licensed exclusively for use in My Tracks and derived Android applications.
|
||||
libGoogleAnalytics.jar
|
||||
- see http://code.google.com/mobile/analytics/docs/.
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -14,6 +14,10 @@
|
||||
-dontwarn com.google.android.gsf.**
|
||||
-dontwarn org.codehaus.**
|
||||
-dontwarn com.google.appengine.**
|
||||
-dontwarn org.apache.avalon.framework.logger.**
|
||||
-dontwarn org.apache.log.**
|
||||
-dontwarn org.apache.log4j.**
|
||||
-dontwarn javax.servlet.**
|
||||
|
||||
# Make our stack traces useful
|
||||
# Line numbers will be correct, file names will be replaced by "MT" since the
|
||||
@@ -51,3 +55,15 @@
|
||||
-keep class * implements android.os.Parcelable {
|
||||
public static final android.os.Parcelable$Creator *;
|
||||
}
|
||||
|
||||
# Needed by google-api-client to keep generic types and @Key annotations accessed via reflection
|
||||
|
||||
-keepclassmembers class * {
|
||||
@com.google.api.client.util.Key <fields>;
|
||||
}
|
||||
|
||||
-keepattributes Signature,RuntimeVisibleAnnotations,AnnotationDefault
|
||||
|
||||
# Needed by Guava
|
||||
|
||||
-dontwarn sun.misc.Unsafe
|
||||
|
||||
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 |
@@ -40,7 +40,9 @@ limitations under the License.
|
||||
android:singleLine="true"
|
||||
android:autoText="true"
|
||||
android:capitalize="words"
|
||||
android:selectAllOnFocus="true"/>
|
||||
android:selectAllOnFocus="true"
|
||||
android:hint="@string/trackdetails_name_hint"
|
||||
android:imeOptions="actionNext"/>
|
||||
</LinearLayout>
|
||||
<TextView android:text="@string/trackdetails_category"
|
||||
android:layout_width="fill_parent"
|
||||
@@ -48,7 +50,9 @@ limitations under the License.
|
||||
<AutoCompleteTextView android:id="@+id/trackdetails_category"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"/>
|
||||
android:singleLine="true"
|
||||
android:hint="@string/trackdetails_category_hint"
|
||||
android:imeOptions="actionNext"/>
|
||||
<TextView android:text="@string/trackdetails_description"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
@@ -61,7 +65,9 @@ limitations under the License.
|
||||
android:selectAllOnFocus="true"
|
||||
android:maxLines="50"
|
||||
android:gravity="top"
|
||||
android:layout_weight="1"/>
|
||||
android:layout_weight="1"
|
||||
android:hint="@string/trackdetails_description_hint"
|
||||
android:imeOptions="actionDone"/>
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
|
||||
@@ -127,26 +127,24 @@ limitations under the License.
|
||||
</TableLayout>
|
||||
</ScrollView>
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/list_bar"
|
||||
android:padding="3dip">
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="fill_parent"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="2dip"
|
||||
android:paddingRight="2dip"
|
||||
android:paddingTop="4dip">
|
||||
<!-- left spacer -->
|
||||
<LinearLayout style="@style/DialogButtonSpacer"/>
|
||||
<Button android:id="@+id/sendtogoogle_cancel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dip"
|
||||
android:layout_gravity="right"
|
||||
android:layout_gravity="left"
|
||||
android:text="@string/cancel"
|
||||
android:textSize="14dip"/>
|
||||
<TextView
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"/>
|
||||
style="@style/DialogButton"/>
|
||||
<Button android:id="@+id/sendtogoogle_send_now"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dip"
|
||||
android:layout_gravity="right"
|
||||
android:text="@string/sendtogoogle_send_now"
|
||||
android:textSize="14dip"/>
|
||||
style="@style/DialogButton"/>
|
||||
<!-- right spacer -->
|
||||
<LinearLayout style="@style/DialogButtonSpacer"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
@@ -50,7 +50,9 @@ limitations under the License.
|
||||
android:singleLine="true"
|
||||
android:autoText="true"
|
||||
android:capitalize="words"
|
||||
android:selectAllOnFocus="true"/>
|
||||
android:selectAllOnFocus="true"
|
||||
android:hint="@string/waypointdetails_name_hint"
|
||||
android:imeOptions="actionNext"/>
|
||||
</LinearLayout>
|
||||
<LinearLayout android:id="@+id/waypointdetails_description_layout"
|
||||
android:orientation="vertical"
|
||||
@@ -65,7 +67,9 @@ limitations under the License.
|
||||
<AutoCompleteTextView android:id="@+id/waypointdetails_category"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"/>
|
||||
android:singleLine="true"
|
||||
android:hint="@string/waypointdetails_category_hint"
|
||||
android:imeOptions="actionNext"/>
|
||||
<TextView android:text="@string/waypointdetails_description"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
@@ -79,7 +83,9 @@ limitations under the License.
|
||||
android:minLines="5"
|
||||
android:maxLines="50"
|
||||
android:gravity="top"
|
||||
android:layout_weight="1"/>
|
||||
android:layout_weight="1"
|
||||
android:hint="@string/waypointdetails_description_hint"
|
||||
android:imeOptions="actionDone"/>
|
||||
</LinearLayout>
|
||||
|
||||
<TableLayout android:id="@+id/waypoint_stats"
|
||||
|
||||
@@ -125,6 +125,27 @@ limitations under the License.
|
||||
android:text="@string/bpm" />
|
||||
</TableRow>
|
||||
|
||||
<!-- Battery Level -->
|
||||
<TableRow
|
||||
android:padding="1dip">
|
||||
<TextView
|
||||
android:layout_column="1"
|
||||
android:layout_span="3"
|
||||
android:text="@string/battery_level" />
|
||||
</TableRow>
|
||||
<TableRow
|
||||
android:background="@color/stat_label_background">
|
||||
<TextView
|
||||
style="@style/StatsRegister.Big"
|
||||
android:id="@+id/battery_level_register"
|
||||
android:layout_column="1"
|
||||
android:layout_span="4" />
|
||||
<TextView
|
||||
style="@style/StatsUnitSolo"
|
||||
android:layout_column="5"
|
||||
android:text="@string/percent" />
|
||||
</TableRow>
|
||||
|
||||
</TableLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
@@ -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>
|
||||
@@ -284,11 +284,4 @@ limitations under the License.
|
||||
<item>punt de referència</item>
|
||||
</array>
|
||||
|
||||
<array name="sensor_type_options">
|
||||
<item>Cap</item>
|
||||
<item>ANT+ Sensors</item>
|
||||
<item>SRM ANT+ Bridge</item>
|
||||
<item>Zephyr Bluetooth</item>
|
||||
</array>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -152,14 +152,20 @@ limitations under the License.
|
||||
<!-- MyTracks Details -->
|
||||
<string name="trackdetails_title">Detalls de la ruta</string>
|
||||
<string name="trackdetails_name">Nom de la ruta</string>
|
||||
<string name="trackdetails_name_hint">Nom de la ruta</string>
|
||||
<string name="trackdetails_description">Descripció de la ruta</string>
|
||||
<string name="trackdetails_description_hint">Descripció de la ruta</string>
|
||||
<string name="trackdetails_category">Tipus d\'activitat (p.e. senderisme, bicicleta, còrrer, escalada...)</string>
|
||||
<string name="trackdetails_category_hint">Tipus d\'activitat</string>
|
||||
|
||||
<!-- MyTracks Waypoint Details -->
|
||||
<string name="waypointdetails_title">Detalls del marcador</string>
|
||||
<string name="waypointdetails_name">Nom del marcador</string>
|
||||
<string name="waypointdetails_name_hint">Nom del marcador</string>
|
||||
<string name="waypointdetails_description">Descripció del marcador</string>
|
||||
<string name="waypointdetails_description_hint">Descripció del marcador</string>
|
||||
<string name="waypointdetails_category">Tipus de marcador (e.g. edifici, sot, vista...)</string>
|
||||
<string name="waypointdetails_category_hint">Tipus de marcador</string>
|
||||
|
||||
<!-- MyTracks Settings -->
|
||||
<string name="mytracks_settings">Paràmetres de My Tracks</string>
|
||||
@@ -409,4 +415,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>
|
||||
|
||||
@@ -154,14 +154,20 @@ limitations under the License.
|
||||
<!-- MyTracks Details -->
|
||||
<string name="trackdetails_title">Trackdetails</string>
|
||||
<string name="trackdetails_name">Name</string>
|
||||
<string name="trackdetails_name_hint">Name</string>
|
||||
<string name="trackdetails_description">Beschreibung</string>
|
||||
<string name="trackdetails_description_hint">Beschreibung</string>
|
||||
<string name="trackdetails_category">Aktivität (z. B. Wandern, Fahrradfahren, Laufen, Klettern…)</string>
|
||||
<string name="trackdetails_category_hint">Aktivität</string>
|
||||
|
||||
<!-- MyTracks Waypoint Details -->
|
||||
<string name="waypointdetails_title">Wegpunktdetails</string>
|
||||
<string name="waypointdetails_name">Wegpunktname</string>
|
||||
<string name="waypointdetails_name_hint">Wegpunktname</string>
|
||||
<string name="waypointdetails_description">Wegpunktbeschreibung</string>
|
||||
<string name="waypointdetails_description_hint">Wegpunktbeschreibung</string>
|
||||
<string name="waypointdetails_category">Art des Wegpunktes (z. B. Gebäude, Schlagloch, Sehenswürdigkeit…)</string>
|
||||
<string name="waypointdetails_category_hint">Art des Wegpunktes</string>
|
||||
|
||||
<!-- MyTracks Settings -->
|
||||
<string name="mytracks_settings">Einstellungen für My Tracks</string>
|
||||
@@ -333,6 +339,7 @@ limitations under the License.
|
||||
|
||||
<!--string name="revolutions_per_minute">rpm</string-->
|
||||
<!--string name="bpm">bpm</string-->
|
||||
<string name="battery_level">Akkukapazität</string>
|
||||
|
||||
<!-- Stats Labels -->
|
||||
<string name="moving_time_label">Zeit in Bewegung</string>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -138,14 +138,20 @@ limitations under the License.
|
||||
<!-- MyTracks Details -->
|
||||
<string name="trackdetails_title">Detalles del recorrido</string>
|
||||
<string name="trackdetails_name">Nombre del recorrido</string>
|
||||
<string name="trackdetails_name_hint">Nombre del recorrido</string>
|
||||
<string name="trackdetails_description">Descripción del recorrido</string>
|
||||
<string name="trackdetails_description_hint">Descripción del recorrido</string>
|
||||
<string name="trackdetails_category">Tipo de actividad (por ejemplo, ciclismo, alpinismo...)</string>
|
||||
<string name="trackdetails_category_hint">Tipo de actividad</string>
|
||||
|
||||
<!-- MyTracks Waypoint Details -->
|
||||
<string name="waypointdetails_title">Detalles de señal</string>
|
||||
<string name="waypointdetails_name">Nombre de señal</string>
|
||||
<string name="waypointdetails_name_hint">Nombre de señal</string>
|
||||
<string name="waypointdetails_description">Descripción de señal</string>
|
||||
<string name="waypointdetails_description_hint">Descripción de señal</string>
|
||||
<string name="waypointdetails_category">Tipo de señal (por ejemplo, edificio, bache, atracción...)</string>
|
||||
<string name="waypointdetails_category_hint">Tipo de señal</string>
|
||||
|
||||
<!-- MyTracks Settings -->
|
||||
<string name="mytracks_settings">Configuraciones de My Tracks</string>
|
||||
|
||||
@@ -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>
|
||||
@@ -0,0 +1,516 @@
|
||||
<?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 <a href=\'http://mytracks.appspot.com\'>My Tracks</a> on Android.</string>
|
||||
|
||||
<!-- Text and links when uploading to Google My Maps -->
|
||||
<string name="my_map_link">Created by <a href=\'http://mytracks.appspot.com\'>My Tracks</a> 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_name_hint">Reitin nimi</string>
|
||||
<string name="trackdetails_description">Reitin kuvaus</string>
|
||||
<string name="trackdetails_description_hint">Reitin kuvaus</string>
|
||||
<string name="trackdetails_category">Liikunnan muoto (esim. hölkkä, pyöräily, juoksu...)</string>
|
||||
<string name="trackdetails_category_hint">Liikunnan muoto</string>
|
||||
|
||||
<!-- MyTracks Waypoint Details -->
|
||||
<string name="waypointdetails_title">Merkinnän tiedot</string>
|
||||
<string name="waypointdetails_name">Merkinnän nimi</string>
|
||||
<string name="waypointdetails_name_hint">Merkinnän nimi</string>
|
||||
<string name="waypointdetails_description">Merkinnän kuvaus</string>
|
||||
<string name="waypointdetails_description_hint">Merkinnän kuvaus</string>
|
||||
<string name="waypointdetails_category">Merkinnän tyyppi (esim. rakennus, kuoppa, nähtävyys...)</string>
|
||||
<string name="waypointdetails_category_hint">Merkinnän tyyppi</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>
|
||||
<string name="battery_level">Akku</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>
|
||||
@@ -291,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>
|
||||
|
||||
@@ -144,14 +144,20 @@ limitations under the License.
|
||||
<!-- MyTracks Details -->
|
||||
<string name="trackdetails_title">Détails parcours</string>
|
||||
<string name="trackdetails_name">Nom du parcours</string>
|
||||
<string name="trackdetails_name_hint">Nom du parcours</string>
|
||||
<string name="trackdetails_description">Description du parcours</string>
|
||||
<string name="trackdetails_description_hint">Description du parcours</string>
|
||||
<string name="trackdetails_category">Type d\'activité (randonnée, cyclisme, jogging, escalade...)</string>
|
||||
<string name="trackdetails_category_hint">Type d\'activité</string>
|
||||
|
||||
<!-- MyTracks Waypoint Details -->
|
||||
<string name="waypointdetails_title">Details balise</string>
|
||||
<string name="waypointdetails_name">Nom de la balise</string>
|
||||
<string name="waypointdetails_name_hint">Nom de la balise</string>
|
||||
<string name="waypointdetails_description">Description balise</string>
|
||||
<string name="waypointdetails_description_hint">Description balise</string>
|
||||
<string name="waypointdetails_category">Nom de balise (par ex.: immeuble, boutique, point de vue...)</string>
|
||||
<string name="waypointdetails_category_hint">Nom de balise</string>
|
||||
|
||||
<!-- MyTracks Settings -->
|
||||
<string name="mytracks_settings">Paramètres My Tracks</string>
|
||||
@@ -397,6 +403,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>
|
||||
|
||||
@@ -147,14 +147,20 @@ limitations under the License.
|
||||
<!-- MyTracks Details -->
|
||||
<string name="trackdetails_title">Dettagli del percorso</string>
|
||||
<string name="trackdetails_name">Nome del percorso</string>
|
||||
<string name="trackdetails_name_hint">Nome del percorso</string>
|
||||
<string name="trackdetails_description">Descrizione del percorso</string>
|
||||
<string name="trackdetails_description_hint">Descrizione del percorso</string>
|
||||
<string name="trackdetails_category">Tipo di attività (ad es. escursionismo, ciclismo, corsa, arrampicata...)</string>
|
||||
<string name="trackdetails_category_hint">Tipo di attività</string>
|
||||
|
||||
<!-- MyTracks Waypoint Details -->
|
||||
<string name="waypointdetails_title">Dettagli sul segnaposto</string>
|
||||
<string name="waypointdetails_name">Nome del segnaposto</string>
|
||||
<string name="waypointdetails_name_hint">Nome del segnaposto</string>
|
||||
<string name="waypointdetails_description">Descrizione del segnaposto</string>
|
||||
<string name="waypointdetails_description_hint">Descrizione del segnaposto</string>
|
||||
<string name="waypointdetails_category">Tipo di segnaposto (ad es. edificio, buca, vista...)</string>
|
||||
<string name="waypointdetails_category_hint">Tipo di segnaposto</string>
|
||||
|
||||
<!-- MyTracks Settings -->
|
||||
<string name="mytracks_settings">Impostazioni di My Tracks</string>
|
||||
|
||||
@@ -272,11 +272,4 @@ limitations under the License.
|
||||
<item>ウェイポイント</item>
|
||||
</array>
|
||||
|
||||
<array name="sensor_type_options">
|
||||
<item>なし</item>
|
||||
<item>ANT+ センサー</item>
|
||||
<item>SRM ANT+ ブリッジ</item>
|
||||
<item>Zephyr Bluetooth</item>
|
||||
</array>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -159,8 +159,8 @@ limitations under the License.
|
||||
$2 : Attempted imports
|
||||
$3 : MyTracks gpx path
|
||||
-->
|
||||
<string name="import_done">%3$s からGPXファイル %2$d件のうち %1$d件をインポートしました</string>
|
||||
<string name="import_empty">%s ではGPXファイルがありません.SDカードを読み込めないかディレクトリにGPXファイルが無いかも知れません.</string>
|
||||
<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 -->
|
||||
@@ -176,14 +176,20 @@ limitations under the License.
|
||||
<!-- MyTracks Details -->
|
||||
<string name="trackdetails_title">トラック詳細</string>
|
||||
<string name="trackdetails_name">トラック名</string>
|
||||
<string name="trackdetails_name_hint">トラック名</string>
|
||||
<string name="trackdetails_description">トラック説明</string>
|
||||
<string name="trackdetails_description_hint">トラック説明</string>
|
||||
<string name="trackdetails_category">活動タイプ(ハイキング, サイクリング、ランニング、登山...)</string>
|
||||
<string name="trackdetails_category_hint">活動タイプ</string>
|
||||
|
||||
<!-- MyTracks Waypoint Details -->
|
||||
<string name="waypointdetails_title">マーカー詳細</string>
|
||||
<string name="waypointdetails_name">マーカー名</string>
|
||||
<string name="waypointdetails_name_hint">マーカー名</string>
|
||||
<string name="waypointdetails_description">マーカー説明</string>
|
||||
<string name="waypointdetails_description_hint">マーカー説明</string>
|
||||
<string name="waypointdetails_category">マーカータイプ(建物、洞穴、名所...)</string>
|
||||
<string name="waypointdetails_category_hint">マーカータイプ</string>
|
||||
|
||||
<!-- MyTracks Settings -->
|
||||
<string name="mytracks_settings">My Tracks設定</string>
|
||||
@@ -463,6 +469,11 @@ 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>
|
||||
|
||||
@@ -149,14 +149,20 @@ limitations under the License.
|
||||
<!-- MyTracks Details -->
|
||||
<string name="trackdetails_title">Szczegóły trasy</string>
|
||||
<string name="trackdetails_name">Nazwa trasy</string>
|
||||
<string name="trackdetails_name_hint">Nazwa trasy</string>
|
||||
<string name="trackdetails_description">Opis trasy</string>
|
||||
<string name="trackdetails_description_hint">Opis trasy</string>
|
||||
<string name="trackdetails_category">Typ aktywności (np. wspinanie, jazda rowerem, bieganie...)</string>
|
||||
<string name="trackdetails_category_hint">Typ aktywności</string>
|
||||
|
||||
<!-- MyTracks Waypoint Details -->
|
||||
<string name="waypointdetails_title">Szczegóły znacznika</string>
|
||||
<string name="waypointdetails_name">Nazwa znacznika</string>
|
||||
<string name="waypointdetails_name_hint">Nazwa znacznika</string>
|
||||
<string name="waypointdetails_description">Opis znacznika</string>
|
||||
<string name="waypointdetails_description_hint">Opis znacznika</string>
|
||||
<string name="waypointdetails_category">Typ znacznika (np. budynek, jaskinia, punkt widokowy...)</string>
|
||||
<string name="waypointdetails_category_hint">Typ znacznika</string>
|
||||
|
||||
<!-- MyTracks Settings -->
|
||||
<string name="mytracks_settings">Ustawienia My Tracks</string>
|
||||
|
||||
@@ -144,14 +144,20 @@ limitations under the License.
|
||||
<!-- MyTracks Details -->
|
||||
<string name="trackdetails_title">Detalhes do Caminho</string>
|
||||
<string name="trackdetails_name">Nome do Caminho</string>
|
||||
<string name="trackdetails_name_hint">Nome do Caminho</string>
|
||||
<string name="trackdetails_description">Descrição do Caminho</string>
|
||||
<string name="trackdetails_description_hint">Descrição do Caminho</string>
|
||||
<string name="trackdetails_category">Tipo de Atividade (por ex. caminhada, ciclismo, escalada...)</string>
|
||||
<string name="trackdetails_category_hint">Tipo de Atividade</string>
|
||||
|
||||
<!-- MyTracks Waypoint Details -->
|
||||
<string name="waypointdetails_title">Detalhes do Marcador</string>
|
||||
<string name="waypointdetails_name">Nome do Marcador</string>
|
||||
<string name="waypointdetails_name_hint">Nome do Marcador</string>
|
||||
<string name="waypointdetails_description">Descrição do Marcador</string>
|
||||
<string name="waypointdetails_description_hint">Descrição do Marcador</string>
|
||||
<string name="waypointdetails_category">Tipo do Marcador (por ex. Prédio, Mirante, Cachoeira...)</string>
|
||||
<string name="waypointdetails_category_hint">Tipo do Marcador</string>
|
||||
|
||||
<!-- MyTracks Settings -->
|
||||
<string name="mytracks_settings">Configurações do My Tracks</string>
|
||||
|
||||
@@ -272,11 +272,4 @@ limitations under the License.
|
||||
<item>путевая точка</item>
|
||||
</array>
|
||||
|
||||
<array name="sensor_type_options">
|
||||
<item>Нет</item>
|
||||
<item>ANT+ Sensors</item>
|
||||
<item>SRM ANT+ Bridge</item>
|
||||
<item>Zephyr Bluetooth</item>
|
||||
</array>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -162,8 +162,8 @@ limitations under the License.
|
||||
$2 : Attempted imports
|
||||
$3 : MyTracks gpx path
|
||||
-->
|
||||
<string name="import_done">Импортировано %1$d из %2$d GPX файлов с %3$s</string>
|
||||
<string name="import_empty">GPX файлы не найденны в %s. Возможно не читается SD-карта или каталог не содержит GPX файлы.</string>
|
||||
<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 -->
|
||||
@@ -179,14 +179,20 @@ limitations under the License.
|
||||
<!-- MyTracks Details -->
|
||||
<string name="trackdetails_title">Трек детали</string>
|
||||
<string name="trackdetails_name">Название трека</string>
|
||||
<string name="trackdetails_name_hint">Название трека</string>
|
||||
<string name="trackdetails_description">Описание трека</string>
|
||||
<string name="trackdetails_description_hint">Описание трека</string>
|
||||
<string name="trackdetails_category">Тип деятельности (например: пешая прогулка, велосипедная прогулка, бег, восхождение...)</string>
|
||||
<string name="trackdetails_category_hint">Тип деятельности</string>
|
||||
|
||||
<!-- MyTracks Waypoint Details -->
|
||||
<string name="waypointdetails_title">Маркер детали</string>
|
||||
<string name="waypointdetails_name">Имя маркера</string>
|
||||
<string name="waypointdetails_name_hint">Имя маркера</string>
|
||||
<string name="waypointdetails_description">Описание маркера</string>
|
||||
<string name="waypointdetails_description_hint">Описание маркера</string>
|
||||
<string name="waypointdetails_category">Тип маркера (например: здание, выбоина, достопримечательность...)</string>
|
||||
<string name="waypointdetails_category_hint">Тип маркера</string>
|
||||
|
||||
<!-- MyTracks Settings -->
|
||||
<string name="mytracks_settings">Настройки My Tracks</string>
|
||||
@@ -490,6 +496,11 @@ 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+ Bridge</string>
|
||||
|
||||
<!-- Manifest description (not seen inside the app) -->
|
||||
<string name="notification_permission_label">получать уведомления о записи трека</string>
|
||||
<string name="read_tracks_permission_label">чтение записанных данных трека</string>
|
||||
|
||||
@@ -149,14 +149,20 @@ limitations under the License.
|
||||
<!-- MyTracks Details -->
|
||||
<string name="trackdetails_title">Spårdetaljer</string>
|
||||
<string name="trackdetails_name">Spårnamn</string>
|
||||
<string name="trackdetails_name_hint">Spårnamn</string>
|
||||
<string name="trackdetails_description">Spårbeskrivning</string>
|
||||
<string name="trackdetails_description_hint">Spårbeskrivning</string>
|
||||
<string name="trackdetails_category">Aktivitetstyp (t ex vandring, cyckling, löpning, klättring...)</string>
|
||||
<string name="trackdetails_category_hint">Aktivitetstyp</string>
|
||||
|
||||
<!-- MyTracks Waypoint Details -->
|
||||
<string name="waypointdetails_title">Markördetaljer</string>
|
||||
<string name="waypointdetails_name">Markörnamn</string>
|
||||
<string name="waypointdetails_name_hint">Markörnamn</string>
|
||||
<string name="waypointdetails_description">Markörbeskrivning</string>
|
||||
<string name="waypointdetails_description_hint">Markörbeskrivning</string>
|
||||
<string name="waypointdetails_category">Markörtyp (e.g. byggnad, grop, sevärdhet...)</string>
|
||||
<string name="waypointdetails_category_hint">Markörtyp</string>
|
||||
|
||||
<!-- MyTracks Settings -->
|
||||
<string name="mytracks_settings">My Tracks inställningar</string>
|
||||
|
||||
@@ -170,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>
|
||||
|
||||
@@ -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 平台的 <a href=\'http://mytracks.appspot.com\'>My Tracks</a> 创建.</string>
|
||||
|
||||
<!-- Text and links when uploading to Google My Maps -->
|
||||
<string name="new_map_description">由 Android 上的 My Tracks 生成.</string>
|
||||
<string name="fusiontable_link">由 Android 上的 <a href=\'http://mytracks.appspot.com\'>My Tracks</a> 生成.</string>
|
||||
<string name="fusiontable_link">由 Android 上的 <a href=\'http://mytracks.appspot.com\'>My Tracks</a> 创建.</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>
|
||||
@@ -151,14 +180,20 @@ limitations under the License.
|
||||
<!-- MyTracks Details -->
|
||||
<string name="trackdetails_title">轨迹详细信息</string>
|
||||
<string name="trackdetails_name">轨迹名称</string>
|
||||
<string name="trackdetails_name_hint">轨迹名称</string>
|
||||
<string name="trackdetails_description">轨迹描述</string>
|
||||
<string name="trackdetails_description_hint">轨迹描述</string>
|
||||
<string name="trackdetails_category">活动类型 (例如: 徒步, 骑行, 跑步, 攀岩...)</string>
|
||||
<string name="trackdetails_category_hint">活动类型</string>
|
||||
|
||||
<!-- MyTracks Waypoint Details -->
|
||||
<string name="waypointdetails_title">标记详细信息</string>
|
||||
<string name="waypointdetails_name">标记名称</string>
|
||||
<string name="waypointdetails_name_hint">标记名称</string>
|
||||
<string name="waypointdetails_description">标记描述</string>
|
||||
<string name="waypointdetails_description_hint">标记描述</string>
|
||||
<string name="waypointdetails_category">标记类型 (例如: 建筑, 陷坑, 景点...)</string>
|
||||
<string name="waypointdetails_category_hint">标记类型</string>
|
||||
|
||||
<!-- MyTracks Settings -->
|
||||
<string name="mytracks_settings">My Tracks 设置</string>
|
||||
@@ -166,10 +201,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,14 +241,30 @@ 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>
|
||||
@@ -220,7 +272,6 @@ limitations under the License.
|
||||
<string name="settings_restore_from_sd">立即恢复</string>
|
||||
<string name="settings_restore_from_sd_summary">从 SD 存储卡恢复所有轨迹和设置</string>
|
||||
|
||||
<!-- Backups -->
|
||||
<string name="restore_overwrites_warning">从 SD 存储卡恢复备份数据将覆盖掉你当前的所有轨迹和设置. 确定要继续吗?</string>
|
||||
<string name="select_backup_to_restore">请选择要恢复的备份文件</string>
|
||||
<string name="no_backups">没有找到备份文件.</string>
|
||||
@@ -230,7 +281,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">我想你可能会对这个地图感兴趣:
|
||||
|
||||
@@ -239,7 +308,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>
|
||||
@@ -331,10 +399,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>
|
||||
|
||||
@@ -344,10 +415,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 -->
|
||||
@@ -395,4 +467,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>
|
||||
|
||||
@@ -170,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>
|
||||
@@ -272,11 +277,4 @@ limitations under the License.
|
||||
<item>way point</item>
|
||||
</array>
|
||||
|
||||
<array name="sensor_type_options">
|
||||
<item>None</item>
|
||||
<item>ANT+ Sensors</item>
|
||||
<item>SRM ANT+ Bridge</item>
|
||||
<item>Zephyr Bluetooth</item>
|
||||
</array>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -38,16 +38,6 @@ limitations under the License.
|
||||
<item>100</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>
|
||||
@@ -108,10 +98,19 @@ limitations under the License.
|
||||
<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>
|
||||
|
||||
@@ -119,4 +118,16 @@ limitations under the License.
|
||||
<item>@string/ant_sensor_type</item>
|
||||
<item>@string/srm_ant_bridge_sensor_type</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="track_color_mode_options">
|
||||
<item>@string/track_color_mode_none</item>
|
||||
<item>@string/track_color_mode_fixed</item>
|
||||
<item>@string/track_color_mode_dynamic</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="track_color_mode_values">
|
||||
<item>@string/none</item>
|
||||
<item>@string/track_color_mode_fixed</item>
|
||||
<item>@string/track_color_mode_dynamic</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
|
||||
@@ -47,4 +47,18 @@ 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>
|
||||
|
||||
<!-- Colors for dynamic track drawing -->
|
||||
<!-- Green -->
|
||||
<color name="slow_path">#F774DF00</color>
|
||||
|
||||
<!-- Blue -->
|
||||
<color name="normal_path">#F75858FA</color>
|
||||
|
||||
<!-- Red -->
|
||||
<color name="fast_path">#F7DF0101</color>
|
||||
</resources>
|
||||
|
||||
@@ -33,10 +33,28 @@ 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>
|
||||
|
||||
<!-- Symbols -->
|
||||
<string name="percent">%</string>
|
||||
|
||||
<!-- Intent actions -->
|
||||
<string name="save_intent_action">android.intent.action.SAVE</string>
|
||||
<string name="open_settings_screen">android.intent.action.settings.OPEN</string>
|
||||
<string name="start_new_track_action">com.google.android.apps.mytracks.START_NEW_TRACK</string>
|
||||
<string name="end_current_track_action">com.google.android.apps.mytracks.END_CURRENT_TRACK
|
||||
</string>
|
||||
|
||||
<!-- Permissions -->
|
||||
<!-- Permission for MyTracks notifications. -->
|
||||
<string name="mytracks_notifications_permission">com.google.android.apps.mytracks.MYTRACKS_NOTIFICATIONS</string>
|
||||
</resources>
|
||||
|
||||
@@ -15,7 +15,8 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<!-- Keys for application preferences - DO NOT TRANSLATE -->
|
||||
<!-- Keys for application preferences. Sorted alphabetically. - DO NOT TRANSLATE -->
|
||||
<string name="allow_access_key">allowAccess</string>
|
||||
<string name="announcement_frequency_key">announcementFrequency</string>
|
||||
<string name="ant_heart_rate_sensor_id_key">antHeartRateSensorId</string>
|
||||
<string name="ant_power_sensor_id_key">antPowerSensorId</string>
|
||||
@@ -35,22 +36,34 @@ limitations under the License.
|
||||
<string name="report_speed_key">reportSpeed</string>
|
||||
<string name="send_stats_and_points_key">sendStatsAndPoints</string>
|
||||
<string name="send_to_docs_key">sendToDocs</string>
|
||||
<string name="send_to_my_maps_key">sendToMyMaps</string>
|
||||
<string name="send_to_fusion_tables_key">sendToFusionTables</string>
|
||||
<string name="send_to_my_maps_key">sendToMyMaps</string>
|
||||
<string name="sensor_type_key">sensorType</string>
|
||||
<string name="share_url_only_key">shareUrlOnly</string>
|
||||
<string name="split_frequency_key">splitFrequency</string>
|
||||
<string name="timestamp_track_name_key">timestampTrackName</string>
|
||||
|
||||
<!-- Preference keys which keep transient state (not user preferences) - DO NOT TRANSLATE -->
|
||||
<string name="track_color_mode_dynamic_speed_variation_key">trackColorModeDynamicVariation
|
||||
</string>
|
||||
<string name="track_color_mode_fixed_speed_medium_display_key">trackColorModeFixedMediumDisplay
|
||||
</string>
|
||||
<string name="track_color_mode_fixed_speed_medium_key">trackColorModeFixedMedium</string>
|
||||
<string name="track_color_mode_fixed_speed_slow_display_key">trackColorModeFixedSlowDisplay
|
||||
</string>
|
||||
<string name="track_color_mode_fixed_speed_slow_key">trackColorModeFixedSlow</string>
|
||||
<string name="track_color_mode_key">trackColorMode</string>
|
||||
|
||||
<!-- Preference keys which keep transient state (not user preferences). Sorted alphabetically.
|
||||
- DO NOT TRANSLATE -->
|
||||
<string name="auto_resume_track_current_retry_key">autoResumeTrackCurrentRetry</string>
|
||||
<string name="recording_track_key">recordingTrack</string>
|
||||
<string name="selected_track_key">selectedTrack</string>
|
||||
|
||||
<!-- Keys for non-persisted preferences - DO NOT TRANSLATE -->
|
||||
<string name="backup_to_sd_key">backupToSd</string>
|
||||
<string name="restore_from_sd_key">restoreFromSd</string>
|
||||
<string name="reset_key">resetToDefaults</string>
|
||||
<string name="sensor_options_key">sensorOptions</string>
|
||||
<!-- Keys for non-persisted preferences. Sorted alphabetically. - DO NOT TRANSLATE -->
|
||||
<string name="ant_options_key">antOptions</string>
|
||||
<string name="backup_to_sd_key">backupToSd</string>
|
||||
<string name="display_settings_screen_key">displaySettingsScreen</string>
|
||||
<string name="reset_key">resetToDefaults</string>
|
||||
<string name="restore_from_sd_key">restoreFromSd</string>
|
||||
<string name="sensor_options_key">sensorOptions</string>
|
||||
<string name="track_color_mode_fixed_speed_options_key">trackColorModeFixedOptions</string>
|
||||
</resources>
|
||||
|
||||
@@ -83,7 +83,8 @@ limitations under the License.
|
||||
<string name="write_progress_message">Writing file to SD card. This may take a while.</string>
|
||||
<string name="progress_message_updating_track">Updating track statistics...</string>
|
||||
|
||||
<!-- Used by DeleteAllDataHandler -->
|
||||
<!-- Used by deletion actions -->
|
||||
<string name="deletetrack_title">Delete track</string>
|
||||
<string name="are_you_sure_question">Are you sure?</string>
|
||||
<string name="all_data_will_be_permanently_deleted">All tracks and markers will be deleted from this phone.</string>
|
||||
<string name="track_will_be_permanently_deleted">The track and its markers will be permanently deleted from this phone.</string>
|
||||
@@ -163,9 +164,12 @@ limitations under the License.
|
||||
$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>
|
||||
@@ -180,14 +184,20 @@ limitations under the License.
|
||||
<!-- MyTracks Details -->
|
||||
<string name="trackdetails_title">Track Details</string>
|
||||
<string name="trackdetails_name">Track Name</string>
|
||||
<string name="trackdetails_name_hint">Track Name</string>
|
||||
<string name="trackdetails_description">Track Description</string>
|
||||
<string name="trackdetails_description_hint">Track Description</string>
|
||||
<string name="trackdetails_category">Activity Type (e.g. hiking, cycling, running, climbing...)</string>
|
||||
<string name="trackdetails_category_hint">Activity Type</string>
|
||||
|
||||
<!-- MyTracks Waypoint Details -->
|
||||
<string name="waypointdetails_title">Marker Details</string>
|
||||
<string name="waypointdetails_name">Marker Name</string>
|
||||
<string name="waypointdetails_name_hint">Marker Name</string>
|
||||
<string name="waypointdetails_description">Marker Description</string>
|
||||
<string name="waypointdetails_description_hint">Marker Description</string>
|
||||
<string name="waypointdetails_category">Marker Type (e.g. Building, Pothole, Sight...)</string>
|
||||
<string name="waypointdetails_category_hint">Marker Type</string>
|
||||
|
||||
<!-- MyTracks Settings -->
|
||||
<string name="mytracks_settings">My Tracks Settings</string>
|
||||
@@ -198,6 +208,15 @@ limitations under the License.
|
||||
<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_allow_access">Allow access</string>
|
||||
<string name="settings_allow_access_summary_on">Other apps can read, write, start/stop recording
|
||||
MyTracks data.</string>
|
||||
<string name="settings_allow_access_summary_off">Other apps cannot read, write, start/stop
|
||||
recording MyTracks data.</string>
|
||||
<string name="settings_allow_access_dialog_message">Are you sure you want to allow other apps,
|
||||
including future apps, to control and access MyTracks data? There will be no further
|
||||
notification.</string>
|
||||
|
||||
<string name="settings_announcement_frequency">Announcement frequency</string>
|
||||
<string name="settings_announcement_frequency_summary">Minimum time between two voice announcements</string>
|
||||
|
||||
@@ -258,6 +277,17 @@ limitations under the License.
|
||||
<string name="bluetooth_sensor_summary">The bluetooth sensor to connect to</string>
|
||||
<string name="settings_modular_stats_display_title">Modular Stats Display</string>
|
||||
|
||||
<string name="settings_track_color_mode">Track Color Mode</string>
|
||||
<string name="settings_track_color_mode_summary">The way to color the track</string>
|
||||
<string name="settings_track_color_mode_fixed">Fixed</string>
|
||||
<string name="settings_track_color_mode_dynamic">Dynamic</string>
|
||||
<string name="settings_track_color_mode_fixed_speed_slow">Fixed Speed Slow</string>
|
||||
<string name="settings_track_color_mode_fixed_speed_slow_summary">Slow speed top value</string>
|
||||
<string name="settings_track_color_mode_fixed_speed_medium">Fixed Speed Medium</string>
|
||||
<string name="settings_track_color_mode_fixed_speed_medium_summary">Medium speed top value</string>
|
||||
<string name="settings_track_color_mode_dynamic_speed_variation">Dynamic Speed Variation</string>
|
||||
<string name="settings_track_color_mode_dynamic_speed_variation_summary">% Margin from average speed to consider medium speed</string>
|
||||
|
||||
<!-- Backups -->
|
||||
<string name="settings_backup">Backup (BETA)</string>
|
||||
<string name="settings_sd_backup">SD Card Backup</string>
|
||||
@@ -380,6 +410,7 @@ limitations under the License.
|
||||
|
||||
<string name="revolutions_per_minute">rpm</string>
|
||||
<string name="bpm">bpm</string>
|
||||
<string name="battery_level">Battery Level</string>
|
||||
|
||||
<!-- Stats Labels -->
|
||||
<string name="moving_time_label">Moving Time</string>
|
||||
@@ -472,7 +503,10 @@ limitations under the License.
|
||||
<string name="sensor_bluetooth_options_key">bluetoothSensorsEnabled</string>
|
||||
<string name="ant_options">ANT options</string>
|
||||
<string name="sensor_options">Sensor Options</string>
|
||||
|
||||
<string name="track_color_mode">Track Color Mode</string>
|
||||
<string name="fixed_speed_options">Fixed Speed Options</string>
|
||||
<string name="dynamic_speed_options">Dynamic Speed Options</string>
|
||||
|
||||
<!-- Bluetooth Sensor -->
|
||||
<string name="bluetooth_connected">Connected to %s</string>
|
||||
<string name="bluetooth_connecting">Bluetooth sensor connecting ...</string>
|
||||
@@ -492,10 +526,29 @@ limitations under the License.
|
||||
<string name="sending">Sending</string>
|
||||
|
||||
<!-- Manifest description (not seen inside the app) -->
|
||||
<string name="notification_permission_label">receive track recording notifications</string>
|
||||
<string name="read_tracks_permission_label">read recorded track data</string>
|
||||
<string name="write_tracks_permission_label">write recorded track data, start/stop recording tracks</string>
|
||||
<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>
|
||||
<string name="notification_permission_label">receive MyTracks notifications</string>
|
||||
<string name="mytracks_notifications_permission_label">receive MyTracks notifications</string>
|
||||
<string name="read_tracks_permission_label">read MyTracks data</string>
|
||||
<string name="write_tracks_permission_label">write data to MyTracks and start/stop MyTracks
|
||||
recording</string>
|
||||
<string name="notification_permission_description">Allows the application to receive notifications
|
||||
when MyTracks starts or stops a recording.</string>
|
||||
<string name="mytracks_notifications_permission_description">receive MyTracks notifications
|
||||
</string>
|
||||
<string name="read_tracks_permission_description">Allows the application to read MyTracks data.
|
||||
</string>
|
||||
<string name="write_tracks_permission_description">Allows the application to write data to
|
||||
MyTracks and start/stop MyTracks recording.</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>
|
||||
|
||||
<!-- Track Color Modes -->
|
||||
<string name="track_color_mode_none">None</string>
|
||||
<string name="track_color_mode_fixed">Fixed (BETA)</string>
|
||||
<string name="track_color_mode_dynamic">Dynamic (BETA)</string>
|
||||
</resources>
|
||||
|
||||
@@ -74,4 +74,33 @@ 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>
|
||||
|
||||
<!-- The style for the buttons on the bottom of a dialog. -->
|
||||
<style name="DialogButton">
|
||||
<item name="android:layout_height">48dip</item>
|
||||
<item name="android:layout_weight">1</item>
|
||||
<item name="android:layout_width">0dip</item>
|
||||
<item name="android:maxLines">2</item>
|
||||
<item name="android:textSize">14dip</item>
|
||||
</style>
|
||||
|
||||
<!-- The style for the spacer on the left and right of the dialog buttons. -->
|
||||
<style name="DialogButtonSpacer">
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:layout_weight">0.25</item>
|
||||
<item name="android:layout_width">0dip</item>
|
||||
<item name="android:orientation">horizontal</item>
|
||||
<item name="android:visibility">gone</item>
|
||||
</style>
|
||||
</resources>
|
||||
@@ -18,7 +18,8 @@ limitations under the License.
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- Display settings -->
|
||||
<PreferenceScreen android:title="@string/settings_display">
|
||||
<PreferenceScreen android:title="@string/settings_display"
|
||||
android:key="@string/display_settings_screen_key">
|
||||
<CheckBoxPreference
|
||||
android:key="@string/metric_units_key"
|
||||
android:title="@string/settings_metric_units"
|
||||
@@ -32,6 +33,58 @@ limitations under the License.
|
||||
android:summaryOn="@string/settings_report_speed_or_pace_summary_on"
|
||||
android:summaryOff="@string/settings_report_speed_or_pace_summary_off"
|
||||
android:defaultValue="true" />
|
||||
|
||||
<ListPreference android:key="@string/track_color_mode_key"
|
||||
android:title="@string/settings_track_color_mode"
|
||||
android:summary="@string/settings_track_color_mode_summary"
|
||||
android:entries="@array/track_color_mode_options"
|
||||
android:entryValues="@array/track_color_mode_values"
|
||||
android:defaultValue="@string/none"/>
|
||||
|
||||
<PreferenceCategory android:title="@string/fixed_speed_options"
|
||||
android:key="@string/track_color_mode_fixed_speed_options_key">
|
||||
<EditTextPreference android:key="@string/track_color_mode_fixed_speed_slow_key"
|
||||
android:title="@string/settings_track_color_mode_fixed_speed_slow"
|
||||
android:summary="@string/settings_track_color_mode_fixed_speed_slow_summary"
|
||||
android:defaultValue="9"
|
||||
android:inputType="number"
|
||||
android:maxLength="3">
|
||||
</EditTextPreference>
|
||||
|
||||
<EditTextPreference android:key="@string/track_color_mode_fixed_speed_slow_display_key"
|
||||
android:title="@string/settings_track_color_mode_fixed_speed_slow"
|
||||
android:summary="@string/settings_track_color_mode_fixed_speed_slow_summary"
|
||||
android:defaultValue="9"
|
||||
android:inputType="number"
|
||||
android:maxLength="3">
|
||||
</EditTextPreference>
|
||||
|
||||
<EditTextPreference android:key="@string/track_color_mode_fixed_speed_medium_key"
|
||||
android:title="@string/settings_track_color_mode_fixed_speed_medium"
|
||||
android:summary="@string/settings_track_color_mode_fixed_speed_medium_summary"
|
||||
android:defaultValue="15"
|
||||
android:inputType="number"
|
||||
android:maxLength="3">
|
||||
</EditTextPreference>
|
||||
|
||||
<EditTextPreference android:key="@string/track_color_mode_fixed_speed_medium_display_key"
|
||||
android:title="@string/settings_track_color_mode_fixed_speed_medium"
|
||||
android:summary="@string/settings_track_color_mode_fixed_speed_medium_summary"
|
||||
android:defaultValue="15"
|
||||
android:inputType="number"
|
||||
android:maxLength="3">
|
||||
</EditTextPreference>
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:title="@string/dynamic_speed_options">
|
||||
<EditTextPreference android:key="@string/track_color_mode_dynamic_speed_variation_key"
|
||||
android:title="@string/settings_track_color_mode_dynamic_speed_variation"
|
||||
android:summary="@string/settings_track_color_mode_dynamic_speed_variation_summary"
|
||||
android:defaultValue="25"
|
||||
android:inputType="number"
|
||||
android:maxLength="2">
|
||||
</EditTextPreference>
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
|
||||
<!-- Recording settings -->
|
||||
@@ -42,7 +95,7 @@ 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"
|
||||
@@ -156,6 +209,13 @@ limitations under the License.
|
||||
android:summaryOn="@string/settings_share_url_only_summary_on"
|
||||
android:summaryOff="@string/settings_share_url_only_summary_off"
|
||||
android:defaultValue="false" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:key="@string/allow_access_key"
|
||||
android:title="@string/settings_allow_access"
|
||||
android:summaryOn="@string/settings_allow_access_summary_on"
|
||||
android:summaryOff="@string/settings_allow_access_summary_off"
|
||||
android:defaultValue="false" />
|
||||
</PreferenceScreen>
|
||||
|
||||
<!-- Backup settings -->
|
||||
|
||||
@@ -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" />
|
||||
@@ -61,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;
|
||||
@@ -210,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
|
||||
@@ -1223,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,7 +52,7 @@ 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
|
||||
*/
|
||||
@@ -65,16 +65,16 @@ public class AccountChooser {
|
||||
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(Constants.TAG, "Multiple matching accounts found.");
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
@@ -83,14 +83,20 @@ public class AccountChooser {
|
||||
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,6 +113,10 @@ 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.
|
||||
*/
|
||||
@@ -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
|
||||
@@ -43,7 +43,7 @@ public class AggregatedStatsActivity extends Activity implements
|
||||
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);
|
||||
@@ -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() {
|
||||
|
||||
@@ -20,11 +20,11 @@ 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.Sensor;
|
||||
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.content.TrackDataHub.ListenerDataType;
|
||||
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.services.tasks.StatusAnnouncerFactory;
|
||||
import com.google.android.apps.mytracks.stats.DoubleBuffer;
|
||||
@@ -35,6 +35,9 @@ import com.google.android.apps.mytracks.util.UnitConversions;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.location.Location;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
@@ -58,6 +61,7 @@ import java.util.EnumSet;
|
||||
*/
|
||||
public class ChartActivity extends Activity implements TrackDataListener {
|
||||
|
||||
private static final int CHART_SETTINGS_DIALOG = 1;
|
||||
private final DoubleBuffer elevationBuffer =
|
||||
new DoubleBuffer(Constants.ELEVATION_SMOOTHING_FACTOR);
|
||||
private final DoubleBuffer speedBuffer =
|
||||
@@ -73,7 +77,6 @@ public class ChartActivity extends Activity implements TrackDataListener {
|
||||
private double trackMaxSpeed;
|
||||
|
||||
// Modes of operation
|
||||
private Mode mode = Mode.BY_DISTANCE;
|
||||
private boolean metricUnits;
|
||||
private boolean reportSpeed;
|
||||
|
||||
@@ -93,10 +96,16 @@ public class ChartActivity extends Activity implements TrackDataListener {
|
||||
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(dataHub.isRecordingSelected());
|
||||
chartView.setShowPointer(localDataHub.isRecordingSelected());
|
||||
chartView.invalidate();
|
||||
}
|
||||
};
|
||||
@@ -105,8 +114,6 @@ public class ChartActivity extends Activity implements TrackDataListener {
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
Log.w(TAG, "ChartActivity.onCreate");
|
||||
super.onCreate(savedInstanceState);
|
||||
MyTracks.getInstance().setChartActivity(this);
|
||||
dataHub = MyTracks.getInstance().getDataHub();
|
||||
|
||||
// The volume we want to control is the Text-To-Speech volume
|
||||
int volumeStream =
|
||||
@@ -117,7 +124,6 @@ public class ChartActivity extends Activity implements TrackDataListener {
|
||||
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);
|
||||
@@ -142,8 +148,10 @@ public class ChartActivity extends Activity implements TrackDataListener {
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
dataHub = ((MyTracksApplication) getApplication()).getTrackDataHub();
|
||||
dataHub.registerTrackDataListener(this, EnumSet.of(
|
||||
ListenerDataType.SELECTED_TRACK_CHANGED,
|
||||
ListenerDataType.TRACK_UPDATES,
|
||||
ListenerDataType.POINT_UPDATES,
|
||||
ListenerDataType.SAMPLED_OUT_POINT_UPDATES,
|
||||
ListenerDataType.WAYPOINT_UPDATES,
|
||||
@@ -153,6 +161,7 @@ public class ChartActivity extends Activity implements TrackDataListener {
|
||||
@Override
|
||||
protected void onPause() {
|
||||
dataHub.unregisterTrackDataListener(this);
|
||||
dataHub = null;
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
@@ -169,27 +178,13 @@ public class ChartActivity extends Activity implements TrackDataListener {
|
||||
zoomControls.setIsZoomOutEnabled(chartView.canZoomOut());
|
||||
}
|
||||
|
||||
public void setMode(Mode newMode) {
|
||||
if (this.mode != newMode) {
|
||||
this.mode = newMode;
|
||||
chartView.setMode(this.mode);
|
||||
private void setMode(Mode newMode) {
|
||||
if (chartView.getMode() != newMode) {
|
||||
chartView.setMode(newMode);
|
||||
dataHub.reloadDataForListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
@@ -204,13 +199,52 @@ public class ChartActivity extends Activity implements TrackDataListener {
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case Constants.MENU_CHART_SETTINGS:
|
||||
MyTracks.getInstance().getDialogManager().showDialogSafely(
|
||||
DialogManager.DIALOG_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:
|
||||
@@ -257,6 +291,7 @@ public class ChartActivity extends Activity implements TrackDataListener {
|
||||
}
|
||||
|
||||
// TODO: Account for segment splits?
|
||||
Mode mode = chartView.getMode();
|
||||
switch (mode) {
|
||||
case BY_DISTANCE:
|
||||
timeOrDistance = profileLength / 1000.0;
|
||||
@@ -424,10 +459,11 @@ public class ChartActivity extends Activity implements TrackDataListener {
|
||||
this.metricUnits = metric;
|
||||
|
||||
chartView.setMetricUnits(metric);
|
||||
|
||||
|
||||
return true; // Reload data
|
||||
}
|
||||
|
||||
@SuppressWarnings("hiding")
|
||||
@Override
|
||||
public boolean onReportSpeedChanged(boolean reportSpeed) {
|
||||
boolean changed = reportSpeed != this.reportSpeed;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,7 +63,6 @@ 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;
|
||||
@@ -199,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.
|
||||
@@ -333,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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -401,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;
|
||||
@@ -593,7 +594,7 @@ public class ChartView extends View {
|
||||
|
||||
final float x = getWaypointX(waypoint);
|
||||
c.drawLine(x, h - bottomBorder, x, topBorder, gridPaint);
|
||||
c.translate(x - markerWidth / 2, markerHeight);
|
||||
c.translate(x - (float) markerWidth / 2.0f, (float) markerHeight);
|
||||
if (waypoints.get(i).getType() == Waypoint.TYPE_STATISTICS) {
|
||||
statsMarker.draw(c);
|
||||
} else {
|
||||
@@ -865,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
@@ -79,6 +80,8 @@ class CheckUnits {
|
||||
private static void accept(Context context, SharedPreferences preferences) {
|
||||
recordCheckPerformed(preferences);
|
||||
Intent startIntent = new Intent(context, SettingsActivity.class);
|
||||
startIntent.putExtra(context.getString(R.string.open_settings_screen),
|
||||
context.getString(R.string.display_settings_screen_key));
|
||||
context.startActivity(startIntent);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
|
||||
/**
|
||||
* Represents a colored {@code Path} to save its relative color for drawing.
|
||||
* @author Vangelis S.
|
||||
*/
|
||||
public class ColoredPath {
|
||||
private final Path path;
|
||||
private final Paint pathPaint;
|
||||
|
||||
/**
|
||||
* Constructor for a ColoredPath by color.
|
||||
*/
|
||||
public ColoredPath(int color) {
|
||||
path = new Path();
|
||||
pathPaint = new Paint();
|
||||
pathPaint.setColor(color);
|
||||
pathPaint.setStrokeWidth(3);
|
||||
pathPaint.setStyle(Paint.Style.STROKE);
|
||||
pathPaint.setAntiAlias(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for a ColoredPath by Paint.
|
||||
*/
|
||||
public ColoredPath(Paint paint) {
|
||||
path = new Path();
|
||||
pathPaint = paint;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the path
|
||||
*/
|
||||
public Path getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the pathPaint
|
||||
*/
|
||||
public Paint getPathPaint() {
|
||||
return pathPaint;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -26,7 +26,7 @@ public abstract class Constants {
|
||||
* Should be used by all log statements
|
||||
*/
|
||||
public static final String TAG = "MyTracks";
|
||||
|
||||
|
||||
/**
|
||||
* Name of the top-level directory inside the SD card where our files will
|
||||
* be read from/written to.
|
||||
@@ -39,32 +39,21 @@ public abstract class Constants {
|
||||
|
||||
public static final int GET_LOGIN = 0;
|
||||
public static final int GET_MAP = 1;
|
||||
public static final int CREATE_MAP = 2;
|
||||
public static final int SHOW_TRACK = 3;
|
||||
public static final int ADD_LIST = 4;
|
||||
public static final int FEATURE_DETAILS = 5;
|
||||
public static final int START_RECORDING = 6;
|
||||
public static final int STOP_RECORDING = 7;
|
||||
public static final int AUTHENTICATE_TO_MY_MAPS = 8;
|
||||
public static final int AUTHENTICATE_TO_FUSION_TABLES = 9;
|
||||
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 SHARE_LINK = 15;
|
||||
public static final int SHARE_GPX_FILE = 16;
|
||||
public static final int SHARE_KML_FILE = 17;
|
||||
public static final int SHARE_CSV_FILE = 18;
|
||||
public static final int SHARE_TCX_FILE = 19;
|
||||
public static final int EDIT_DETAILS = 20;
|
||||
public static final int SAVE_GPX_FILE = 21;
|
||||
public static final int SAVE_KML_FILE = 22;
|
||||
public static final int SAVE_CSV_FILE = 23;
|
||||
public static final int SAVE_TCX_FILE = 24;
|
||||
public static final int CLEAR_MAP = 25;
|
||||
public static final int SHOW_WAYPOINT = 26;
|
||||
public static final int EDIT_WAYPOINT = 27;
|
||||
public static final int WELCOME = 28;
|
||||
public static final int SHOW_TRACK = 2;
|
||||
public static final int AUTHENTICATE_TO_MY_MAPS = 3;
|
||||
public static final int AUTHENTICATE_TO_FUSION_TABLES = 4;
|
||||
public static final int AUTHENTICATE_TO_DOCLIST = 5;
|
||||
public static final int AUTHENTICATE_TO_TRIX = 6;
|
||||
public static final int SHARE_GPX_FILE = 7;
|
||||
public static final int SHARE_KML_FILE = 8;
|
||||
public static final int SHARE_CSV_FILE = 9;
|
||||
public static final int SHARE_TCX_FILE = 10;
|
||||
public static final int SAVE_GPX_FILE = 11;
|
||||
public static final int SAVE_KML_FILE = 12;
|
||||
public static final int SAVE_CSV_FILE = 13;
|
||||
public static final int SAVE_TCX_FILE = 14;
|
||||
public static final int SHOW_WAYPOINT = 15;
|
||||
public static final int WELCOME = 16;
|
||||
|
||||
/*
|
||||
* Menu ids:
|
||||
@@ -179,7 +168,7 @@ public abstract class Constants {
|
||||
* The type of account that we can use for gdata uploads.
|
||||
*/
|
||||
public static final String ACCOUNT_TYPE = "com.google";
|
||||
|
||||
|
||||
/**
|
||||
* The name of extra intent property to indicate whether we want to resume
|
||||
* a previously recorded track.
|
||||
@@ -189,14 +178,6 @@ public abstract class Constants {
|
||||
|
||||
public static int getActionFromMenuId(int menuId) {
|
||||
switch (menuId) {
|
||||
case Constants.MENU_SEND_TO_GOOGLE:
|
||||
return Constants.SEND_TO_GOOGLE_DIALOG;
|
||||
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:
|
||||
@@ -213,15 +194,13 @@ public abstract class Constants {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
public static final String MAPSHOP_BASE_URL =
|
||||
"http://maps.google.com/maps/ms";
|
||||
"https://maps.google.com/maps/ms";
|
||||
|
||||
/*
|
||||
* Default values - keep in sync with those in preferences.xml.
|
||||
|
||||
@@ -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
|
||||
@@ -56,8 +56,8 @@ public class DeleteAllTracks 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();
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
dialogInterface.dismiss();
|
||||
Log.w(Constants.TAG, "deleting all!");
|
||||
MyTracksProviderUtils.Factory.get(context).deleteAllTracks();
|
||||
SharedPreferences prefs =
|
||||
@@ -74,8 +74,8 @@ public class DeleteAllTracks 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();
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import static com.google.android.apps.mytracks.Constants.TAG;
|
||||
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.TracksColumns;
|
||||
import com.google.android.apps.mytracks.util.ApiFeatures;
|
||||
import com.google.android.apps.mytracks.util.UriUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.ContentUris;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnCancelListener;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.Editor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Activity used to delete a track.
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class DeleteTrack extends Activity
|
||||
implements DialogInterface.OnClickListener, OnCancelListener {
|
||||
private static final int CONFIRM_DIALOG = 1;
|
||||
|
||||
private MyTracksProviderUtils providerUtils;
|
||||
|
||||
private long deleteTrackId;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
providerUtils = MyTracksProviderUtils.Factory.get(this);
|
||||
|
||||
Intent intent = getIntent();
|
||||
String action = intent.getAction();
|
||||
Uri data = intent.getData();
|
||||
if (!Intent.ACTION_DELETE.equals(action) ||
|
||||
!UriUtils.matchesContentUri(data, TracksColumns.CONTENT_URI)) {
|
||||
Log.e(TAG, "Got bad delete intent: " + intent);
|
||||
finish();
|
||||
}
|
||||
|
||||
deleteTrackId = ContentUris.parseId(data);
|
||||
|
||||
showDialog(CONFIRM_DIALOG);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Dialog onCreateDialog(int id) {
|
||||
if (id != CONFIRM_DIALOG) {
|
||||
Log.e(TAG, "Unknown dialog " + id);
|
||||
return null;
|
||||
}
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setMessage(getString(R.string.track_will_be_permanently_deleted));
|
||||
builder.setTitle(getString(R.string.are_you_sure_question));
|
||||
builder.setIcon(android.R.drawable.ic_dialog_alert);
|
||||
builder.setPositiveButton(getString(R.string.yes), this);
|
||||
builder.setNegativeButton(getString(R.string.no), this);
|
||||
builder.setOnCancelListener(this);
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int which) {
|
||||
dialogInterface.dismiss();
|
||||
if (which == DialogInterface.BUTTON_POSITIVE) {
|
||||
deleteTrack();
|
||||
}
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
onClick(dialog, DialogInterface.BUTTON_NEGATIVE);
|
||||
}
|
||||
|
||||
private void deleteTrack() {
|
||||
providerUtils.deleteTrack(deleteTrackId);
|
||||
|
||||
// If the track we just deleted was selected, unselect it.
|
||||
String selectedKey = getString(R.string.selected_track_key);
|
||||
SharedPreferences preferences = getSharedPreferences(Constants.SETTINGS_NAME, 0);
|
||||
if (preferences.getLong(selectedKey, -1) == deleteTrackId) {
|
||||
Editor editor = preferences.edit().putLong(selectedKey, -1);
|
||||
ApiFeatures.getInstance().getApiPlatformAdapter().applyPreferenceChanges(editor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,14 +17,8 @@ package com.google.android.apps.mytracks;
|
||||
|
||||
import static com.google.android.apps.mytracks.Constants.TAG;
|
||||
|
||||
import com.google.android.apps.mytracks.io.sendtogoogle.SendDialog;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.WindowManager.BadTokenException;
|
||||
|
||||
@@ -35,145 +29,16 @@ import android.view.WindowManager.BadTokenException;
|
||||
*/
|
||||
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;
|
||||
|
||||
private ProgressDialog progressDialog;
|
||||
private ProgressDialog importProgressDialog;
|
||||
private SendDialog sendToGoogleDialog;
|
||||
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 SendDialog(activity);
|
||||
return sendToGoogleDialog;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void onPrepareDialog(int id, Dialog dialog) {
|
||||
switch (id) {
|
||||
case DIALOG_SEND_TO_GOOGLE:
|
||||
activity.resetSendToGoogleStatus();
|
||||
break;
|
||||
case DIALOG_CHART_SETTINGS:
|
||||
Log.d(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 SendDialog 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 {@link 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);
|
||||
} catch (BadTokenException e) {
|
||||
Log.w(TAG, "Could not display dialog with id " + id, e);
|
||||
} catch (IllegalStateException e) {
|
||||
Log.w(TAG, "Could not display dialog with id " + id, e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
@@ -187,26 +52,16 @@ public class DialogManager {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Dismisses the progress dialog if it is showing. Executed on the UI thread.
|
||||
*/
|
||||
public void dismissDialogSafely(final int id) {
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
activity.dismissDialog(id);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// This will be thrown if this dialog was not shown before.
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* The equivalent of {@link #dismissDialogSafely(int)}, but for a specific
|
||||
* dialog instance.
|
||||
*/
|
||||
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 {
|
||||
@@ -217,4 +72,6 @@ public class DialogManager {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private DialogManager() {}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -117,7 +110,7 @@ public class ExportAllTracks {
|
||||
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 = SystemUtils.acquireWakeLock(activity, wakeLock);
|
||||
@@ -133,7 +126,7 @@ public class ExportAllTracks {
|
||||
Log.i(Constants.TAG, "ExportAllTracks: Releasing wake lock.");
|
||||
}
|
||||
Log.i(Constants.TAG, "ExportAllTracks: Done");
|
||||
Toast.makeText(activity, R.string.export_done, Toast.LENGTH_SHORT).show();
|
||||
showToast(R.string.export_done, Toast.LENGTH_SHORT);
|
||||
}
|
||||
|
||||
private void makeProgressDialog(final int trackCount) {
|
||||
@@ -189,12 +182,16 @@ public class ExportAllTracks {
|
||||
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
|
||||
@@ -25,8 +25,6 @@ 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 {
|
||||
@@ -63,12 +61,8 @@ public class ImportAllTracks {
|
||||
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() {
|
||||
@@ -101,12 +95,21 @@ public class ImportAllTracks {
|
||||
Log.i(Constants.TAG, "ImportAllTracks: Releasing wake lock.");
|
||||
}
|
||||
|
||||
activity.runOnUiThread(new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
showDoneDialog();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void showDoneDialog() {
|
||||
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);
|
||||
@@ -214,4 +217,4 @@ public class ImportAllTracks {
|
||||
}
|
||||
return gpxFiles;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -22,7 +22,10 @@ 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.TracksColumns;
|
||||
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;
|
||||
@@ -33,8 +36,10 @@ import com.google.android.maps.MapController;
|
||||
import com.google.android.maps.MapView;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.content.ContentUris;
|
||||
import android.content.Intent;
|
||||
import android.location.Location;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
@@ -51,6 +56,7 @@ import android.widget.ImageButton;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
@@ -121,7 +127,7 @@ public class MapActivity extends com.google.android.maps.MapActivity
|
||||
// ------------------------
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle bundle) {
|
||||
protected void onCreate(Bundle bundle) {
|
||||
Log.d(TAG, "MapActivity.onCreate");
|
||||
super.onCreate(bundle);
|
||||
|
||||
@@ -130,8 +136,6 @@ public class MapActivity extends com.google.android.maps.MapActivity
|
||||
new StatusAnnouncerFactory(ApiFeatures.getInstance()).getVolumeStream();
|
||||
setVolumeControlStream(volumeStream);
|
||||
|
||||
dataHub = MyTracks.getInstance().getDataHub();
|
||||
|
||||
// We don't need a window title bar:
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
|
||||
@@ -178,9 +182,10 @@ public class MapActivity extends com.google.android.maps.MapActivity
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
Log.d(TAG, "MapActivity.onStart");
|
||||
Log.d(TAG, "MapActivity.onResume");
|
||||
super.onResume();
|
||||
|
||||
dataHub = ((MyTracksApplication) getApplication()).getTrackDataHub();
|
||||
dataHub.registerTrackDataListener(this, EnumSet.of(
|
||||
ListenerDataType.SELECTED_TRACK_CHANGED,
|
||||
ListenerDataType.POINT_UPDATES,
|
||||
@@ -201,9 +206,10 @@ public class MapActivity extends com.google.android.maps.MapActivity
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
Log.d(TAG, "MapActivity.onStop");
|
||||
Log.d(TAG, "MapActivity.onPause");
|
||||
|
||||
dataHub.unregisterTrackDataListener(this);
|
||||
dataHub = null;
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
@@ -336,9 +342,9 @@ public class MapActivity extends com.google.android.maps.MapActivity
|
||||
|
||||
if (trackSelected) {
|
||||
busyPane.setVisibility(View.VISIBLE);
|
||||
|
||||
|
||||
zoomMapToBoundaries(track);
|
||||
|
||||
|
||||
mapOverlay.setShowEndMarker(!isRecording);
|
||||
busyPane.setVisibility(View.GONE);
|
||||
}
|
||||
@@ -391,13 +397,44 @@ public class MapActivity extends com.google.android.maps.MapActivity
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemSelected(int featureId, MenuItem item) {
|
||||
if (!super.onMenuItemSelected(featureId, item)) {
|
||||
MyTracks.getInstance().onActivityResult(
|
||||
Constants.getActionFromMenuId(item.getItemId()), RESULT_OK,
|
||||
new Intent());
|
||||
return true;
|
||||
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;
|
||||
case Constants.MENU_EDIT: {
|
||||
Intent intent = new Intent(this, TrackDetails.class);
|
||||
// TODO: Pass in a content URI
|
||||
intent.putExtra("trackid", dataHub.getSelectedTrackId());
|
||||
startActivity(intent);
|
||||
return true;
|
||||
}
|
||||
case Constants.MENU_DELETE: {
|
||||
Uri uri = ContentUris.withAppendedId(
|
||||
TracksColumns.CONTENT_URI, dataHub.getSelectedTrackId());
|
||||
Intent intent = new Intent(Intent.ACTION_DELETE, uri);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
}
|
||||
case Constants.MENU_CLEAR_MAP:
|
||||
dataHub.unloadCurrentTrack();
|
||||
return true;
|
||||
default:
|
||||
return super.onMenuItemSelected(featureId, item);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -464,21 +501,21 @@ public class MapActivity extends com.google.android.maps.MapActivity
|
||||
@Override
|
||||
public void onProviderStateChange(ProviderState state) {
|
||||
final int messageId;
|
||||
final boolean bindClick;
|
||||
final boolean isGpsDisabled;
|
||||
switch (state) {
|
||||
case DISABLED:
|
||||
messageId = R.string.status_enable_gps;
|
||||
bindClick = true;
|
||||
isGpsDisabled = true;
|
||||
break;
|
||||
case NO_FIX:
|
||||
case BAD_FIX:
|
||||
messageId = R.string.wait_for_fix;
|
||||
bindClick = false;
|
||||
isGpsDisabled = false;
|
||||
break;
|
||||
case GOOD_FIX:
|
||||
// Nothing to show.
|
||||
messageId = -1;
|
||||
bindClick = false;
|
||||
isGpsDisabled = false;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unexpected state: " + state);
|
||||
@@ -491,7 +528,13 @@ public class MapActivity extends com.google.android.maps.MapActivity
|
||||
messageText.setText(messageId);
|
||||
messagePane.setVisibility(View.VISIBLE);
|
||||
|
||||
if (bindClick) {
|
||||
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);
|
||||
|
||||
@@ -15,7 +15,12 @@
|
||||
*/
|
||||
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.maps.TrackPathPainter;
|
||||
import com.google.android.apps.mytracks.maps.TrackPathPainterFactory;
|
||||
import com.google.android.apps.mytracks.maps.TrackPathUtilities;
|
||||
import com.google.android.apps.mytracks.util.LocationUtils;
|
||||
import com.google.android.maps.GeoPoint;
|
||||
import com.google.android.maps.MapView;
|
||||
@@ -25,14 +30,16 @@ import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
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 +52,7 @@ import java.util.concurrent.BlockingQueue;
|
||||
*
|
||||
* @author Leif Hendrik Wilden
|
||||
*/
|
||||
public class MapOverlay extends Overlay {
|
||||
public class MapOverlay extends Overlay implements OnSharedPreferenceChangeListener {
|
||||
|
||||
private final Drawable[] arrows;
|
||||
private final int arrowWidth, arrowHeight;
|
||||
@@ -54,7 +61,6 @@ public class MapOverlay extends Overlay {
|
||||
private final Drawable startMarker;
|
||||
private final Drawable endMarker;
|
||||
private final int markerWidth, markerHeight;
|
||||
private final Paint selectedTrackPaint;
|
||||
private final Paint errorCirclePaint;
|
||||
private final Context context;
|
||||
private final List<Waypoint> waypoints;
|
||||
@@ -70,22 +76,26 @@ public class MapOverlay extends Overlay {
|
||||
|
||||
private GeoPoint lastReferencePoint;
|
||||
private Rect lastViewRect;
|
||||
private Path lastPath;
|
||||
|
||||
private boolean lastPathExists;
|
||||
private Location lastLocation;
|
||||
private TrackPathPainter trackPathPainter;
|
||||
|
||||
/**
|
||||
* Represents a pre-processed {@code Location} to speed up drawing.
|
||||
* This class is more like a data object and doesn't provide accessors.
|
||||
*/
|
||||
private static class CachedLocation {
|
||||
public static class CachedLocation {
|
||||
public final boolean valid;
|
||||
public final GeoPoint geoPoint;
|
||||
|
||||
public final int speed;
|
||||
|
||||
/**
|
||||
* Constructor for an invalid cached location.
|
||||
*/
|
||||
public CachedLocation() {
|
||||
this.valid = false;
|
||||
this.geoPoint = null;
|
||||
this.speed = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,13 +103,14 @@ public class MapOverlay extends Overlay {
|
||||
*/
|
||||
public CachedLocation(Location location) {
|
||||
this.valid = LocationUtils.isValidLocation(location);
|
||||
this.geoPoint = valid ? LocationUtils.getGeoPoint(location) : null;
|
||||
this.geoPoint = valid ? LocationUtils.getGeoPoint(location) : null;
|
||||
this.speed = (int) Math.floor(location.getSpeed() * 3.6);
|
||||
}
|
||||
};
|
||||
|
||||
public MapOverlay(Context context) {
|
||||
this.context = context;
|
||||
|
||||
|
||||
this.waypoints = new ArrayList<Waypoint>();
|
||||
this.points = new ArrayList<CachedLocation>(1024);
|
||||
this.pendingPoints = new ArrayBlockingQueue<CachedLocation>(
|
||||
@@ -148,23 +159,18 @@ public class MapOverlay extends Overlay {
|
||||
waypointMarker = resources.getDrawable(R.drawable.blue_pushpin);
|
||||
waypointMarker.setBounds(0, 0, markerWidth, markerHeight);
|
||||
|
||||
selectedTrackPaint = new Paint();
|
||||
selectedTrackPaint.setColor(resources.getColor(R.color.red));
|
||||
selectedTrackPaint.setStrokeWidth(3);
|
||||
selectedTrackPaint.setStyle(Paint.Style.STROKE);
|
||||
selectedTrackPaint.setAntiAlias(true);
|
||||
|
||||
errorCirclePaint = new Paint();
|
||||
errorCirclePaint.setColor(resources.getColor(R.color.blue));
|
||||
errorCirclePaint.setStyle(Paint.Style.STROKE);
|
||||
errorCirclePaint.setStrokeWidth(3);
|
||||
errorCirclePaint = TrackPathUtilities.getPaint(R.color.blue, context);
|
||||
errorCirclePaint.setAlpha(127);
|
||||
errorCirclePaint.setAntiAlias(true);
|
||||
|
||||
trackPathPainter = TrackPathPainterFactory.getTrackPathPainter(context);
|
||||
|
||||
context.getSharedPreferences(Constants.SETTINGS_NAME, 0)
|
||||
.registerOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
@@ -172,14 +178,18 @@ public class MapOverlay 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() {
|
||||
pendingPoints.offer(new CachedLocation());
|
||||
if (!pendingPoints.offer(new CachedLocation())) {
|
||||
Log.e(TAG, "Unable to add pending points");
|
||||
}
|
||||
}
|
||||
|
||||
public void addWaypoint(Waypoint wpt) {
|
||||
@@ -198,18 +208,19 @@ public class MapOverlay extends Overlay {
|
||||
}
|
||||
|
||||
// Visible for testing.
|
||||
int getNumWaypoints() {
|
||||
public int getNumWaypoints() {
|
||||
synchronized (waypoints) {
|
||||
return waypoints.size();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void clearPoints() {
|
||||
synchronized (points) {
|
||||
points.clear();
|
||||
synchronized (getPoints()) {
|
||||
getPoints().clear();
|
||||
pendingPoints.clear();
|
||||
lastPath = null;
|
||||
lastPathExists = false;
|
||||
lastViewRect = null;
|
||||
trackPathPainter.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,13 +246,21 @@ public class MapOverlay 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);
|
||||
|
||||
// Draw the "Start" and "End" markers:
|
||||
drawMarkers(canvas, projection);
|
||||
|
||||
// Draw the waypoints:
|
||||
drawWaypoints(canvas, projection);
|
||||
}
|
||||
@@ -249,12 +268,34 @@ public class MapOverlay extends Overlay {
|
||||
// Draw the current location
|
||||
drawMyLocation(canvas, projection);
|
||||
}
|
||||
|
||||
private void drawMarkers(Canvas canvas, Projection projection) {
|
||||
// Draw the "End" marker.
|
||||
if (showEndMarker) {
|
||||
for (int i = getPoints().size() - 1; i >= 0; --i) {
|
||||
if (getPoints().get(i).valid) {
|
||||
drawElement(canvas, projection, getPoints().get(i).geoPoint, endMarker,
|
||||
-markerWidth / 2, -markerHeight);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the "Start" marker.
|
||||
for (int i = 0; i < getPoints().size(); ++i) {
|
||||
if (getPoints().get(i).valid) {
|
||||
drawElement(canvas, projection, getPoints().get(i).geoPoint, startMarker,
|
||||
-markerWidth / 2, -markerHeight);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Visible for testing.
|
||||
Projection getMapProjection(MapView mapView) {
|
||||
return mapView.getProjection();
|
||||
}
|
||||
|
||||
|
||||
// Visible for testing.
|
||||
Rect getMapViewRect(MapView mapView) {
|
||||
int w = mapView.getLongitudeSpan();
|
||||
@@ -263,15 +304,15 @@ public class MapOverlay 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();
|
||||
|
||||
// For use in testing only.
|
||||
public TrackPathPainter getTrackPathPainter() {
|
||||
return trackPathPainter;
|
||||
}
|
||||
|
||||
// Visible for testing.
|
||||
Path getLastPath() {
|
||||
return lastPath;
|
||||
// For use in testing only.
|
||||
public void setTrackPathPainter(TrackPathPainter trackPathPainter) {
|
||||
this.trackPathPainter = trackPathPainter;
|
||||
}
|
||||
|
||||
private void drawWaypoints(Canvas canvas, Projection projection) {
|
||||
@@ -299,99 +340,42 @@ public class MapOverlay extends Overlay {
|
||||
canvas.drawCircle(pt.x, pt.y, radius, errorCirclePaint);
|
||||
}
|
||||
|
||||
private void drawTrack(Canvas canvas, Projection projection, Rect viewRect) {
|
||||
Path path;
|
||||
private void drawTrack(Canvas canvas, Projection projection, Rect viewRect)
|
||||
{
|
||||
boolean draw;
|
||||
|
||||
synchronized (points) {
|
||||
// Merge the pending points with the list of cached locations.
|
||||
final GeoPoint referencePoint = projection.fromPixels(0, 0);
|
||||
int newPoints = pendingPoints.drainTo(points);
|
||||
boolean newProjection = !viewRect.equals(lastViewRect) ||
|
||||
!referencePoint.equals(lastReferencePoint);
|
||||
if (newPoints == 0 && lastPath != null && !newProjection) {
|
||||
if (newPoints == 0 && lastPathExists && !newProjection) {
|
||||
// No need to recreate path (same points and viewing area).
|
||||
path = lastPath;
|
||||
draw = true;
|
||||
} else {
|
||||
int numPoints = points.size();
|
||||
if (numPoints < 2) {
|
||||
// Not enough points to draw a path.
|
||||
path = null;
|
||||
} else if (lastPath != null && !newProjection) {
|
||||
draw = false;
|
||||
} else if (!trackPathPainter.needsRedraw() && lastPathExists && !newProjection) {
|
||||
// Incremental update of the path, without repositioning the view.
|
||||
path = lastPath;
|
||||
updatePath(projection, viewRect, path, numPoints - newPoints);
|
||||
draw = true;
|
||||
trackPathPainter.updatePath(projection, viewRect, numPoints - newPoints, alwaysVisible, points);
|
||||
} else {
|
||||
// The view has changed so we have to start from scratch.
|
||||
path = newPath();
|
||||
path.incReserve(numPoints);
|
||||
updatePath(projection, viewRect, path, 0);
|
||||
draw = true;
|
||||
trackPathPainter.updatePath(projection, viewRect, 0, alwaysVisible, points);
|
||||
}
|
||||
lastPath = path;
|
||||
}
|
||||
lastReferencePoint = referencePoint;
|
||||
lastViewRect = viewRect;
|
||||
}
|
||||
if (path != null) {
|
||||
canvas.drawPath(path, selectedTrackPaint);
|
||||
if (draw) {
|
||||
trackPathPainter.drawTrack(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the "End" marker.
|
||||
if (showEndMarker) {
|
||||
for (int i = points.size() - 1; i >= 0; --i) {
|
||||
if (points.get(i).valid) {
|
||||
drawElement(canvas, projection, points.get(i).geoPoint, endMarker,
|
||||
-markerWidth / 2, -markerHeight);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the "Start" marker.
|
||||
for (int i = 0; i < points.size(); ++i) {
|
||||
if (points.get(i).valid) {
|
||||
drawElement(canvas, projection, points.get(i).geoPoint, startMarker,
|
||||
-markerWidth / 2, -markerHeight);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePath(Projection projection, Rect viewRect, Path path,
|
||||
int startLocationIdx) {
|
||||
// Whether to start a new segment on new valid and visible point.
|
||||
boolean newSegment =
|
||||
startLocationIdx > 0 ? !points.get(startLocationIdx - 1).valid : true;
|
||||
boolean lastVisible = !newSegment;
|
||||
final Point pt = new Point();
|
||||
// Loop over track points.
|
||||
for (int i = startLocationIdx; i < points.size(); ++i) {
|
||||
CachedLocation loc = points.get(i);
|
||||
// Check if valid, if not then indicate a new segment.
|
||||
if (!loc.valid) {
|
||||
newSegment = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
final GeoPoint geoPoint = loc.geoPoint;
|
||||
// Check if this breaks the existing segment.
|
||||
boolean visible = alwaysVisible || viewRect.contains(
|
||||
geoPoint.getLongitudeE6(), geoPoint.getLatitudeE6());
|
||||
if (!visible && !lastVisible) {
|
||||
// This is a point outside view not connected to a visible one.
|
||||
newSegment = true;
|
||||
}
|
||||
lastVisible = visible;
|
||||
|
||||
// Either move to beginning of a new segment or continue the old one.
|
||||
projection.toPixels(geoPoint, pt);
|
||||
if (newSegment) {
|
||||
path.moveTo(pt.x, pt.y);
|
||||
newSegment = false;
|
||||
} else {
|
||||
path.lineTo(pt.x, pt.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Visible for testing.
|
||||
Point drawElement(Canvas canvas, Projection projection, GeoPoint geoPoint,
|
||||
Drawable element, int offsetX, int offsetY) {
|
||||
@@ -467,4 +451,21 @@ public class MapOverlay extends Overlay {
|
||||
}
|
||||
return super.onTap(p, mapView);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the points
|
||||
*/
|
||||
public List<CachedLocation> getPoints() {
|
||||
return points;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
Log.d(TAG, "MapOverlay: onSharedPreferences changed " + key);
|
||||
if (key != null) {
|
||||
if (key.equals(context.getString(R.string.track_color_mode_key))) {
|
||||
trackPathPainter = TrackPathPainterFactory.getTrackPathPainter(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -24,7 +24,7 @@ import android.view.MenuItem;
|
||||
|
||||
/**
|
||||
* Manage the application menus.
|
||||
*
|
||||
*
|
||||
* @author Sandor Dornbush
|
||||
*/
|
||||
class MenuManager {
|
||||
@@ -34,7 +34,7 @@ class MenuManager {
|
||||
public MenuManager(MyTracks activity) {
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
activity.getMenuInflater().inflate(R.menu.main, menu);
|
||||
return true;
|
||||
@@ -52,7 +52,7 @@ class MenuManager {
|
||||
.setEnabled(isRecording)
|
||||
.setVisible(isRecording);
|
||||
}
|
||||
|
||||
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_start_recording: {
|
||||
@@ -86,10 +86,6 @@ class MenuManager {
|
||||
case R.id.menu_help: {
|
||||
return startActivity(WelcomeActivity.class);
|
||||
}
|
||||
case Constants.MENU_CLEAR_MAP: {
|
||||
activity.clearSelectedTrack();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -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,8 +15,10 @@
|
||||
*/
|
||||
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.mymaps.MapsFacade;
|
||||
import com.google.android.apps.mytracks.io.mymaps.MyMapsConstants;
|
||||
@@ -25,11 +27,8 @@ 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;
|
||||
@@ -42,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
|
||||
@@ -91,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();
|
||||
@@ -101,28 +85,33 @@ 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 = new MapsFacade(MyMapsList.this, auth);
|
||||
|
||||
@@ -183,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],
|
||||
MapsFacade.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
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 com.google.android.apps.mytracks.content.TrackDataHub;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
/**
|
||||
* MyTracksApplication for keeping global state.
|
||||
*
|
||||
* @author jshih@google.com (Jimmy Shih)
|
||||
*/
|
||||
public class MyTracksApplication extends Application {
|
||||
|
||||
private TrackDataHub trackDataHub;
|
||||
|
||||
/**
|
||||
* Gets the application's TrackDataHub.
|
||||
*
|
||||
* Note: use synchronized to make sure only one instance is created per application.
|
||||
*/
|
||||
public synchronized TrackDataHub getTrackDataHub() {
|
||||
if (trackDataHub == null) {
|
||||
trackDataHub = TrackDataHub.newInstance(getApplicationContext());
|
||||
}
|
||||
return trackDataHub;
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,12 @@
|
||||
package com.google.android.apps.mytracks;
|
||||
|
||||
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.SensorManager;
|
||||
import com.google.android.apps.mytracks.services.sensors.SensorManagerFactory;
|
||||
import com.google.android.apps.mytracks.services.sensors.SensorUtils;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
@@ -53,10 +57,16 @@ public class SensorStateActivity extends Activity {
|
||||
|
||||
private final Runnable stateUpdater = new Runnable() {
|
||||
public void run() {
|
||||
updateState();
|
||||
if (isVisible) // only update when UI is visible
|
||||
updateState();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Connection to the recording service.
|
||||
*/
|
||||
private TrackRecordingServiceConnection serviceConnection;
|
||||
|
||||
/**
|
||||
* A task which will update the U/I.
|
||||
*/
|
||||
@@ -66,6 +76,23 @@ public class SensorStateActivity extends Activity {
|
||||
runOnUiThread(stateUpdater);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A temporary sensor manager, when none is available.
|
||||
*/
|
||||
SensorManager tempSensorManager = null;
|
||||
|
||||
/**
|
||||
* A state flag set to true when the activity is active/visible,
|
||||
* i.e. after resume, and before pause
|
||||
*
|
||||
* Used to avoid updating after the pause event, because sometimes an update
|
||||
* event occurs even after the timer is cancelled. In this case,
|
||||
* it could cause the {@link #tempSensorManager} to be recreated, after it
|
||||
* is destroyed at the pause event.
|
||||
*/
|
||||
boolean isVisible = false;
|
||||
|
||||
public SensorStateActivity() {
|
||||
utils = new StatsUtilities(this);
|
||||
@@ -79,56 +106,141 @@ public class SensorStateActivity extends Activity {
|
||||
|
||||
setContentView(R.layout.sensor_state);
|
||||
|
||||
serviceConnection = new TrackRecordingServiceConnection(this, stateUpdater);
|
||||
serviceConnection.bindIfRunning();
|
||||
updateState();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
isVisible = true;
|
||||
|
||||
serviceConnection.bindIfRunning();
|
||||
|
||||
timer = new Timer();
|
||||
timer.schedule(new RefreshTask(), REFRESH_PERIOD_MS, REFRESH_PERIOD_MS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
isVisible = false;
|
||||
|
||||
timer.cancel();
|
||||
timer.purge();
|
||||
timer = null;
|
||||
stopTempSensorManager();
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
serviceConnection.unbind();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
protected void updateState() {
|
||||
MyTracks mt = MyTracks.getInstance();
|
||||
|
||||
ITrackRecordingService service =
|
||||
mt == null ? null : mt.getTrackRecordingService();
|
||||
if (service == null) {
|
||||
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();
|
||||
if (buff != null) {
|
||||
sds = Sensor.SensorDataSet.parseFrom(buff);
|
||||
updateSensorData(sds);
|
||||
Log.d(TAG, "Updating SensorStateActivity");
|
||||
|
||||
ITrackRecordingService service = serviceConnection.getServiceIfBound();
|
||||
|
||||
// Check if service is available, and recording.
|
||||
boolean isRecording = false;
|
||||
if (service != null) {
|
||||
try {
|
||||
isRecording = service.isRecording();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Unable to determine if service is recording.", e);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e(Constants.TAG, "Could not read sensor data.", e);
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
Log.e(Constants.TAG, "Could not read sensor data.", e);
|
||||
}
|
||||
updateSensorData(sds);
|
||||
|
||||
// If either service isn't available, or not recording.
|
||||
if (!isRecording) {
|
||||
updateFromTempSensorManager();
|
||||
} else {
|
||||
updateFromSysSensorManager();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateFromTempSensorManager()
|
||||
{
|
||||
// Use variables to hold the sensor state and data set.
|
||||
Sensor.SensorState currentState = null;
|
||||
Sensor.SensorDataSet currentDataSet = null;
|
||||
|
||||
// If no temp sensor manager is present, create one, and start it.
|
||||
if (tempSensorManager == null) {
|
||||
tempSensorManager = SensorManagerFactory.getSensorManager(this);
|
||||
if (tempSensorManager != null)
|
||||
tempSensorManager.onStartTrack();
|
||||
}
|
||||
|
||||
// If a temp sensor manager is available, use states from temp sensor
|
||||
// manager.
|
||||
if (tempSensorManager != null) {
|
||||
currentState = tempSensorManager.getSensorState();
|
||||
currentDataSet = tempSensorManager.getSensorDataSet();
|
||||
}
|
||||
|
||||
try {
|
||||
int i = service.getSensorState();
|
||||
updateSensorState(Sensor.SensorState.valueOf(i));
|
||||
} catch (RemoteException e) {
|
||||
Log.e(Constants.TAG, "Could not read sensor state.", e);
|
||||
updateSensorState(Sensor.SensorState.NONE);
|
||||
// Update the sensor state, and sensor data, using the variables.
|
||||
updateSensorStateAndData(currentState, currentDataSet);
|
||||
}
|
||||
|
||||
private void updateFromSysSensorManager()
|
||||
{
|
||||
// Use variables to hold the sensor state and data set.
|
||||
Sensor.SensorState currentState = null;
|
||||
Sensor.SensorDataSet currentDataSet = null;
|
||||
|
||||
ITrackRecordingService service = serviceConnection.getServiceIfBound();
|
||||
|
||||
// If a temp sensor manager is present, shut it down,
|
||||
// probably recording just started.
|
||||
stopTempSensorManager();
|
||||
|
||||
// Get sensor details from the service.
|
||||
if (service == null) {
|
||||
Log.d(TAG, "Could not get track recording service.");
|
||||
} else {
|
||||
try {
|
||||
byte[] buff = service.getSensorData();
|
||||
if (buff != null) {
|
||||
currentDataSet = Sensor.SensorDataSet.parseFrom(buff);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Could not read sensor data.", e);
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
Log.e(TAG, "Could not read sensor data.", e);
|
||||
}
|
||||
|
||||
try {
|
||||
currentState = Sensor.SensorState.valueOf(service.getSensorState());
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Could not read sensor state.", e);
|
||||
currentState = Sensor.SensorState.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the sensor state, and sensor data, using the variables.
|
||||
updateSensorStateAndData(currentState, currentDataSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the temporary sensor manager, if one exists.
|
||||
*/
|
||||
private void stopTempSensorManager()
|
||||
{
|
||||
if (tempSensorManager != null) {
|
||||
tempSensorManager.shutdown();
|
||||
tempSensorManager = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSensorStateAndData(Sensor.SensorState state, Sensor.SensorDataSet dataSet)
|
||||
{
|
||||
updateSensorState(state == null ? Sensor.SensorState.NONE : state);
|
||||
updateSensorData(dataSet);
|
||||
}
|
||||
|
||||
private void updateSensorState(Sensor.SensorState state) {
|
||||
@@ -143,6 +255,7 @@ public class SensorStateActivity extends Activity {
|
||||
utils.setUnknown(R.id.cadence_state_register);
|
||||
utils.setUnknown(R.id.power_state_register);
|
||||
utils.setUnknown(R.id.heart_rate_register);
|
||||
utils.setUnknown(R.id.battery_level_register);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -153,8 +266,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 +293,27 @@ 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));
|
||||
}
|
||||
|
||||
if (sds.hasBatteryLevel() && sds.getBatteryLevel().hasValue()
|
||||
&& sds.getBatteryLevel().getState() == Sensor.SensorState.SENDING) {
|
||||
utils.setText(R.id.battery_level_register,
|
||||
Integer.toString(sds.getBatteryLevel().getValue()));
|
||||
} else {
|
||||
utils.setText(R.id.battery_level_register,
|
||||
SensorUtils.getStateAsString(
|
||||
sds.hasBatteryLevel()
|
||||
? sds.getBatteryLevel().getState()
|
||||
: Sensor.SensorState.NONE,
|
||||
this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ 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.apps.mytracks.util.UnitConversions;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
@@ -32,11 +33,13 @@ import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.preference.EditTextPreference;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.Preference.OnPreferenceChangeListener;
|
||||
import android.preference.Preference.OnPreferenceClickListener;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceCategory;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.provider.Settings;
|
||||
@@ -50,7 +53,11 @@ import java.util.Set;
|
||||
|
||||
/**
|
||||
* An activity that let's the user see and edit the settings.
|
||||
*
|
||||
*
|
||||
* This activity has two entry points, "root" and "display" preference screen.
|
||||
* If bundle.getString("open_settings_screen") is set to "display_settings_screen_key", then
|
||||
* the "display" preference screen is shown, otherwise, the "root" display preference is shown.
|
||||
*
|
||||
* @author Leif Hendrik Wilden
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
@@ -58,12 +65,22 @@ public class SettingsActivity extends PreferenceActivity {
|
||||
|
||||
private BackupPreferencesListener backupListener;
|
||||
private SharedPreferences preferences;
|
||||
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
initActivityCommons();
|
||||
|
||||
// If we only need the display setting screen nothing else needs to load.
|
||||
if (processIntent())
|
||||
return;
|
||||
|
||||
initActivitySpecifics();
|
||||
}
|
||||
|
||||
private void initActivityCommons() {
|
||||
// The volume we want to control is the Text-To-Speech volume
|
||||
ApiFeatures apiFeatures = ApiFeatures.getInstance();
|
||||
int volumeStream =
|
||||
@@ -83,6 +100,19 @@ public class SettingsActivity extends PreferenceActivity {
|
||||
// Load the preferences to be displayed
|
||||
addPreferencesFromResource(R.xml.preferences);
|
||||
|
||||
// Disable TTS announcement preference if not available
|
||||
if (!apiFeatures.hasTextToSpeech()) {
|
||||
IntegerListPreference announcementFrequency =
|
||||
(IntegerListPreference) findPreference(
|
||||
getString(R.string.announcement_frequency_key));
|
||||
announcementFrequency.setEnabled(false);
|
||||
announcementFrequency.setValue("-1");
|
||||
announcementFrequency.setSummary(
|
||||
R.string.settings_not_available_summary);
|
||||
}
|
||||
}
|
||||
|
||||
private void initActivitySpecifics() {
|
||||
// Hook up switching of displayed list entries between metric and imperial
|
||||
// units
|
||||
CheckBoxPreference metricUnitsPreference =
|
||||
@@ -101,18 +131,8 @@ public class SettingsActivity extends PreferenceActivity {
|
||||
updatePreferenceUnits(metricUnitsPreference.isChecked());
|
||||
|
||||
customizeSensorOptionsPreferences();
|
||||
|
||||
// Disable TTS announcement preference if not available
|
||||
if (!apiFeatures.hasTextToSpeech()) {
|
||||
IntegerListPreference announcementFrequency =
|
||||
(IntegerListPreference) findPreference(
|
||||
getString(R.string.announcement_frequency_key));
|
||||
announcementFrequency.setEnabled(false);
|
||||
announcementFrequency.setValue("-1");
|
||||
announcementFrequency.setSummary(
|
||||
R.string.settings_not_available_summary);
|
||||
}
|
||||
|
||||
customizeTrackColorModePreferences();
|
||||
|
||||
// Hook up action for resetting all settings
|
||||
Preference resetPreference = findPreference(getString(R.string.reset_key));
|
||||
resetPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
@@ -122,6 +142,50 @@ public class SettingsActivity extends PreferenceActivity {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// Add a confirmation dialog for the "Allow access" preference.
|
||||
final CheckBoxPreference allowAccessPreference = (CheckBoxPreference) findPreference(
|
||||
getString(R.string.allow_access_key));
|
||||
allowAccessPreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
if ((Boolean) newValue) {
|
||||
AlertDialog dialog = new AlertDialog.Builder(SettingsActivity.this)
|
||||
.setCancelable(true)
|
||||
.setTitle(getString(R.string.settings_allow_access))
|
||||
.setMessage(getString(R.string.settings_allow_access_dialog_message))
|
||||
.setPositiveButton(android.R.string.ok, new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int button) {
|
||||
allowAccessPreference.setChecked(true);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create();
|
||||
dialog.show();
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean processIntent() {
|
||||
boolean showDisplaySettings = false;
|
||||
Bundle bundle = getIntent().getExtras();
|
||||
PreferenceScreen preferenceScreen;
|
||||
String intentString = getString(R.string.open_settings_screen);
|
||||
|
||||
if (bundle != null) {
|
||||
preferenceScreen = (PreferenceScreen) findPreference(bundle.getString(intentString));
|
||||
if (preferenceScreen != null) {
|
||||
showDisplaySettings = true;
|
||||
setPreferenceScreen(preferenceScreen);
|
||||
}
|
||||
}
|
||||
|
||||
return showDisplaySettings;
|
||||
}
|
||||
|
||||
private void customizeSensorOptionsPreferences() {
|
||||
@@ -170,10 +234,37 @@ public class SettingsActivity extends PreferenceActivity {
|
||||
sensorOptionsScreen.removePreference(findPreference(getString(R.string.ant_options_key)));
|
||||
}
|
||||
}
|
||||
|
||||
private void customizeTrackColorModePreferences() {
|
||||
ListPreference trackColorModePreference =
|
||||
(ListPreference) findPreference(getString(R.string.track_color_mode_key));
|
||||
trackColorModePreference.setOnPreferenceChangeListener(
|
||||
new OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference,
|
||||
Object newValue) {
|
||||
updateTrackColorModeSettings((String) newValue);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
updateTrackColorModeSettings(trackColorModePreference.getValue());
|
||||
|
||||
setTrackColorModePreferenceListeners();
|
||||
|
||||
PreferenceCategory speedOptionsCategory =
|
||||
(PreferenceCategory) findPreference(getString(R.string.track_color_mode_fixed_speed_options_key));
|
||||
|
||||
speedOptionsCategory.removePreference(findPreference(getString(R.string.track_color_mode_fixed_speed_slow_key)));
|
||||
speedOptionsCategory.removePreference(findPreference(getString(R.string.track_color_mode_fixed_speed_medium_key)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
// If we only need the display setting screen nothing else needs to load.
|
||||
if (processIntent())
|
||||
return;
|
||||
|
||||
configureBluetoothPreferences();
|
||||
Preference backupNowPreference =
|
||||
@@ -232,7 +323,8 @@ public class SettingsActivity 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(
|
||||
@@ -250,6 +342,18 @@ public class SettingsActivity extends PreferenceActivity {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTrackColorModeSettings(String trackColorMode) {
|
||||
boolean usesFixedSpeed = trackColorMode.equals(getString(R.string.track_color_mode_fixed));
|
||||
boolean usesDynamicSpeed = trackColorMode.equals(getString(R.string.track_color_mode_dynamic));
|
||||
|
||||
findPreference(
|
||||
getString(R.string.track_color_mode_fixed_speed_slow_display_key)).setEnabled(usesFixedSpeed);
|
||||
findPreference(
|
||||
getString(R.string.track_color_mode_fixed_speed_medium_display_key)).setEnabled(usesFixedSpeed);
|
||||
findPreference(
|
||||
getString(R.string.track_color_mode_dynamic_speed_variation_key)).setEnabled(usesDynamicSpeed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all the preferences which give options with distance units to use
|
||||
* the proper unit the user has selected.
|
||||
@@ -339,7 +443,7 @@ public class SettingsActivity extends PreferenceActivity {
|
||||
.setPositiveButton(android.R.string.ok,
|
||||
new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int button) {
|
||||
public void onClick(DialogInterface dialogInterface, int button) {
|
||||
onResetPreferencesConfirmed();
|
||||
}
|
||||
})
|
||||
@@ -378,4 +482,84 @@ public class SettingsActivity extends PreferenceActivity {
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the given edit text preference text.
|
||||
* If the units are not metric convert the value before displaying.
|
||||
*/
|
||||
private void viewTrackColorModeSettings(EditTextPreference preference, int id) {
|
||||
CheckBoxPreference metricUnitsPreference = (CheckBoxPreference) findPreference(
|
||||
getString(R.string.metric_units_key));
|
||||
if(metricUnitsPreference.isChecked()) {
|
||||
return;
|
||||
}
|
||||
// Convert miles/h to km/h
|
||||
SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
|
||||
String metricspeed = prefs.getString(getString(id), null);
|
||||
int englishspeed;
|
||||
try {
|
||||
englishspeed = (int) (Double.parseDouble(metricspeed) * UnitConversions.KMH_TO_MPH);
|
||||
} catch (NumberFormatException e) {
|
||||
englishspeed = 0;
|
||||
}
|
||||
preference.getEditText().setText(String.valueOf(englishspeed));
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the given edit text preference value.
|
||||
* If the units are not metric convert the value before saving.
|
||||
*/
|
||||
private void validateTrackColorModeSettings(EditTextPreference preference,
|
||||
String newValue, int id) {
|
||||
CheckBoxPreference metricUnitsPreference = (CheckBoxPreference) findPreference(
|
||||
getString(R.string.metric_units_key));
|
||||
String metricspeed;
|
||||
if(!metricUnitsPreference.isChecked()) {
|
||||
// Convert miles/h to km/h
|
||||
try {
|
||||
metricspeed = String.valueOf((int) (Double.parseDouble(newValue) * UnitConversions.MPH_TO_KMH) + 1);
|
||||
} catch (NumberFormatException e) {
|
||||
metricspeed = "0";
|
||||
}
|
||||
} else {
|
||||
metricspeed = newValue;
|
||||
}
|
||||
SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
|
||||
prefs.edit().putString(getString(id), metricspeed).commit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the TrackColorMode preference listeners.
|
||||
*/
|
||||
private void setTrackColorModePreferenceListeners() {
|
||||
setTrackColorModePreferenceListener(R.string.track_color_mode_fixed_speed_slow_display_key,
|
||||
R.string.track_color_mode_fixed_speed_slow_key);
|
||||
setTrackColorModePreferenceListener(R.string.track_color_mode_fixed_speed_medium_display_key,
|
||||
R.string.track_color_mode_fixed_speed_medium_key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a TrackColorMode preference listener.
|
||||
*/
|
||||
private void setTrackColorModePreferenceListener(int displayKey, final int metricKey) {
|
||||
EditTextPreference trackColorModePreference =
|
||||
(EditTextPreference) findPreference(getString(displayKey));
|
||||
trackColorModePreference.setOnPreferenceChangeListener(
|
||||
new OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference,
|
||||
Object newValue) {
|
||||
validateTrackColorModeSettings((EditTextPreference) preference, (String) newValue, metricKey);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
trackColorModePreference.setOnPreferenceClickListener(
|
||||
new OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
viewTrackColorModeSettings((EditTextPreference) preference, metricKey);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,11 +22,13 @@ 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.SharedPreferences;
|
||||
import android.location.Location;
|
||||
import android.os.Bundle;
|
||||
import android.util.DisplayMetrics;
|
||||
@@ -46,6 +48,18 @@ import java.util.EnumSet;
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
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;
|
||||
|
||||
@@ -61,18 +75,7 @@ public class StatsActivity extends Activity implements TrackDataListener {
|
||||
private boolean showCurrentSegment = false;
|
||||
|
||||
private TrackDataHub dataHub;
|
||||
|
||||
/**
|
||||
* 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.isRecordingSelected()) {
|
||||
utils.setTime(R.id.total_time_register,
|
||||
System.currentTimeMillis() - startTime);
|
||||
}
|
||||
}
|
||||
};
|
||||
private SharedPreferences preferences;
|
||||
|
||||
/**
|
||||
* A thread that updates the total time field every second.
|
||||
@@ -87,7 +90,7 @@ public class StatsActivity extends Activity implements TrackDataListener {
|
||||
@Override
|
||||
public void run() {
|
||||
Log.i(TAG, "Started UI update thread");
|
||||
while (MyTracks.getInstance().isRecording()) {
|
||||
while (ServiceUtils.isRecording(StatsActivity.this, null, preferences)) {
|
||||
runOnUiThread(updateResults);
|
||||
try {
|
||||
Thread.sleep(1000L);
|
||||
@@ -102,10 +105,10 @@ public class StatsActivity extends Activity implements TrackDataListener {
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
dataHub = MyTracks.getInstance().getDataHub();
|
||||
preferences = getSharedPreferences(Constants.SETTINGS_NAME, 0);
|
||||
utils = new StatsUtilities(this);
|
||||
|
||||
// The volume we want to control is the Text-To-Speech volume
|
||||
@@ -132,18 +135,20 @@ public class StatsActivity extends Activity implements TrackDataListener {
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
dataHub = ((MyTracksApplication) getApplication()).getTrackDataHub();
|
||||
dataHub.registerTrackDataListener(this, EnumSet.of(
|
||||
ListenerDataType.SELECTED_TRACK_CHANGED,
|
||||
ListenerDataType.TRACK_UPDATES,
|
||||
ListenerDataType.LOCATION_UPDATES,
|
||||
ListenerDataType.DISPLAY_PREFERENCES));
|
||||
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
dataHub.unregisterTrackDataListener(this);
|
||||
dataHub = null;
|
||||
|
||||
if (thread != null) {
|
||||
thread.interrupt();
|
||||
@@ -171,7 +176,7 @@ public class StatsActivity extends Activity implements TrackDataListener {
|
||||
|
||||
utils.setReportSpeed(displaySpeed);
|
||||
updateLabels();
|
||||
|
||||
|
||||
return true; // Reload data
|
||||
}
|
||||
|
||||
@@ -260,7 +265,8 @@ public class StatsActivity extends Activity implements TrackDataListener {
|
||||
|
||||
@Override
|
||||
public void onCurrentLocationChanged(final Location loc) {
|
||||
if (dataHub.isRecordingSelected()) {
|
||||
TrackDataHub localDataHub = dataHub;
|
||||
if (localDataHub != null && localDataHub.isRecordingSelected()) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -296,6 +302,8 @@ public class StatsActivity extends Activity implements TrackDataListener {
|
||||
|
||||
@Override
|
||||
public void onTrackUpdated(final Track track) {
|
||||
TrackDataHub localDataHub = dataHub;
|
||||
final boolean recordingSelected = localDataHub != null && localDataHub.isRecordingSelected();
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -305,7 +313,7 @@ public class StatsActivity extends Activity implements TrackDataListener {
|
||||
}
|
||||
|
||||
startTime = track.getStatistics().getStartTime();
|
||||
if (!dataHub.isRecordingSelected()) {
|
||||
if (!recordingSelected) {
|
||||
utils.setTime(R.id.total_time_register,
|
||||
track.getStatistics().getTotalTime());
|
||||
showUnknownLocation();
|
||||
|
||||
@@ -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,17 +15,26 @@
|
||||
*/
|
||||
package com.google.android.apps.mytracks;
|
||||
|
||||
import static com.google.android.apps.mytracks.Constants.TAG;
|
||||
|
||||
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;
|
||||
|
||||
import android.app.ListActivity;
|
||||
import android.content.ContentUris;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.view.MenuItem;
|
||||
@@ -76,8 +85,7 @@ public class TrackList extends ListActivity
|
||||
R.string.tracklist_show_track);
|
||||
menu.add(0, Constants.MENU_EDIT, 0,
|
||||
R.string.tracklist_edit_track);
|
||||
if (!MyTracks.getInstance().isRecording()
|
||||
|| trackId != recordingTrackId) {
|
||||
if (!isRecording() || trackId != recordingTrackId) {
|
||||
menu.add(0, Constants.MENU_SEND_TO_GOOGLE, 0,
|
||||
R.string.tracklist_send_to_google);
|
||||
SubMenu share = menu.addSubMenu(0, Constants.MENU_SHARE, 0,
|
||||
@@ -109,6 +117,16 @@ public class TrackList extends ListActivity
|
||||
}
|
||||
};
|
||||
|
||||
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) {
|
||||
@@ -138,32 +156,48 @@ public class TrackList extends ListActivity
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemSelected(int featureId, MenuItem item) {
|
||||
if (!super.onMenuItemSelected(featureId, item)) {
|
||||
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;
|
||||
default: {
|
||||
Intent result = new Intent();
|
||||
result.putExtra("trackid", trackId);
|
||||
setResult(
|
||||
Constants.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;
|
||||
case Constants.MENU_DELETE: {
|
||||
Intent intent = new Intent(Intent.ACTION_DELETE);
|
||||
Uri uri = ContentUris.withAppendedId(TracksColumns.CONTENT_URI, trackId);
|
||||
intent.setDataAndType(uri, TracksColumns.CONTENT_ITEMTYPE);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
Log.w(TAG, "Unknown menu item: " + item.getItemId() + "(" + item.getTitle() + ")");
|
||||
return super.onMenuItemSelected(featureId, item);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -197,17 +231,19 @@ public class TrackList extends ListActivity
|
||||
listView = getListView();
|
||||
listView.setOnCreateContextMenuListener(contextMenuListener);
|
||||
|
||||
preferences = getSharedPreferences(Constants.SETTINGS_NAME, 0);
|
||||
serviceConnection = new TrackRecordingServiceConnection(this, serviceBindingChanged);
|
||||
|
||||
View deleteAll = findViewById(R.id.tracklist_btn_delete_all);
|
||||
View exportAll = findViewById(R.id.tracklist_btn_export_all);
|
||||
boolean notRecording = !MyTracks.getInstance().isRecording();
|
||||
deleteAll.setOnClickListener(this);
|
||||
deleteAll.setEnabled(notRecording);
|
||||
|
||||
View exportAll = findViewById(R.id.tracklist_btn_export_all);
|
||||
exportAll.setOnClickListener(this);
|
||||
exportAll.setEnabled(notRecording);
|
||||
|
||||
updateButtonsEnabled();
|
||||
|
||||
findViewById(R.id.tracklist_btn_import_all).setOnClickListener(this);
|
||||
|
||||
SharedPreferences preferences =
|
||||
getSharedPreferences(Constants.SETTINGS_NAME, 0);
|
||||
preferences.registerOnSharedPreferenceChangeListener(this);
|
||||
metricUnits =
|
||||
preferences.getBoolean(getString(R.string.metric_units_key), true);
|
||||
@@ -220,6 +256,29 @@ public class TrackList 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(
|
||||
@@ -283,4 +342,8 @@ public class TrackList extends ListActivity
|
||||
});
|
||||
setListAdapter(adapter);
|
||||
}
|
||||
|
||||
private boolean isRecording() {
|
||||
return ServiceUtils.isRecording(TrackList.this, serviceConnection.getServiceIfBound(), preferences);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.AutoCompleteTextView;
|
||||
import android.widget.Button;
|
||||
@@ -139,6 +140,7 @@ public class WaypointDetails extends Activity
|
||||
utils.setAllStats(waypointStats);
|
||||
utils.setAltitude(
|
||||
R.id.elevation_register, waypoint.getLocation().getAltitude());
|
||||
name.setImeOptions(EditorInfo.IME_ACTION_DONE);
|
||||
break;
|
||||
}
|
||||
icon.setImageDrawable(getResources().getDrawable(iconId));
|
||||
|
||||
@@ -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,6 +47,7 @@ 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.
|
||||
@@ -54,12 +59,13 @@ public class WaypointsList extends ListActivity
|
||||
|
||||
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 MyTracksProviderUtils providerUtils;
|
||||
private TrackRecordingServiceConnection serviceConnection;
|
||||
|
||||
private Cursor waypointsCursor = null;
|
||||
|
||||
@@ -71,27 +77,26 @@ public class WaypointsList extends ListActivity
|
||||
AdapterView.AdapterContextMenuInfo info =
|
||||
(AdapterView.AdapterContextMenuInfo) menuInfo;
|
||||
contextPosition = info.position;
|
||||
waypointId = WaypointsList.this.listView.getAdapter()
|
||||
selectedWaypointId = WaypointsList.this.listView.getAdapter()
|
||||
.getItemId(contextPosition);
|
||||
int type = providerUtils.getWaypoint(info.id).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));
|
||||
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));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onListItemClick(ListView l, View v, int position, long id) {
|
||||
Intent result = new Intent();
|
||||
result.putExtra("trackid", trackId);
|
||||
result.putExtra(WaypointDetails.WAYPOINT_ID_EXTRA, id);
|
||||
setResult(Constants.EDIT_WAYPOINT, result);
|
||||
finish();
|
||||
editWaypoint(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -99,29 +104,38 @@ public class WaypointsList extends ListActivity
|
||||
if (!super.onMenuItemSelected(featureId, item)) {
|
||||
switch (item.getItemId()) {
|
||||
case Constants.MENU_SHOW: {
|
||||
onListItemClick(null, null, 0, waypointId);
|
||||
Intent result = new Intent();
|
||||
result.putExtra("trackid", trackId);
|
||||
result.putExtra(WaypointDetails.WAYPOINT_ID_EXTRA, selectedWaypointId);
|
||||
setResult(RESULT_OK, result);
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
case Constants.MENU_EDIT: {
|
||||
Intent intent = new Intent(this, WaypointDetails.class);
|
||||
intent.putExtra("trackid", trackId);
|
||||
intent.putExtra(WaypointDetails.WAYPOINT_ID_EXTRA, waypointId);
|
||||
startActivity(intent);
|
||||
editWaypoint(selectedWaypointId);
|
||||
return true;
|
||||
}
|
||||
case Constants.MENU_DELETE: {
|
||||
deleteWaypoint(waypointId);
|
||||
deleteWaypoint(selectedWaypointId);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void editWaypoint(long waypointId) {
|
||||
Intent intent = new Intent(this, WaypointDetails.class);
|
||||
intent.putExtra("trackid", trackId);
|
||||
intent.putExtra(WaypointDetails.WAYPOINT_ID_EXTRA, waypointId);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
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);
|
||||
@@ -159,7 +173,7 @@ public class WaypointsList 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 "
|
||||
@@ -168,6 +182,20 @@ public class WaypointsList 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;
|
||||
@@ -181,17 +209,10 @@ public class WaypointsList extends ListActivity
|
||||
default:
|
||||
return;
|
||||
}
|
||||
long id;
|
||||
try {
|
||||
id = MyTracks.getInstance().insertWaypoint(request);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(Constants.TAG, "Cannot insert marker.", e);
|
||||
return;
|
||||
} catch (IllegalStateException e) {
|
||||
Log.e(Constants.TAG, "Cannot insert marker.", e);
|
||||
return;
|
||||
}
|
||||
long id = insertWaypoint(request);
|
||||
if (id < 0) {
|
||||
Toast.makeText(this, R.string.error_unable_to_insert_marker,
|
||||
Toast.LENGTH_LONG).show();
|
||||
Log.e(Constants.TAG, "Failed to insert marker.");
|
||||
return;
|
||||
}
|
||||
@@ -200,6 +221,28 @@ public class WaypointsList extends ListActivity
|
||||
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(
|
||||
@@ -209,7 +252,7 @@ public class WaypointsList 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 });
|
||||
|
||||
@@ -219,7 +262,7 @@ public class WaypointsList 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;
|
||||
@@ -258,8 +301,8 @@ public class WaypointsList 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(WaypointsList.this));
|
||||
}
|
||||
@@ -267,8 +310,8 @@ public class WaypointsList extends ListActivity
|
||||
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();
|
||||
|
||||
@@ -24,7 +24,7 @@ import java.util.Set;
|
||||
|
||||
/**
|
||||
* External data source manager, which converts system-level events into My Tracks data events.
|
||||
*
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
class DataSourceManager {
|
||||
@@ -36,6 +36,7 @@ class DataSourceManager {
|
||||
void notifyPointsUpdated();
|
||||
void notifyPreferenceChanged(String key);
|
||||
void notifyLocationProviderEnabled(boolean enabled);
|
||||
void notifyLocationProviderAvailable(boolean available);
|
||||
void notifyLocationChanged(Location loc);
|
||||
void notifyHeadingChanged(float heading);
|
||||
}
|
||||
@@ -93,7 +94,7 @@ class DataSourceManager {
|
||||
public void onStatusChanged(String provider, int status, Bundle extras) {
|
||||
if (!LocationManager.GPS_PROVIDER.equals(provider)) return;
|
||||
|
||||
listener.notifyLocationProviderEnabled(status == LocationProvider.AVAILABLE);
|
||||
listener.notifyLocationProviderAvailable(status == LocationProvider.AVAILABLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -168,7 +169,7 @@ class DataSourceManager {
|
||||
neededListeners.remove(ListenerDataType.SAMPLED_OUT_POINT_UPDATES);
|
||||
neededListeners.add(ListenerDataType.POINT_UPDATES);
|
||||
}
|
||||
|
||||
|
||||
Log.d(TAG, "Updating internal listeners to types " + neededListeners);
|
||||
|
||||
// Unnecessary = registered - needed
|
||||
|
||||
@@ -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
|
||||
@@ -17,11 +17,13 @@ package com.google.android.apps.mytracks.content;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.apps.mytracks.util.ApiFeatures;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentUris;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.UriMatcher;
|
||||
import android.database.Cursor;
|
||||
import android.database.SQLException;
|
||||
@@ -30,6 +32,8 @@ import android.database.sqlite.SQLiteException;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.database.sqlite.SQLiteQueryBuilder;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.Process;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -154,12 +158,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");
|
||||
}
|
||||
}
|
||||
@@ -183,15 +187,36 @@ public class MyTracksProvider extends ContentProvider {
|
||||
"waypoints/#", WAYPOINTS_ID);
|
||||
}
|
||||
|
||||
private boolean canAccess() {
|
||||
if (Binder.getCallingPid() == Process.myPid()) {
|
||||
return true;
|
||||
} else {
|
||||
Context context = getContext();
|
||||
SharedPreferences sharedPreferences = context.getSharedPreferences(
|
||||
Constants.SETTINGS_NAME, 0);
|
||||
return sharedPreferences.getBoolean(context.getString(R.string.allow_access_key), false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
if (!canAccess()) {
|
||||
return false;
|
||||
}
|
||||
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) {
|
||||
if (!canAccess()) {
|
||||
return 0;
|
||||
}
|
||||
String table;
|
||||
boolean shouldVacuum = false;
|
||||
switch (urlMatcher.match(url)) {
|
||||
@@ -224,6 +249,9 @@ public class MyTracksProvider extends ContentProvider {
|
||||
|
||||
@Override
|
||||
public String getType(Uri url) {
|
||||
if (!canAccess()) {
|
||||
return null;
|
||||
}
|
||||
switch (urlMatcher.match(url)) {
|
||||
case TRACKPOINTS:
|
||||
return TrackPointsColumns.CONTENT_TYPE;
|
||||
@@ -244,6 +272,9 @@ public class MyTracksProvider extends ContentProvider {
|
||||
|
||||
@Override
|
||||
public Uri insert(Uri url, ContentValues initialValues) {
|
||||
if (!canAccess()) {
|
||||
return null;
|
||||
}
|
||||
Log.d(MyTracksProvider.TAG, "MyTracksProvider.insert");
|
||||
ContentValues values;
|
||||
if (initialValues != null) {
|
||||
@@ -272,6 +303,9 @@ public class MyTracksProvider extends ContentProvider {
|
||||
|
||||
@Override
|
||||
public int bulkInsert(Uri url, ContentValues[] valuesBulk) {
|
||||
if (!canAccess()) {
|
||||
return 0;
|
||||
}
|
||||
Log.d(MyTracksProvider.TAG, "MyTracksProvider.bulkInsert");
|
||||
int numInserted = 0;
|
||||
try {
|
||||
@@ -344,6 +378,9 @@ public class MyTracksProvider extends ContentProvider {
|
||||
public Cursor query(
|
||||
Uri url, String[] projection, String selection, String[] selectionArgs,
|
||||
String sort) {
|
||||
if (!canAccess()) {
|
||||
return null;
|
||||
}
|
||||
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
|
||||
int match = urlMatcher.match(url);
|
||||
String sortOrder = null;
|
||||
@@ -383,7 +420,7 @@ public class MyTracksProvider extends ContentProvider {
|
||||
|
||||
if (ApiFeatures.getInstance().canReuseSQLiteQueryBuilder()) {
|
||||
Log.i(Constants.TAG,
|
||||
"Build query: " + qb.buildQuery(projection, selection, selectionArgs,
|
||||
"Build query: " + qb.buildQuery(projection, selection, selectionArgs,
|
||||
null, null, sortOrder, null));
|
||||
}
|
||||
Cursor c = qb.query(db, projection, selection, selectionArgs, null, null,
|
||||
@@ -395,6 +432,9 @@ public class MyTracksProvider extends ContentProvider {
|
||||
@Override
|
||||
public int update(Uri url, ContentValues values, String where,
|
||||
String[] selectionArgs) {
|
||||
if (!canAccess()) {
|
||||
return 0;
|
||||
}
|
||||
int count;
|
||||
int match = urlMatcher.match(url);
|
||||
if (match == TRACKPOINTS) {
|
||||
|
||||
@@ -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
|
||||
@@ -17,11 +17,12 @@ package com.google.android.apps.mytracks.content;
|
||||
|
||||
import static com.google.android.apps.mytracks.Constants.DEFAULT_MIN_REQUIRED_ACCURACY;
|
||||
import static com.google.android.apps.mytracks.Constants.MAX_DISPLAYED_WAYPOINTS_POINTS;
|
||||
import static com.google.android.apps.mytracks.Constants.TARGET_DISPLAYED_TRACK_POINTS;
|
||||
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 static com.google.android.apps.mytracks.Constants.TAG;
|
||||
import static com.google.android.apps.mytracks.Constants.TARGET_DISPLAYED_TRACK_POINTS;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.apps.mytracks.content.DataSourceManager.DataSourceListener;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.DoubleBufferedLocationFactory;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
|
||||
@@ -40,7 +41,6 @@ import android.location.LocationManager;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
@@ -129,6 +129,12 @@ public class TrackDataHub {
|
||||
TrackDataHub.this.notifyFixType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyLocationProviderAvailable(boolean available) {
|
||||
hasFix = available;
|
||||
TrackDataHub.this.notifyFixType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyLocationChanged(Location loc) {
|
||||
TrackDataHub.this.notifyLocationChanged(loc,
|
||||
@@ -150,24 +156,21 @@ public class TrackDataHub {
|
||||
|
||||
// Get content notifications on the main thread, send listener callbacks in another.
|
||||
// This ensures listener calls are serialized.
|
||||
private final HandlerThread listenerHandlerThread;
|
||||
private final Handler listenerHandler;
|
||||
private HandlerThread listenerHandlerThread;
|
||||
private Handler listenerHandler;
|
||||
|
||||
/** Manager for external listeners (those from activities). */
|
||||
private final TrackDataListeners listeners;
|
||||
private final TrackDataListeners dataListeners;
|
||||
|
||||
/** Wrapper for interacting with system data managers. */
|
||||
private final DataSourcesWrapper dataSources;
|
||||
private DataSourcesWrapper dataSources;
|
||||
|
||||
/** Manager for system data listener registrations. */
|
||||
private final DataSourceManager dataSourceManager;
|
||||
private DataSourceManager dataSourceManager;
|
||||
|
||||
/** Condensed listener for system data listener events. */
|
||||
private final DataSourceListener dataSourceListener = new HubDataSourceListener();
|
||||
|
||||
/** Whether we've been started. */
|
||||
private boolean started;
|
||||
|
||||
// Cached preference values
|
||||
private int minRequiredAccuracy;
|
||||
private boolean useMetricUnits;
|
||||
@@ -192,28 +195,31 @@ public class TrackDataHub {
|
||||
private int lastSamplingFrequency;
|
||||
private DoubleBufferedLocationFactory locationFactory;
|
||||
|
||||
private boolean started = false;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
* Builds a new {@link TrackDataHub} instance.
|
||||
*/
|
||||
public TrackDataHub(Context ctx, SharedPreferences preferences,
|
||||
MyTracksProviderUtils providerUtils) {
|
||||
this(ctx, new DataSourcesWrapperImpl(ctx, preferences), new TrackDataListeners(),
|
||||
preferences, providerUtils, TARGET_DISPLAYED_TRACK_POINTS);
|
||||
public synchronized static TrackDataHub newInstance(Context context) {
|
||||
SharedPreferences preferences = context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
|
||||
MyTracksProviderUtils providerUtils = MyTracksProviderUtils.Factory.get(context);
|
||||
return new TrackDataHub(context,
|
||||
new TrackDataListeners(),
|
||||
preferences, providerUtils,
|
||||
TARGET_DISPLAYED_TRACK_POINTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection constructor.
|
||||
*/
|
||||
// @VisibleForTesting
|
||||
TrackDataHub(Context ctx, DataSourcesWrapper dataSources, TrackDataListeners listeners,
|
||||
SharedPreferences preferences, MyTracksProviderUtils providerUtils, int targetNumPoints) {
|
||||
TrackDataHub(Context ctx, TrackDataListeners listeners, SharedPreferences preferences,
|
||||
MyTracksProviderUtils providerUtils, int targetNumPoints) {
|
||||
this.context = ctx;
|
||||
this.listeners = listeners;
|
||||
this.dataListeners = listeners;
|
||||
this.preferences = preferences;
|
||||
this.providerUtils = providerUtils;
|
||||
this.dataSources = dataSources;
|
||||
this.targetNumPoints = targetNumPoints;
|
||||
this.dataSourceManager = new DataSourceManager(dataSourceListener, dataSources);
|
||||
this.locationFactory = new DoubleBufferedLocationFactory();
|
||||
|
||||
SELECTED_TRACK_KEY = context.getString(R.string.selected_track_key);
|
||||
@@ -222,10 +228,6 @@ public class TrackDataHub {
|
||||
METRIC_UNITS_KEY = context.getString(R.string.metric_units_key);
|
||||
SPEED_REPORTING_KEY = context.getString(R.string.report_speed_key);
|
||||
|
||||
listenerHandlerThread = new HandlerThread("trackDataContentThread");
|
||||
listenerHandlerThread.start();
|
||||
listenerHandler = new Handler(listenerHandlerThread.getLooper());
|
||||
|
||||
resetState();
|
||||
}
|
||||
|
||||
@@ -235,12 +237,18 @@ public class TrackDataHub {
|
||||
*/
|
||||
public void start() {
|
||||
Log.i(TAG, "TrackDataHub.start");
|
||||
if (started) {
|
||||
if (isStarted()) {
|
||||
Log.w(TAG, "Already started, ignoring");
|
||||
return;
|
||||
}
|
||||
started = true;
|
||||
|
||||
listenerHandlerThread = new HandlerThread("trackDataContentThread");
|
||||
listenerHandlerThread.start();
|
||||
listenerHandler = new Handler(listenerHandlerThread.getLooper());
|
||||
dataSources = newDataSources();
|
||||
dataSourceManager = new DataSourceManager(dataSourceListener, dataSources);
|
||||
|
||||
// This may or may not register internal listeners, depending on whether
|
||||
// we already had external listeners.
|
||||
dataSourceManager.updateAllListeners(getNeededListenerTypes());
|
||||
@@ -250,12 +258,9 @@ public class TrackDataHub {
|
||||
loadDataForAllListeners();
|
||||
}
|
||||
|
||||
private void loadSharedPreferences() {
|
||||
selectedTrackId = preferences.getLong(SELECTED_TRACK_KEY, -1);
|
||||
useMetricUnits = preferences.getBoolean(METRIC_UNITS_KEY, true);
|
||||
reportSpeed = preferences.getBoolean(SPEED_REPORTING_KEY, true);
|
||||
minRequiredAccuracy = preferences.getInt(MIN_REQUIRED_ACCURACY_KEY,
|
||||
DEFAULT_MIN_REQUIRED_ACCURACY);
|
||||
// @VisibleForTesting
|
||||
protected DataSourcesWrapper newDataSources() {
|
||||
return new DataSourcesWrapperImpl(context, preferences);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -264,25 +269,42 @@ public class TrackDataHub {
|
||||
*/
|
||||
public void stop() {
|
||||
Log.i(TAG, "TrackDataHub.stop");
|
||||
if (!started) {
|
||||
if (!isStarted()) {
|
||||
Log.w(TAG, "Not started, ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Unregister internal listeners even if there are external listeners registered.
|
||||
dataSourceManager.unregisterAllListeners();
|
||||
listenerHandlerThread.getLooper().quit();
|
||||
|
||||
started = false;
|
||||
|
||||
dataSources = null;
|
||||
dataSourceManager = null;
|
||||
listenerHandlerThread = null;
|
||||
listenerHandler = null;
|
||||
}
|
||||
|
||||
/** Permanently invalidates and throws away all resources used by this class. */
|
||||
public void destroy() {
|
||||
if (started) {
|
||||
throw new IllegalStateException("Can only destroy the data hub after it's been stopped");
|
||||
private boolean isStarted() {
|
||||
return started;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
if (isStarted() || listenerHandlerThread.isAlive()) {
|
||||
Log.e(TAG, "Forgot to stop() TrackDataHub");
|
||||
}
|
||||
|
||||
ApiFeatures.getInstance().getApiPlatformAdapter()
|
||||
.stopHandlerThread(listenerHandlerThread);
|
||||
super.finalize();
|
||||
}
|
||||
|
||||
private void loadSharedPreferences() {
|
||||
selectedTrackId = preferences.getLong(SELECTED_TRACK_KEY, -1);
|
||||
useMetricUnits = preferences.getBoolean(METRIC_UNITS_KEY, true);
|
||||
reportSpeed = preferences.getBoolean(SPEED_REPORTING_KEY, true);
|
||||
minRequiredAccuracy = preferences.getInt(MIN_REQUIRED_ACCURACY_KEY,
|
||||
DEFAULT_MIN_REQUIRED_ACCURACY);
|
||||
}
|
||||
|
||||
/** Updates known magnetic declination if needed. */
|
||||
@@ -325,6 +347,10 @@ public class TrackDataHub {
|
||||
* is not available or doesn't have a fix.
|
||||
*/
|
||||
public void forceUpdateLocation() {
|
||||
if (!isStarted()) {
|
||||
Log.w(TAG, "Not started, not forcing location update");
|
||||
return;
|
||||
}
|
||||
Log.i(TAG, "Forcing location update");
|
||||
|
||||
Location loc = dataSources.getLastKnownLocation();
|
||||
@@ -336,7 +362,7 @@ public class TrackDataHub {
|
||||
|
||||
/** Returns the ID of the currently-selected track. */
|
||||
public long getSelectedTrackId() {
|
||||
if (!started) {
|
||||
if (!isStarted()) {
|
||||
loadSharedPreferences();
|
||||
}
|
||||
return selectedTrackId;
|
||||
@@ -347,17 +373,9 @@ public class TrackDataHub {
|
||||
return getSelectedTrackId() > 0;
|
||||
}
|
||||
|
||||
/** Returns whether we're currently recording a track. */
|
||||
public boolean isRecording() {
|
||||
if (!started) {
|
||||
loadSharedPreferences();
|
||||
}
|
||||
return preferences.getLong(RECORDING_TRACK_KEY, -1) > 0;
|
||||
}
|
||||
|
||||
/** Returns whether the selected track is still being recorded. */
|
||||
public boolean isRecordingSelected() {
|
||||
if (!started) {
|
||||
if (!isStarted()) {
|
||||
loadSharedPreferences();
|
||||
}
|
||||
long recordingTrackId = preferences.getLong(RECORDING_TRACK_KEY, -1);
|
||||
@@ -377,10 +395,10 @@ public class TrackDataHub {
|
||||
return;
|
||||
}
|
||||
|
||||
// Save the selection to memory and flash.
|
||||
// Save the selection to memory and flush.
|
||||
selectedTrackId = trackId;
|
||||
ApiFeatures.getInstance().getApiPlatformAdapter().applyPreferenceChanges(
|
||||
preferences.edit().putLong(SELECTED_TRACK_KEY, trackId));
|
||||
selectedTrackId = trackId;
|
||||
|
||||
// Force it to reload data from the beginning.
|
||||
Log.d(TAG, "Loading track");
|
||||
@@ -408,26 +426,27 @@ public class TrackDataHub {
|
||||
|
||||
public void registerTrackDataListener(
|
||||
TrackDataListener listener, EnumSet<ListenerDataType> dataTypes) {
|
||||
synchronized (listeners) {
|
||||
ListenerRegistration registration = listeners.registerTrackDataListener(listener, dataTypes);
|
||||
synchronized (dataListeners) {
|
||||
ListenerRegistration registration =
|
||||
dataListeners.registerTrackDataListener(listener, dataTypes);
|
||||
|
||||
// Don't load any data or start internal listeners if start() hasn't been
|
||||
// called. When it is called, we'll do both things.
|
||||
if (!started) return;
|
||||
if (!isStarted()) return;
|
||||
|
||||
reloadDataForListener(registration);
|
||||
loadNewDataForListener(registration);
|
||||
|
||||
dataSourceManager.updateAllListeners(getNeededListenerTypes());
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterTrackDataListener(TrackDataListener listener) {
|
||||
synchronized (listeners) {
|
||||
listeners.unregisterTrackDataListener(listener);
|
||||
synchronized (dataListeners) {
|
||||
dataListeners.unregisterTrackDataListener(listener);
|
||||
|
||||
// Don't load any data or start internal listeners if start() hasn't been
|
||||
// called. When it is called, we'll do both things.
|
||||
if (!started) return;
|
||||
if (!isStarted()) return;
|
||||
|
||||
dataSourceManager.updateAllListeners(getNeededListenerTypes());
|
||||
}
|
||||
@@ -438,30 +457,32 @@ public class TrackDataHub {
|
||||
*/
|
||||
public void reloadDataForListener(TrackDataListener listener) {
|
||||
ListenerRegistration registration;
|
||||
synchronized (listeners) {
|
||||
registration = listeners.getRegistration(listener);
|
||||
reloadDataForListener(registration);
|
||||
synchronized (dataListeners) {
|
||||
registration = dataListeners.getRegistration(listener);
|
||||
registration.resetState();
|
||||
loadNewDataForListener(registration);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads all track data received so far into the specified listeners.
|
||||
*
|
||||
* Assumes it's called from a block that synchronizes on {@link #listeners}.
|
||||
*
|
||||
* Assumes it's called from a block that synchronizes on {@link #dataListeners}.
|
||||
*/
|
||||
private void reloadDataForListener(final ListenerRegistration registration) {
|
||||
if (!started) {
|
||||
private void loadNewDataForListener(final ListenerRegistration registration) {
|
||||
if (!isStarted()) {
|
||||
Log.w(TAG, "Not started, not reloading");
|
||||
return;
|
||||
}
|
||||
if (registration == null) {
|
||||
Log.w(TAG, "Not reloading for null registration");
|
||||
return;
|
||||
}
|
||||
|
||||
// If a listener happens to be added after this method but before the Runnable below is
|
||||
// executed, it will have triggered a separate call to load data only up to the point this
|
||||
// listener got to. This is ensured by being synchronized on listeners.
|
||||
final boolean isOnlyListener = (listeners.getNumListeners() == 1);
|
||||
final boolean isOnlyListener = (dataListeners.getNumListeners() == 1);
|
||||
|
||||
runInListenerThread(new Runnable() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -542,12 +563,12 @@ public class TrackDataHub {
|
||||
* Reloads all track data received so far into the specified listeners.
|
||||
*/
|
||||
private void loadDataForAllListeners() {
|
||||
if (!started) {
|
||||
if (!isStarted()) {
|
||||
Log.w(TAG, "Not started, not reloading");
|
||||
return;
|
||||
}
|
||||
synchronized (listeners) {
|
||||
if (!listeners.hasListeners()) {
|
||||
synchronized (dataListeners) {
|
||||
if (!dataListeners.hasListeners()) {
|
||||
Log.d(TAG, "No listeners, not reloading");
|
||||
return;
|
||||
}
|
||||
@@ -604,24 +625,27 @@ public class TrackDataHub {
|
||||
} else if (SPEED_REPORTING_KEY.equals(key)) {
|
||||
reportSpeed = preferences.getBoolean(SPEED_REPORTING_KEY, true);
|
||||
notifySpeedReportingChanged();
|
||||
} else if (SELECTED_TRACK_KEY.equals(key)) {
|
||||
long trackId = preferences.getLong(SELECTED_TRACK_KEY, -1);
|
||||
loadTrack(trackId);
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when the speed/pace reporting preference changes. */
|
||||
private void notifySpeedReportingChanged() {
|
||||
if (!started) return;
|
||||
if (!isStarted()) return;
|
||||
|
||||
runInListenerThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Set<TrackDataListener> displayListeners =
|
||||
getListenersFor(ListenerDataType.DISPLAY_PREFERENCES);
|
||||
getListenersFor(ListenerDataType.DISPLAY_PREFERENCES);
|
||||
|
||||
for (TrackDataListener listener : displayListeners) {
|
||||
// TODO: Do the reloading just once for all interested listeners
|
||||
if (listener.onReportSpeedChanged(reportSpeed)) {
|
||||
synchronized (listeners) {
|
||||
reloadDataForListener(listeners.getRegistration(listener));
|
||||
synchronized (dataListeners) {
|
||||
reloadDataForListener(listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -631,17 +655,17 @@ public class TrackDataHub {
|
||||
|
||||
/** Called when the metric units setting changes. */
|
||||
private void notifyUnitsChanged() {
|
||||
if (!started) return;
|
||||
if (!isStarted()) return;
|
||||
|
||||
runInListenerThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Set<TrackDataListener> displayListeners = getListenersFor(ListenerDataType.DISPLAY_PREFERENCES);
|
||||
Set<TrackDataListener> displayListeners = getListenersFor(ListenerDataType.DISPLAY_PREFERENCES);
|
||||
|
||||
for (TrackDataListener listener : displayListeners) {
|
||||
if (listener.onUnitsChanged(useMetricUnits)) {
|
||||
synchronized (listeners) {
|
||||
reloadDataForListener(listeners.getRegistration(listener));
|
||||
synchronized (dataListeners) {
|
||||
reloadDataForListener(listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -654,9 +678,6 @@ public class TrackDataHub {
|
||||
final TrackDataListener.ProviderState state;
|
||||
if (!hasProviderEnabled) {
|
||||
state = ProviderState.DISABLED;
|
||||
|
||||
// Give a global warning about this state.
|
||||
Toast.makeText(context, R.string.error_no_gps_location_provider, Toast.LENGTH_LONG).show();
|
||||
} else if (!hasFix) {
|
||||
state = ProviderState.NO_FIX;
|
||||
} else if (!hasGoodFix) {
|
||||
@@ -711,7 +732,7 @@ public class TrackDataHub {
|
||||
if (isGpsLocation) {
|
||||
// We consider a good fix to be a recent one with reasonable accuracy.
|
||||
hasFix = !isLocationOld(location, now, MAX_LOCATION_AGE_MS);
|
||||
hasGoodFix = (location != null && location.getAccuracy() <= minRequiredAccuracy);
|
||||
hasGoodFix = (location.getAccuracy() <= minRequiredAccuracy);
|
||||
} else {
|
||||
if (!isLocationOld(lastSeenLocation, now, MAX_LOCATION_AGE_MS)) {
|
||||
// This is a network location, but we have a recent/valid GPS location, just ignore this.
|
||||
@@ -794,10 +815,6 @@ public class TrackDataHub {
|
||||
public void run() {
|
||||
for (TrackDataListener listener : listeners) {
|
||||
listener.onSelectedTrackChanged(track, isRecordingSelected());
|
||||
|
||||
if (track != null) {
|
||||
listener.onTrackUpdated(track);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -851,7 +868,7 @@ public class TrackDataHub {
|
||||
if (!LocationUtils.isValidLocation(waypoint.getLocation())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
for (TrackDataListener listener : listeners) {
|
||||
listener.onNewWaypoint(waypoint);
|
||||
}
|
||||
@@ -862,7 +879,7 @@ public class TrackDataHub {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (TrackDataListener listener : listeners) {
|
||||
listener.onNewWaypointsDone();
|
||||
}
|
||||
@@ -937,7 +954,7 @@ public class TrackDataHub {
|
||||
|
||||
Log.i(TAG, "Resampling point set after " + numLoadedPoints + " points.");
|
||||
resetState();
|
||||
synchronized (listeners) {
|
||||
synchronized (dataListeners) {
|
||||
sampledListeners = getListenersFor(ListenerDataType.POINT_UPDATES);
|
||||
sampledOutListeners = getListenersFor(ListenerDataType.SAMPLED_OUT_POINT_UPDATES);
|
||||
}
|
||||
@@ -997,6 +1014,7 @@ public class TrackDataHub {
|
||||
// no matter how many points we get in the newest batch, we'll never exceed
|
||||
// MAX_DISPLAYED_TRACK_POINTS = 2 * TARGET_DISPLAYED_TRACK_POINTS before resampling.
|
||||
long numTotalPoints = lastStoredLocationId - localFirstSeenLocationId;
|
||||
numTotalPoints = Math.max(0L, numTotalPoints);
|
||||
pointSamplingFrequency = (int) (1 + numTotalPoints / targetNumPoints);
|
||||
}
|
||||
|
||||
@@ -1021,7 +1039,7 @@ public class TrackDataHub {
|
||||
listener.onNewTrackPointsDone();
|
||||
|
||||
// Update the listener state
|
||||
ListenerRegistration registration = listeners.getRegistration(listener);
|
||||
ListenerRegistration registration = dataListeners.getRegistration(listener);
|
||||
if (registration != null) {
|
||||
registration.lastTrackId = currentSelectedTrackId;
|
||||
registration.lastPointId = localLastSeenLocationId;
|
||||
@@ -1034,7 +1052,7 @@ public class TrackDataHub {
|
||||
private void notifyNewPoint(Location location,
|
||||
long locationId,
|
||||
long lastStoredLocationId,
|
||||
int numLoadedPoints,
|
||||
int loadedPoints,
|
||||
int pointSamplingFrequency,
|
||||
Set<TrackDataListener> sampledListeners,
|
||||
Set<TrackDataListener> sampledOutListeners) {
|
||||
@@ -1053,7 +1071,7 @@ public class TrackDataHub {
|
||||
// - Is the last point and we are not recording this track.
|
||||
boolean recordingSelected = isRecordingSelected();
|
||||
boolean includeInSample =
|
||||
(numLoadedPoints % pointSamplingFrequency == 0 ||
|
||||
(loadedPoints % pointSamplingFrequency == 0 ||
|
||||
(!recordingSelected && locationId == lastStoredLocationId));
|
||||
|
||||
if (!includeInSample) {
|
||||
@@ -1071,17 +1089,23 @@ public class TrackDataHub {
|
||||
|
||||
// @VisibleForTesting
|
||||
protected void runInListenerThread(Runnable runnable) {
|
||||
if (listenerHandler == null) {
|
||||
// Use a Throwable to ensure the stack trace is logged.
|
||||
Log.e(TAG, "Tried to use listener thread before start()", new Throwable());
|
||||
return;
|
||||
}
|
||||
|
||||
listenerHandler.post(runnable);
|
||||
}
|
||||
|
||||
private Set<TrackDataListener> getListenersFor(ListenerDataType type) {
|
||||
synchronized (listeners) {
|
||||
return listeners.getListenersFor(type);
|
||||
synchronized (dataListeners) {
|
||||
return dataListeners.getListenersFor(type);
|
||||
}
|
||||
}
|
||||
|
||||
private EnumSet<ListenerDataType> getNeededListenerTypes() {
|
||||
EnumSet<ListenerDataType> neededTypes = listeners.getAllRegisteredTypes();
|
||||
EnumSet<ListenerDataType> neededTypes = dataListeners.getAllRegisteredTypes();
|
||||
|
||||
// We always want preference updates.
|
||||
neededTypes.add(ListenerDataType.DISPLAY_PREFERENCES);
|
||||
|
||||
@@ -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
|
||||
@@ -57,6 +57,13 @@ class TrackDataListeners {
|
||||
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
|
||||
|
||||
@@ -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.Constants;
|
||||
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(Constants.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(Constants.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.Constants;
|
||||
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, Constants.GET_LOGIN);
|
||||
return;
|
||||
}
|
||||
|
||||
authToken = result.getString(
|
||||
authToken = future.getResult().getString(
|
||||
AccountManager.KEY_AUTHTOKEN);
|
||||
Log.e(Constants.TAG, "Got auth token.");
|
||||
runWhenFinished();
|
||||
Log.i(TAG, "Got auth token");
|
||||
} catch (OperationCanceledException e) {
|
||||
Log.e(Constants.TAG, "Operation Canceled", e);
|
||||
Log.e(TAG, "Auth token operation Canceled", e);
|
||||
} catch (IOException e) {
|
||||
Log.e(Constants.TAG, "IOException", e);
|
||||
Log.e(TAG, "Auth token IO exception", e);
|
||||
} catch (AuthenticatorException e) {
|
||||
Log.e(Constants.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(Constants.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(Constants.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(Constants.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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
package com.google.android.apps.mytracks.io;
|
||||
|
||||
import com.google.android.apps.mytracks.MyTracks;
|
||||
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;
|
||||
@@ -25,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;
|
||||
@@ -46,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;
|
||||
|
||||
@@ -64,12 +60,13 @@ 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(
|
||||
Constants.SETTINGS_NAME, 0);
|
||||
@@ -80,24 +77,20 @@ public class SendToDocs {
|
||||
} else {
|
||||
metricUnits = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void sendToDocs(final long trackId) {
|
||||
Log.d(Constants.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() {
|
||||
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;
|
||||
@@ -162,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);
|
||||
@@ -190,7 +183,7 @@ 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(Constants.TAG, "Spreadsheet lookup failed.", e);
|
||||
@@ -198,7 +191,7 @@ public class SendToDocs {
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -206,18 +199,18 @@ public class SendToDocs {
|
||||
} catch (InterruptedException e) {
|
||||
Log.e(Constants.TAG, "Sleep interrupted", e);
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
|
||||
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
|
||||
sheetTitle);
|
||||
} catch (IOException 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(Constants.TAG, "Creating new spreadsheet: " + sheetTitle);
|
||||
|
||||
@@ -229,11 +222,11 @@ public class SendToDocs {
|
||||
+ 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
|
||||
@@ -247,7 +240,7 @@ public class SendToDocs {
|
||||
}
|
||||
|
||||
try {
|
||||
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
|
||||
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
|
||||
sheetTitle);
|
||||
} catch (IOException e) {
|
||||
Log.i(Constants.TAG, "Failed create-failed lookup", e);
|
||||
@@ -255,16 +248,16 @@ public class SendToDocs {
|
||||
}
|
||||
|
||||
if (spreadsheetId == null) {
|
||||
MyTracks.getInstance().setProgressValue(87);
|
||||
progressIndicator.setProgressValue(87);
|
||||
// Re-try
|
||||
try {
|
||||
Thread.sleep(5000);
|
||||
} catch (InterruptedException e) {
|
||||
Log.e(Constants.TAG, "Sleep interrupted", e);
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
|
||||
spreadsheetId = docsHelper.requestSpreadsheetId(docListWrapper,
|
||||
sheetTitle);
|
||||
} catch (IOException e) {
|
||||
Log.i(Constants.TAG, "Failed create-failed relookup", e);
|
||||
@@ -290,9 +283,9 @@ public class SendToDocs {
|
||||
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(Constants.TAG, "Done uploading to docs.");
|
||||
} catch (IOException e) {
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.google.android.apps.mytracks.io;
|
||||
|
||||
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;
|
||||
@@ -24,20 +26,23 @@ 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.ApiFeatures;
|
||||
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;
|
||||
import com.google.api.client.googleapis.MethodOverrideIntercepter;
|
||||
import com.google.api.client.googleapis.MethodOverride;
|
||||
import com.google.api.client.http.GenericUrl;
|
||||
import com.google.api.client.http.HttpRequest;
|
||||
import com.google.api.client.http.HttpRequestFactory;
|
||||
import com.google.api.client.http.HttpResponse;
|
||||
import com.google.api.client.http.HttpResponseException;
|
||||
import com.google.api.client.http.HttpTransport;
|
||||
import com.google.api.client.http.InputStreamContent;
|
||||
import com.google.api.client.javanet.NetHttpTransport;
|
||||
import com.google.api.client.http.apache.ApacheHttpTransport;
|
||||
import com.google.api.client.http.javanet.NetHttpTransport;
|
||||
import com.google.api.client.util.Strings;
|
||||
|
||||
import android.app.Activity;
|
||||
@@ -62,6 +67,8 @@ import java.util.Vector;
|
||||
*/
|
||||
public class SendToFusionTables implements Runnable {
|
||||
|
||||
private static final String CONTENT_TYPE = "application/x-www-form-urlencoded";
|
||||
|
||||
/**
|
||||
* Listener invoked when sending to fusion tables completes.
|
||||
*/
|
||||
@@ -74,13 +81,13 @@ public class SendToFusionTables implements Runnable {
|
||||
|
||||
/** The path for viewing a map visualization of a table. */
|
||||
private static final String FUSIONTABLES_MAP =
|
||||
"http://www.google.com/fusiontables/embedviz?" +
|
||||
"https://www.google.com/fusiontables/embedviz?" +
|
||||
"viz=MAP&q=select+col0,+col1,+col2,+col3+from+%s+&h=false&" +
|
||||
"lat=%f&lng=%f&z=%d&t=1&l=col2";
|
||||
|
||||
/** Standard base feed url for Fusion Tables. */
|
||||
private static final String FUSIONTABLES_BASE_FEED_URL =
|
||||
"http://www.google.com/fusiontables/api/query";
|
||||
"https://www.google.com/fusiontables/api/query";
|
||||
|
||||
private static final int MAX_POINTS_PER_UPLOAD = 2048;
|
||||
|
||||
@@ -116,22 +123,15 @@ public class SendToFusionTables implements Runnable {
|
||||
private int totalLocations;
|
||||
private int totalSegmentsUploaded;
|
||||
|
||||
private HttpTransport transport;
|
||||
private HttpRequestFactory httpRequestFactory;
|
||||
private String tableId;
|
||||
|
||||
private static String MARKER_TYPE_START = "large_green";
|
||||
private static String MARKER_TYPE_END = "large_red";
|
||||
private static String MARKER_TYPE_WAYPOINT = "large_yellow";
|
||||
|
||||
static {
|
||||
// We manually assign the transport to avoid having HttpTransport try to
|
||||
// load it via reflection (which breaks due to ProGuard).
|
||||
HttpTransport.setLowLevelHttpTransport(new NetHttpTransport());
|
||||
}
|
||||
|
||||
public SendToFusionTables(Activity context, AuthManager auth,
|
||||
long trackId, ProgressIndicator progressIndicator,
|
||||
OnSendCompletedListener onCompletion) {
|
||||
public SendToFusionTables(Activity context, AuthManager auth, long trackId,
|
||||
ProgressIndicator progressIndicator, OnSendCompletedListener onCompletion) {
|
||||
this.context = context;
|
||||
this.auth = auth;
|
||||
this.trackId = trackId;
|
||||
@@ -140,13 +140,9 @@ public class SendToFusionTables implements Runnable {
|
||||
this.stringUtils = new StringUtils(context);
|
||||
this.providerUtils = MyTracksProviderUtils.Factory.get(context);
|
||||
|
||||
GoogleHeaders headers = new GoogleHeaders();
|
||||
headers.setApplicationName("Google-MyTracks-" + SystemUtils.getMyTracksVersion(context));
|
||||
headers.gdataVersion = GDATA_VERSION;
|
||||
|
||||
transport = new HttpTransport();
|
||||
MethodOverrideIntercepter.setAsFirstFor(transport);
|
||||
transport.defaultHeaders = headers;
|
||||
HttpTransport transport = ApiFeatures.getInstance().useNetHttpTransport()
|
||||
? new NetHttpTransport() : new ApacheHttpTransport();
|
||||
httpRequestFactory = transport.createRequestFactory(new MethodOverride());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -156,6 +152,11 @@ public class SendToFusionTables implements Runnable {
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -170,7 +171,6 @@ public class SendToFusionTables implements Runnable {
|
||||
}
|
||||
|
||||
private void doUpload() {
|
||||
((GoogleHeaders) transport.defaultHeaders).setGoogleLogin(auth.getAuthToken());
|
||||
int statusMessageId = R.string.error_sending_to_fusiontables;
|
||||
boolean success = true;
|
||||
try {
|
||||
@@ -179,12 +179,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;
|
||||
}
|
||||
|
||||
@@ -207,7 +212,6 @@ public class SendToFusionTables implements Runnable {
|
||||
Log.d(Constants.TAG, "SendToFusionTables: Done: " + success);
|
||||
progressIndicator.setProgressValue(PROGRESS_COMPLETE);
|
||||
} finally {
|
||||
|
||||
final boolean finalSuccess = success;
|
||||
final int finalStatusMessageId = statusMessageId;
|
||||
context.runOnUiThread(new Runnable() {
|
||||
@@ -234,7 +238,7 @@ public class SendToFusionTables implements Runnable {
|
||||
return runUpdate(query);
|
||||
}
|
||||
|
||||
private boolean makeTableUnlisted(String tableId) {
|
||||
private boolean makeTableUnlisted() {
|
||||
Log.d(Constants.TAG, "Setting visibility to unlisted.");
|
||||
String query = "UPDATE TABLE " + tableId + " SET VISIBILITY = UNLISTED";
|
||||
return runUpdate(query);
|
||||
@@ -269,7 +273,7 @@ public class SendToFusionTables implements Runnable {
|
||||
*
|
||||
* @param name the marker name
|
||||
* @param description the marker description
|
||||
* @param the marker location
|
||||
* @param location the marker location
|
||||
* @return true in case of success.
|
||||
*/
|
||||
private boolean createNewPoint(String name, String description, Location location,
|
||||
@@ -295,7 +299,6 @@ public class SendToFusionTables implements Runnable {
|
||||
}
|
||||
|
||||
private boolean uploadAllTrackPoints(final Track track, String originalDescription) {
|
||||
|
||||
SharedPreferences preferences = context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
|
||||
boolean metricUnits = true;
|
||||
if (preferences != null) {
|
||||
@@ -304,7 +307,7 @@ public class SendToFusionTables implements Runnable {
|
||||
|
||||
Cursor locationsCursor = providerUtils.getLocationsCursor(track.getId(), 0, -1, false);
|
||||
try {
|
||||
if (!locationsCursor.moveToFirst()) {
|
||||
if (locationsCursor == null || !locationsCursor.moveToFirst()) {
|
||||
Log.w(Constants.TAG, "Unable to get any points to upload");
|
||||
return false;
|
||||
}
|
||||
@@ -391,7 +394,9 @@ public class SendToFusionTables implements Runnable {
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
locationsCursor.close();
|
||||
if (locationsCursor != null) {
|
||||
locationsCursor.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,17 +425,17 @@ 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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a KML Point tag for the given location.
|
||||
* Returns a KML LineString.
|
||||
*
|
||||
* @param location The location.
|
||||
* @return the kml.
|
||||
* @param track the track.
|
||||
* @return the KML LineString.
|
||||
*/
|
||||
private String getKmlLineString(Track track) {
|
||||
StringBuilder builder = new StringBuilder("<LineString><coordinates>");
|
||||
@@ -487,7 +492,7 @@ public class SendToFusionTables implements Runnable {
|
||||
* Prepares a buffer of locations for transmission to google fusion tables.
|
||||
*
|
||||
* @param track the original track with meta data
|
||||
* @param buffer a buffer of locations on the track
|
||||
* @param locations locations on the track
|
||||
* @return an array of tracks each with a sub section of the points in the
|
||||
* original buffer
|
||||
*/
|
||||
@@ -599,7 +604,7 @@ 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(
|
||||
@@ -613,9 +618,9 @@ public class SendToFusionTables implements Runnable {
|
||||
Waypoint wpt = providerUtils.createWaypoint(c);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -637,7 +642,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;
|
||||
@@ -652,37 +657,44 @@ public class SendToFusionTables implements Runnable {
|
||||
* @return true in case of success
|
||||
*/
|
||||
private boolean runUpdate(final String query) {
|
||||
GDataWrapper<HttpTransport> wrapper = new GDataWrapper<HttpTransport>();
|
||||
GDataWrapper<HttpRequestFactory> wrapper = new GDataWrapper<HttpRequestFactory>();
|
||||
wrapper.setAuthManager(auth);
|
||||
wrapper.setRetryOnAuthFailure(true);
|
||||
wrapper.setClient(transport);
|
||||
wrapper.setClient(httpRequestFactory);
|
||||
Log.d(Constants.TAG, "GData connection prepared: " + this.auth);
|
||||
wrapper.runQuery(new QueryFunction<HttpTransport>() {
|
||||
wrapper.runQuery(new QueryFunction<HttpRequestFactory>() {
|
||||
@Override
|
||||
public void query(HttpTransport client)
|
||||
public void query(HttpRequestFactory factory)
|
||||
throws IOException, GDataWrapper.ParseException, GDataWrapper.HttpException,
|
||||
GDataWrapper.AuthenticationException {
|
||||
HttpRequest request = transport.buildPostRequest();
|
||||
request.headers.contentType = "application/x-www-form-urlencoded";
|
||||
GenericUrl url = new GenericUrl(FUSIONTABLES_BASE_FEED_URL);
|
||||
request.url = url;
|
||||
InputStreamContent isc = new InputStreamContent();
|
||||
String sql = "sql=" + URLEncoder.encode(query, "UTF-8");
|
||||
isc.inputStream = new ByteArrayInputStream(Strings.toBytesUtf8(sql));
|
||||
request.content = isc;
|
||||
|
||||
String sql = "sql=" + URLEncoder.encode(query, "UTF-8");
|
||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(Strings.toBytesUtf8(sql));
|
||||
InputStreamContent isc = new InputStreamContent(null, inputStream );
|
||||
|
||||
HttpRequest request = factory.buildPostRequest(url, isc);
|
||||
|
||||
GoogleHeaders headers = new GoogleHeaders();
|
||||
headers.setApplicationName("Google-MyTracks-" + SystemUtils.getMyTracksVersion(context));
|
||||
headers.gdataVersion = GDATA_VERSION;
|
||||
headers.setGoogleLogin(auth.getAuthToken());
|
||||
headers.setContentType(CONTENT_TYPE);
|
||||
request.setHeaders(headers);
|
||||
|
||||
Log.d(Constants.TAG, "Running update query " + url.toString() + ": " + sql);
|
||||
HttpResponse response;
|
||||
try {
|
||||
response = request.execute();
|
||||
} catch (HttpResponseException e) {
|
||||
throw new GDataWrapper.HttpException(e.response.statusCode, e.response.statusMessage);
|
||||
throw new GDataWrapper.HttpException(e.getResponse().getStatusCode(),
|
||||
e.getResponse().getStatusMessage());
|
||||
}
|
||||
boolean success = response.isSuccessStatusCode;
|
||||
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, "UTF8");
|
||||
String[] lines = s.split(Strings.LINE_SEPARATOR);
|
||||
if (lines[0].equals("tableid")) {
|
||||
tableId = lines[1];
|
||||
@@ -691,9 +703,11 @@ public class SendToFusionTables implements Runnable {
|
||||
Log.w(Constants.TAG, "Unrecognized response: " + lines[0]);
|
||||
}
|
||||
} else {
|
||||
Log.d(Constants.TAG, "Query failed: " + response.statusMessage + " (" +
|
||||
response.statusCode + ")");
|
||||
throw new GDataWrapper.HttpException(response.statusCode, response.statusMessage);
|
||||
Log.d(Constants.TAG,
|
||||
"Query failed: " + response.getStatusMessage() + " ("
|
||||
+ response.getStatusCode() + ")");
|
||||
throw new GDataWrapper.HttpException(
|
||||
response.getStatusCode(), response.getStatusMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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
|
||||
@@ -76,7 +76,7 @@ public class SendToMyMaps implements Runnable {
|
||||
public interface OnSendCompletedListener {
|
||||
void onSendCompleted(String mapId, boolean success, int statusMessage);
|
||||
}
|
||||
|
||||
|
||||
public SendToMyMaps(Activity context, String mapId, AuthManager auth,
|
||||
long trackId, ProgressIndicator progressIndicator,
|
||||
OnSendCompletedListener onCompletion) {
|
||||
@@ -100,18 +100,22 @@ public class SendToMyMaps implements Runnable {
|
||||
int statusMessageId = R.string.error_sending_to_mymap;
|
||||
boolean success = true;
|
||||
try {
|
||||
progressIndicator.setProgressValue(1);
|
||||
progressIndicator.setProgressMessage(
|
||||
R.string.progress_message_reading_track);
|
||||
|
||||
|
||||
// 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();
|
||||
track.setDescription("<p>" + track.getDescription() + "</p><p>"
|
||||
+ stringUtils.generateTrackDescription(track, null, null) + "</p>");
|
||||
|
||||
mapsClient = new MapsFacade(context, auth);
|
||||
|
||||
|
||||
// Create a new map if necessary:
|
||||
boolean isNewMap = mapId.equals(NEW_MAP_ID);
|
||||
if (isNewMap) {
|
||||
@@ -166,7 +170,7 @@ public class SendToMyMaps implements Runnable {
|
||||
Log.w(TAG, "SendToMyMaps: upload waypoints failed.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (success) {
|
||||
statusMessageId = isNewMap
|
||||
? R.string.status_new_mymap_has_been_created
|
||||
@@ -178,7 +182,7 @@ public class SendToMyMaps implements Runnable {
|
||||
if (mapsClient != null) {
|
||||
mapsClient.cleanUp();
|
||||
}
|
||||
|
||||
|
||||
final boolean finalSuccess = success;
|
||||
final int finalStatusMessageId = statusMessageId;
|
||||
context.runOnUiThread(new Runnable() {
|
||||
@@ -206,17 +210,17 @@ public class SendToMyMaps implements Runnable {
|
||||
Cursor locationsCursor =
|
||||
providerUtils.getLocationsCursor(track.getId(), 0, -1, false);
|
||||
try {
|
||||
if (!locationsCursor.moveToFirst()) {
|
||||
if (locationsCursor == null || !locationsCursor.moveToFirst()) {
|
||||
Log.w(TAG, "Unable to get any points to upload");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
totalLocationsRead = 0;
|
||||
totalLocationsPrepared = 0;
|
||||
totalLocationsUploaded = 0;
|
||||
totalLocations = locationsCursor.getCount();
|
||||
totalSegmentsUploaded = 0;
|
||||
|
||||
|
||||
// Limit the number of elevation readings. Ideally we would want around 250.
|
||||
int elevationSamplingFrequency =
|
||||
Math.max(1, (int) (totalLocations / 250.0));
|
||||
@@ -224,12 +228,12 @@ public class SendToMyMaps implements Runnable {
|
||||
"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(Constants.ELEVATION_SMOOTHING_FACTOR);
|
||||
|
||||
|
||||
List<Location> locations = new ArrayList<Location>(MAX_POINTS_PER_UPLOAD);
|
||||
progressIndicator.setProgressMessage(
|
||||
R.string.progress_message_reading_track);
|
||||
@@ -238,15 +242,15 @@ public class SendToMyMaps implements Runnable {
|
||||
if (totalLocationsRead % 100 == 0) {
|
||||
updateProgress();
|
||||
}
|
||||
|
||||
|
||||
Location loc = providerUtils.createLocation(locationsCursor);
|
||||
locations.add(loc);
|
||||
|
||||
|
||||
if (totalLocationsRead == 0) {
|
||||
// Put a marker at the first point of the first valid segment:
|
||||
mapsClient.uploadMarker(mapId, track.getName(), track.getDescription(), loc, true);
|
||||
}
|
||||
|
||||
|
||||
// Add to the elevation profile.
|
||||
if (loc != null && LocationUtils.isValidLocation(loc)) {
|
||||
// All points go into the smoothing buffer...
|
||||
@@ -256,19 +260,19 @@ public class SendToMyMaps implements Runnable {
|
||||
double dist = lastLocation.distanceTo(loc);
|
||||
totalDistance += dist;
|
||||
}
|
||||
|
||||
|
||||
// ...but only a few points are really used to keep the url short.
|
||||
if (totalLocationsRead % elevationSamplingFrequency == 0) {
|
||||
distances.add(totalDistance);
|
||||
elevations.add(elevationBuffer.getAverage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If the location was not valid, it's a segment split, so make sure the
|
||||
// distance between the previous segment and the new one is not accounted
|
||||
// for in the next iteration.
|
||||
lastLocation = loc;
|
||||
|
||||
|
||||
// Every now and then, upload the accumulated points
|
||||
if (totalLocationsRead % MAX_POINTS_PER_UPLOAD
|
||||
== MAX_POINTS_PER_UPLOAD - 1) {
|
||||
@@ -276,28 +280,30 @@ public class SendToMyMaps implements Runnable {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
totalLocationsRead++;
|
||||
} while (locationsCursor.moveToNext());
|
||||
|
||||
|
||||
// Do a final upload with what's left
|
||||
if (!prepareAndUploadPoints(track, locations)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Put an end marker at the last point of the last valid segment:
|
||||
if (lastLocation != null) {
|
||||
track.setDescription("<p>" + originalDescription + "</p><p>"
|
||||
+ stringUtils.generateTrackDescription(
|
||||
track, distances, elevations)
|
||||
+ "</p>");
|
||||
return mapsClient.uploadMarker(mapId, track.getName(), track.getDescription(),
|
||||
return mapsClient.uploadMarker(mapId, track.getName(), track.getDescription(),
|
||||
lastLocation, false);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
locationsCursor.close();
|
||||
if (locationsCursor != null) {
|
||||
locationsCursor.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,17 +312,17 @@ public class SendToMyMaps implements Runnable {
|
||||
progressIndicator.setProgressMessage(
|
||||
R.string.progress_message_preparing_track);
|
||||
updateProgress();
|
||||
|
||||
|
||||
int numLocations = locations.size();
|
||||
if (numLocations < 2) {
|
||||
Log.d(TAG, "Not preparing/uploading too few points");
|
||||
totalLocationsUploaded += numLocations;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Prepare/pre-process the points
|
||||
ArrayList<Track> splitTracks = prepareLocations(track, locations);
|
||||
|
||||
|
||||
// Start uploading them
|
||||
progressIndicator.setProgressMessage(
|
||||
R.string.progress_message_sending_mymaps);
|
||||
@@ -330,7 +336,7 @@ public class SendToMyMaps implements Runnable {
|
||||
Log.d(TAG,
|
||||
"SendToMyMaps: Prepared feature for upload w/ "
|
||||
+ splitTrack.getLocations().size() + " points.");
|
||||
|
||||
|
||||
// Transmit tracks via GData feed:
|
||||
// -------------------------------
|
||||
Log.d(TAG,
|
||||
@@ -340,7 +346,7 @@ public class SendToMyMaps implements Runnable {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
locations.clear();
|
||||
totalLocationsUploaded += numLocations;
|
||||
updateProgress();
|
||||
@@ -358,7 +364,7 @@ public class SendToMyMaps implements Runnable {
|
||||
private ArrayList<Track> prepareLocations(
|
||||
Track track, Iterable<Location> locations) {
|
||||
ArrayList<Track> splitTracks = new ArrayList<Track>();
|
||||
|
||||
|
||||
// Create segments from each full track:
|
||||
Track segment = new Track();
|
||||
TripStatistics segmentStats = segment.getStatistics();
|
||||
@@ -377,11 +383,11 @@ public class SendToMyMaps implements Runnable {
|
||||
if (loc.getLatitude() > 90) {
|
||||
startNewTrackSegment = true;
|
||||
}
|
||||
|
||||
|
||||
if (startNewTrackSegment) {
|
||||
// Close up the last segment.
|
||||
prepareTrackSegment(segment, splitTracks);
|
||||
|
||||
|
||||
Log.d(TAG,
|
||||
"MyTracksSendToMyMaps: Starting new track segment...");
|
||||
startNewTrackSegment = false;
|
||||
@@ -391,7 +397,7 @@ public class SendToMyMaps implements Runnable {
|
||||
segment.setDescription(/* track.getDescription() */ "");
|
||||
segment.setCategory(track.getCategory());
|
||||
}
|
||||
|
||||
|
||||
if (loc.getLatitude() <= 90) {
|
||||
segment.addLocation(loc);
|
||||
if (segmentStats.getStartTime() < 0) {
|
||||
@@ -400,9 +406,9 @@ public class SendToMyMaps implements Runnable {
|
||||
}
|
||||
totalLocationsPrepared++;
|
||||
}
|
||||
|
||||
|
||||
prepareTrackSegment(segment, splitTracks);
|
||||
|
||||
|
||||
return splitTracks;
|
||||
}
|
||||
|
||||
@@ -425,13 +431,13 @@ public class SendToMyMaps implements Runnable {
|
||||
&& segment.getLocations().size() > 0) {
|
||||
segmentStats.setStopTime(segment.getLocations().size() - 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Decimate to 2 meter precision. Mapshop doesn't like too many
|
||||
* points:
|
||||
*/
|
||||
LocationUtils.decimate(segment, 2.0);
|
||||
|
||||
|
||||
/* It the track still has > 500 points, split it in pieces: */
|
||||
if (segment.getLocations().size() > 500) {
|
||||
splitTracks.addAll(LocationUtils.split(segment, 500));
|
||||
@@ -447,7 +453,7 @@ public class SendToMyMaps implements Runnable {
|
||||
// The percent of the total that represents the completed part of this
|
||||
// segment.
|
||||
int totalPercentage =
|
||||
(totalLocationsRead + totalLocationsPrepared + totalLocationsUploaded)
|
||||
(totalLocationsRead + totalLocationsPrepared + totalLocationsUploaded) * 100
|
||||
/ (totalLocations * 3);
|
||||
totalPercentage = Math.min(99, totalPercentage);
|
||||
progressIndicator.setProgressValue(totalPercentage);
|
||||
|
||||
@@ -185,7 +185,7 @@ public class BackupActivityHelper {
|
||||
*/
|
||||
private void restoreFromDateAsync(final Date date) {
|
||||
// Show a progress dialog
|
||||
final ProgressDialog progressDialog = ProgressDialog.show(
|
||||
ProgressDialog.show(
|
||||
activity,
|
||||
activity.getString(R.string.progress_title),
|
||||
activity.getString(R.string.backup_import_progress_message),
|
||||
@@ -202,8 +202,6 @@ public class BackupActivityHelper {
|
||||
Log.e(Constants.TAG, "Failed to restore backup", e);
|
||||
showToast(R.string.io_read_failed);
|
||||
} finally {
|
||||
dismissDialog(progressDialog);
|
||||
|
||||
// Data may have been restored, "reboot" the app to catch it
|
||||
restartApplication();
|
||||
}
|
||||
|
||||
@@ -80,12 +80,13 @@ class DatabaseDumper {
|
||||
*
|
||||
* @param cursor the cursor to get columns from
|
||||
* @param numRows the number of rows that will be later written
|
||||
* @param writer the output to write to
|
||||
* @throws IOException if there are errors while writing
|
||||
*/
|
||||
public void writeHeaders(Cursor cursor, int numRows, DataOutputStream writer)
|
||||
throws IOException {
|
||||
initializeCachedValues(cursor);
|
||||
writeQueryMetadata(cursor, numRows, writer);
|
||||
writeQueryMetadata(numRows, writer);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,6 +94,7 @@ class DatabaseDumper {
|
||||
* This must be called after {@link #writeHeaders}.
|
||||
*
|
||||
* @param cursor the cursor to write data from
|
||||
* @param writer the output to write to
|
||||
* @throws IOException if there are any errors while writing
|
||||
*/
|
||||
public void writeOneRow(Cursor cursor, DataOutputStream writer)
|
||||
@@ -146,12 +148,12 @@ class DatabaseDumper {
|
||||
/**
|
||||
* Writes metadata about the query to be dumped.
|
||||
*
|
||||
* @param cursor the cursor that the data will come from
|
||||
* @param numRows the number of rows that will be dumped
|
||||
* @param writer the output to write to
|
||||
* @throws IOException if there are any errors while writing
|
||||
*/
|
||||
private void writeQueryMetadata(
|
||||
Cursor cursor, int numRows, DataOutputStream writer) throws IOException {
|
||||
int numRows, DataOutputStream writer) throws IOException {
|
||||
// Write column data
|
||||
writer.writeInt(columnNames.length);
|
||||
for (int i = 0; i < columnNames.length; i++) {
|
||||
@@ -171,6 +173,7 @@ class DatabaseDumper {
|
||||
* @param columnIdx the column index to read from
|
||||
* @param columnTypeId the type of the column to be read
|
||||
* @param cursor the cursor to read from
|
||||
* @param writer the output to write to
|
||||
* @throws IOException if there are any errors while writing
|
||||
*/
|
||||
private void writeCell(
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.google.android.apps.mytracks.io.backup;
|
||||
|
||||
import static com.google.android.apps.mytracks.Constants.TAG;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.apps.mytracks.content.TrackPointsColumns;
|
||||
import com.google.android.apps.mytracks.content.TracksColumns;
|
||||
@@ -205,7 +207,9 @@ class ExternalFileBackup {
|
||||
} catch (IOException e) {
|
||||
// We tried to delete the partially created file, but do nothing
|
||||
// if that also fails.
|
||||
outputFile.delete();
|
||||
if (!outputFile.delete()) {
|
||||
Log.w(TAG, "Failed to delete file " + outputFile.getAbsolutePath());
|
||||
}
|
||||
|
||||
throw e;
|
||||
} finally {
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.google.wireless.gdata.parser.ParseException;
|
||||
import com.google.wireless.gdata2.client.AuthenticationException;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.format.DateFormat;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
@@ -44,6 +45,7 @@ import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
@@ -55,36 +57,36 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
*/
|
||||
public class DocsHelper {
|
||||
private static final String DOCS_FEED_URL =
|
||||
"http://docs.google.com/feeds/documents/private/full";
|
||||
"https://docs.google.com/feeds/documents/private/full";
|
||||
private static final String DOCS_SPREADSHEET_URL =
|
||||
"http://docs.google.com/feeds/documents/private/full/spreadsheet%3A";
|
||||
"https://docs.google.com/feeds/documents/private/full/spreadsheet%3A";
|
||||
private static final String DOCS_WORKSHEETS_URL_FORMAT =
|
||||
"http://spreadsheets.google.com/feeds/worksheets/%s/private/full";
|
||||
"https://spreadsheets.google.com/feeds/worksheets/%s/private/full";
|
||||
private static final String DOCS_MY_SPREADSHEETS_FEED_URL =
|
||||
"http://docs.google.com/feeds/documents/private/full?category=mine,spreadsheet";
|
||||
"https://docs.google.com/feeds/documents/private/full?category=mine,spreadsheet";
|
||||
private static final String DOCS_SPREADSHEET_URL_FORMAT =
|
||||
"http://spreadsheets.google.com/feeds/list/%s/%s/private/full";
|
||||
"https://spreadsheets.google.com/feeds/list/%s/%s/private/full";
|
||||
|
||||
private static final String CONTENT_TYPE_PARAM = "Content-Type";
|
||||
private static final String OPENDOCUMENT_SPREADSHEET_MIME_TYPE =
|
||||
"application/x-vnd.oasis.opendocument.spreadsheet";
|
||||
private static final String ATOM_FEED_MIME_TYPE = "application/atom+xml";
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new MyTracks spreadsheet with the given name.
|
||||
*
|
||||
*
|
||||
* @param context The context associated with this request.
|
||||
* @param docListWrapper The GData handle for the Document List service.
|
||||
* @param name The name for the newly-created spreadsheet.
|
||||
* @return The spreadsheet ID, if one is created. {@code null} will be
|
||||
* returned if a GData error didn't occur, but no spreadsheet ID was
|
||||
* returned.
|
||||
* returned.
|
||||
*/
|
||||
public String createSpreadsheet(final Context context,
|
||||
public String createSpreadsheet(final Context context,
|
||||
final GDataWrapper<GDataServiceClient> docListWrapper, final String name) throws IOException {
|
||||
final AtomicReference<String> idSaver = new AtomicReference<String>();
|
||||
|
||||
boolean result = docListWrapper.runQuery(new QueryFunction<GDataServiceClient>() {
|
||||
boolean success = docListWrapper.runQuery(new QueryFunction<GDataServiceClient>() {
|
||||
@Override
|
||||
public void query(GDataServiceClient client) throws IOException,
|
||||
GDataWrapper.AuthenticationException {
|
||||
@@ -95,7 +97,7 @@ public class DocsHelper {
|
||||
OPENDOCUMENT_SPREADSHEET_MIME_TYPE);
|
||||
conn.addRequestProperty("Slug", name);
|
||||
conn.addRequestProperty("Authorization",
|
||||
"GoogleLogin auth=" +
|
||||
"GoogleLogin auth=" +
|
||||
docListWrapper.getAuthManager().getAuthToken());
|
||||
conn.setDoOutput(true);
|
||||
OutputStream os = conn.getOutputStream();
|
||||
@@ -141,24 +143,24 @@ public class DocsHelper {
|
||||
if (idStringStart == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
String id = result.substring(
|
||||
idStringStart + DOCS_SPREADSHEET_URL.length(), idTagCloseIndex);
|
||||
Log.i(Constants.TAG, "Created new spreadsheet: " + id);
|
||||
idSaver.set(id);
|
||||
}});
|
||||
|
||||
if (!result) {
|
||||
throw newIOException(docListWrapper,
|
||||
|
||||
if (!success) {
|
||||
throw newIOException(docListWrapper,
|
||||
"Failed to create new spreadsheet.");
|
||||
}
|
||||
|
||||
|
||||
return idSaver.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the ID of a spreadsheet with the given name.
|
||||
*
|
||||
*
|
||||
* @param docListWrapper The GData handle for the Document List service.
|
||||
* @param title The name of the spreadsheet whose ID is to be retrieved.
|
||||
* @return The spreadsheet ID, if it can be retrieved. {@code null} will
|
||||
@@ -177,7 +179,7 @@ public class DocsHelper {
|
||||
GDataParser listParser;
|
||||
try {
|
||||
listParser = client.getParserForFeed(Entry.class,
|
||||
DOCS_MY_SPREADSHEETS_FEED_URL,
|
||||
DOCS_MY_SPREADSHEETS_FEED_URL,
|
||||
docListWrapper.getAuthManager().getAuthToken());
|
||||
listParser.init();
|
||||
|
||||
@@ -201,22 +203,22 @@ public class DocsHelper {
|
||||
});
|
||||
|
||||
if (!result) {
|
||||
throw newIOException(docListWrapper,
|
||||
throw newIOException(docListWrapper,
|
||||
"Failed to retrieve spreadsheet list.");
|
||||
}
|
||||
|
||||
|
||||
return idSaver.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the ID of the first worksheet in the named spreadsheet.
|
||||
*
|
||||
*
|
||||
* @param trixWrapper The GData handle for the spreadsheet service.
|
||||
* @param spreadsheetId The GData ID for the given spreadsheet.
|
||||
* @return The worksheet ID, if it can be retrieved. {@code null} will be
|
||||
* returned if the GData request returns without error, but without an
|
||||
* ID.
|
||||
* @throws IOException If an error occurs during the GData request.
|
||||
* @throws IOException If an error occurs during the GData request.
|
||||
*/
|
||||
public String getWorksheetId(final GDataWrapper<GDataServiceClient> trixWrapper,
|
||||
final String spreadsheetId) throws IOException {
|
||||
@@ -250,17 +252,17 @@ public class DocsHelper {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (!result) {
|
||||
throw newIOException(trixWrapper, "Failed to retrieve worksheet ID.");
|
||||
}
|
||||
|
||||
|
||||
return idSaver.get();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a row to a worksheet containing the stats for a given track.
|
||||
*
|
||||
*
|
||||
* @param context The context associated with this request.
|
||||
* @param trixAuth The GData authorization for the spreadsheet service.
|
||||
* @param spreadsheetId The spreadsheet to be modified.
|
||||
@@ -270,26 +272,31 @@ public class DocsHelper {
|
||||
* imperial units will be used.
|
||||
* @throws IOException If an error occurs while updating the worksheet.
|
||||
*/
|
||||
public void addTrackRow(Context context, AuthManager trixAuth,
|
||||
String spreadsheetId, String worksheetId, Track track,
|
||||
public void addTrackRow(Context context, AuthManager trixAuth,
|
||||
String spreadsheetId, String worksheetId, Track track,
|
||||
boolean metricUnits) throws IOException {
|
||||
|
||||
|
||||
String worksheetUri = String.format(DOCS_SPREADSHEET_URL_FORMAT,
|
||||
spreadsheetId, worksheetId);
|
||||
TripStatistics stats = track.getStatistics();
|
||||
|
||||
String distanceUnit = context.getString(metricUnits ?
|
||||
|
||||
String distanceUnit = context.getString(metricUnits ?
|
||||
R.string.kilometer : R.string.mile);
|
||||
String speedUnit = context.getString(metricUnits ?
|
||||
String speedUnit = context.getString(metricUnits ?
|
||||
R.string.kilometer_per_hour : R.string.mile_per_hour);
|
||||
String elevationUnit = context.getString(metricUnits ?
|
||||
R.string.meter : R.string.feet);
|
||||
|
||||
java.text.DateFormat dateFormat = DateFormat.getDateFormat(context);
|
||||
java.text.DateFormat timeFormat = DateFormat.getTimeFormat(context);
|
||||
Date startTime = new Date(stats.getStartTime());
|
||||
String dateString = dateFormat.format(startTime) + " " + timeFormat.format(startTime);
|
||||
|
||||
// Prepare the Post-Text we are going to send.
|
||||
DocsTagBuilder tagBuilder = new DocsTagBuilder(metricUnits)
|
||||
.append("name", track.getName())
|
||||
.append("description", track.getDescription())
|
||||
.append("date", String.format("%tc", stats.getStartTime()))
|
||||
.append("date", dateString)
|
||||
.append("totaltime", StringUtils.formatTimeAlwaysShowingHours(
|
||||
stats.getTotalTime()))
|
||||
.append("movingtime", StringUtils.formatTimeAlwaysShowingHours(
|
||||
@@ -310,7 +317,7 @@ public class DocsHelper {
|
||||
tagBuilder.append("map", String.format("%s?msa=0&msid=%s",
|
||||
Constants.MAPSHOP_BASE_URL, track.getMapId()));
|
||||
}
|
||||
|
||||
|
||||
String postText = new StringBuilder()
|
||||
.append("<entry xmlns='http://www.w3.org/2005/Atom' "
|
||||
+ "xmlns:gsx='http://schemas.google.com/spreadsheets/"
|
||||
@@ -323,7 +330,7 @@ public class DocsHelper {
|
||||
"Inserting at: " + spreadsheetId + " => " + worksheetUri);
|
||||
|
||||
Log.i(Constants.TAG, postText);
|
||||
|
||||
|
||||
writeRowData(trixAuth, worksheetUri, postText);
|
||||
|
||||
Log.i(Constants.TAG, "Post finished.");
|
||||
@@ -331,13 +338,13 @@ public class DocsHelper {
|
||||
|
||||
/**
|
||||
* Writes spreadsheet row data to the indicated worksheet.
|
||||
*
|
||||
*
|
||||
* @param trixAuth The GData authorization for the spreadsheet service.
|
||||
* @param worksheetUri The URI of the worksheet to be altered.
|
||||
* @param postText The XML tags describing the change to be made.
|
||||
* @throws IOException Thrown if an error occurs during the write.
|
||||
*/
|
||||
protected void writeRowData(AuthManager trixAuth, String worksheetUri,
|
||||
protected void writeRowData(AuthManager trixAuth, String worksheetUri,
|
||||
String postText) throws IOException {
|
||||
// No need for a wrapper because we know that the authorization was good
|
||||
// enough to get this far.
|
||||
@@ -364,9 +371,9 @@ public class DocsHelper {
|
||||
rd.close();
|
||||
}
|
||||
|
||||
private static IOException newIOException(GDataWrapper<GDataServiceClient> wrapper,
|
||||
private static IOException newIOException(GDataWrapper<GDataServiceClient> wrapper,
|
||||
String message) {
|
||||
return new IOException(String.format("%s: %d: %s", message,
|
||||
return new IOException(String.format("%s: %d: %s", message,
|
||||
wrapper.getErrorType(), wrapper.getErrorMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,40 +15,44 @@
|
||||
*/
|
||||
package com.google.android.apps.mytracks.io.docs;
|
||||
|
||||
import com.google.android.apps.mytracks.util.ApiFeatures;
|
||||
import com.google.android.apps.mytracks.util.StringUtils;
|
||||
import com.google.android.apps.mytracks.util.UnitConversions;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.DecimalFormatSymbols;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* <p>This class builds a string of XML tags used to talk to Docs using GData.
|
||||
*
|
||||
*
|
||||
* <p>Sample Usage:
|
||||
*
|
||||
*
|
||||
* <code>
|
||||
* String tags = new DocsTagBuilder(false)
|
||||
* .append("tagName", "tagValue")
|
||||
* .appendLargeUnits("bigTagName", 1.0)
|
||||
* .build();
|
||||
* </code>
|
||||
*
|
||||
*
|
||||
* <p>results in:
|
||||
*
|
||||
*
|
||||
* <code>
|
||||
* <gsx:tagName><![CDATA[tagValue]]></gsx:tagName>
|
||||
* <gsx:bigTagName><![CDATA[1.00]]></gsx:bigTagName>
|
||||
* </code>
|
||||
*
|
||||
*
|
||||
* @author Matthew Simmons
|
||||
*/
|
||||
class DocsTagBuilder {
|
||||
// TODO(simmonmt): These formats aren't I18N-compatible. Not everyone uses
|
||||
// commas for thousands and dots for the decimal point.
|
||||
|
||||
private static final DecimalFormatSymbols FORMAT_SYMBOLS =
|
||||
ApiFeatures.getInstance().getApiPlatformAdapter().getDecimalFormatSymbols(Locale.ENGLISH);
|
||||
private static final NumberFormat LARGE_UNIT_FORMAT =
|
||||
new DecimalFormat("#,###,###.00");
|
||||
new DecimalFormat("#,###,###.00", FORMAT_SYMBOLS);
|
||||
private static final NumberFormat SMALL_UNIT_FORMAT =
|
||||
new DecimalFormat("###,###");
|
||||
new DecimalFormat("###,###", FORMAT_SYMBOLS);
|
||||
|
||||
protected final boolean metricUnits;
|
||||
protected final StringBuilder stringBuilder;
|
||||
@@ -59,7 +63,7 @@ class DocsTagBuilder {
|
||||
*/
|
||||
DocsTagBuilder(boolean metricUnits) {
|
||||
this.metricUnits = metricUnits;
|
||||
stringBuilder = new StringBuilder();
|
||||
this.stringBuilder = new StringBuilder();
|
||||
}
|
||||
|
||||
/** Appends a tag containing a string value */
|
||||
@@ -68,13 +72,13 @@ class DocsTagBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Appends a tag containing a numeric value. The value will be formatted
|
||||
* according to the large distance of the specified measurement system (i.e.
|
||||
* kilometers or miles).
|
||||
*
|
||||
*
|
||||
* @param name The tag name.
|
||||
* @param d The value to be formatted, in kilometers.
|
||||
* @param d The value to be formatted, in kilometers.
|
||||
*/
|
||||
DocsTagBuilder appendLargeUnits(String name, double d) {
|
||||
double value = metricUnits ? d : (d * UnitConversions.KM_TO_MI);
|
||||
@@ -86,7 +90,7 @@ class DocsTagBuilder {
|
||||
* Appends a tag containing a numeric value. The value will be formatted
|
||||
* according to the small distance of the specified measurement system (i.e.
|
||||
* meters or feet).
|
||||
*
|
||||
*
|
||||
* @param name The tag name.
|
||||
* @param d The value to be formatted, in meters.
|
||||
*/
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user