diff --git a/MyTracks/.classpath b/MyTracks/.classpath deleted file mode 100644 index 092cde2eb..000000000 --- a/MyTracks/.classpath +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/MyTracks/.gitignore b/MyTracks/.gitignore new file mode 100644 index 000000000..60c3bead2 --- /dev/null +++ b/MyTracks/.gitignore @@ -0,0 +1,7 @@ +.gradle +.idea/workspace.xml +.idea/tasks.xml +.idea/gradle.xml +.idea/libraries +build/ +/import-summary.txt diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/classpath-include b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/classpath-include deleted file mode 100644 index 97fea11f4..000000000 --- a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/classpath-include +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/BSD-LICENSE.txt b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/BSD-LICENSE.txt deleted file mode 100644 index dcdcc4234..000000000 --- a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/BSD-LICENSE.txt +++ /dev/null @@ -1,27 +0,0 @@ -BSD License - -Copyright (c) 2000-2006, www.hamcrest.org -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list of -conditions and the following disclaimer. Redistributions in binary form must reproduce -the above copyright notice, this list of conditions and the following disclaimer in -the documentation and/or other materials provided with the distribution. - -Neither the name of Hamcrest nor the names of its contributors may be used to endorse -or promote products derived from this software without specific prior written -permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY -WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -DAMAGE. diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/css/maven-base.css b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/css/maven-base.css deleted file mode 100644 index f39e42c48..000000000 --- a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/css/maven-base.css +++ /dev/null @@ -1,151 +0,0 @@ -body { - margin: 0px; - padding: 0px; -} -img { - border:none; -} -table { - padding:0px; - width: 100%; - margin-left: -2px; - margin-right: -2px; -} -acronym { - cursor: help; - border-bottom: 1px dotted #feb; -} -table.bodyTable th, table.bodyTable td { - padding: 2px 4px 2px 4px; - vertical-align: top; -} -div.clear{ - clear:both; - visibility: hidden; -} -div.clear hr{ - display: none; -} -#bannerLeft, #bannerRight { - font-size: xx-large; - font-weight: bold; -} -#bannerLeft img, #bannerRight img { - margin: 0px; -} -.xleft, #bannerLeft img { - float:left; -} -.xright, #bannerRight { - float:right; -} -#banner { - padding: 0px; -} -#banner img { - border: none; -} -#breadcrumbs { - padding: 3px 10px 3px 10px; -} -#leftColumn { - width: 170px; - float:left; - overflow: auto; -} -#bodyColumn { - margin-right: 1.5em; - margin-left: 197px; -} -#legend { - padding: 8px 0 8px 0; -} -#navcolumn { - padding: 8px 4px 0 8px; -} -#navcolumn h5 { - margin: 0; - padding: 0; - font-size: small; -} -#navcolumn ul { - margin: 0; - padding: 0; - font-size: small; -} -#navcolumn li { - list-style-type: none; - background-image: none; - background-repeat: no-repeat; - background-position: 0 0.4em; - padding-left: 16px; - list-style-position: outside; - line-height: 1.2em; - font-size: smaller; -} -#navcolumn li.expanded { - background-image: url(../images/expanded.gif); -} -#navcolumn li.collapsed { - background-image: url(../images/collapsed.gif); -} -#poweredBy { - text-align: center; -} -#navcolumn img { - margin-top: 10px; - margin-bottom: 3px; -} -#poweredBy img { - display:block; - margin: 20px 0 20px 17px; -} -#search img { - margin: 0px; - display: block; -} -#search #q, #search #btnG { - border: 1px solid #999; - margin-bottom:10px; -} -#search form { - margin: 0px; -} -#lastPublished { - font-size: x-small; -} -.navSection { - margin-bottom: 2px; - padding: 8px; -} -.navSectionHead { - font-weight: bold; - font-size: x-small; -} -.section { - padding: 4px; -} -#footer { - padding: 3px 10px 3px 10px; - font-size: x-small; -} -#breadcrumbs { - font-size: x-small; - margin: 0pt; -} -.source { - padding: 12px; - margin: 1em 7px 1em 7px; -} -.source pre { - margin: 0px; - padding: 0px; -} -#navcolumn img.imageLink, .imageLink { - padding-left: 0px; - padding-bottom: 0px; - padding-top: 0px; - padding-right: 2px; - border: 0px; - margin: 0px; -} diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/css/maven-theme.css b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/css/maven-theme.css deleted file mode 100644 index ec29c893c..000000000 --- a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/css/maven-theme.css +++ /dev/null @@ -1,141 +0,0 @@ -body { - padding: 0px 0px 10px 0px; -} -body, td, select, input, li{ - font-family: Verdana, Helvetica, Arial, sans-serif; - font-size: 13px; -} -code{ - font-family: Courier, monospace; - font-size: 13px; -} -a { - text-decoration: none; -} -a:link { - color:#36a; -} -a:visited { - color:#47a; -} -a:active, a:hover { - color:#69c; -} -#legend li.externalLink { - background: url(../images/external.png) left top no-repeat; - padding-left: 18px; -} -a.externalLink, a.externalLink:link, a.externalLink:visited, a.externalLink:active, a.externalLink:hover { - background: url(../images/external.png) right center no-repeat; - padding-right: 18px; -} -#legend li.newWindow { - background: url(../images/newwindow.png) left top no-repeat; - padding-left: 18px; -} -a.newWindow, a.newWindow:link, a.newWindow:visited, a.newWindow:active, a.newWindow:hover { - background: url(../images/newwindow.png) right center no-repeat; - padding-right: 18px; -} -h2 { - padding: 4px 4px 4px 6px; - border: 1px solid #999; - color: #900; - background-color: #ddd; - font-weight:900; - font-size: x-large; -} -h3 { - padding: 4px 4px 4px 6px; - border: 1px solid #aaa; - color: #900; - background-color: #eee; - font-weight: normal; - font-size: large; -} -h4 { - padding: 4px 4px 4px 6px; - border: 1px solid #bbb; - color: #900; - background-color: #fff; - font-weight: normal; - font-size: large; -} -h5 { - padding: 4px 4px 4px 6px; - color: #900; - font-size: normal; -} -p { - line-height: 1.3em; - font-size: small; -} -#breadcrumbs { - border-top: 1px solid #aaa; - border-bottom: 1px solid #aaa; - background-color: #ccc; -} -#leftColumn { - margin: 10px 0 0 5px; - border: 1px solid #999; - background-color: #eee; -} -#navcolumn h5 { - font-size: smaller; - border-bottom: 1px solid #aaaaaa; - padding-top: 2px; - color: #000; -} - -table.bodyTable th { - color: white; - background-color: #bbb; - text-align: left; - font-weight: bold; -} - -table.bodyTable th, table.bodyTable td { - font-size: 1em; -} - -table.bodyTable tr.a { - background-color: #ddd; -} - -table.bodyTable tr.b { - background-color: #eee; -} - -.source { - border: 1px solid #999; -} -dl { - padding: 4px 4px 4px 6px; - border: 1px solid #aaa; - background-color: #ffc; -} -dt { - color: #900; -} -#organizationLogo img, #projectLogo img, #projectLogo span{ - margin: 8px; -} -#banner { - border-bottom: 1px solid #fff; -} -.errormark, .warningmark, .donemark, .infomark { - background: url(../images/icon_error_sml.gif) no-repeat; -} - -.warningmark { - background-image: url(../images/icon_warning_sml.gif); -} - -.donemark { - background-image: url(../images/icon_success_sml.gif); -} - -.infomark { - background-image: url(../images/icon_info_sml.gif); -} - diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/css/print.css b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/css/print.css deleted file mode 100644 index a5e7bd95f..000000000 --- a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/css/print.css +++ /dev/null @@ -1,7 +0,0 @@ -#banner, #footer, #leftcol, #breadcrumbs, .docs #toc, .docs .courtesylinks, #leftColumn, #navColumn { - display: none !important; -} -#bodyColumn, body.docs div.docs { - margin: 0 !important; - border: none !important -} diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/css/site.css b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/css/site.css deleted file mode 100644 index 055e7e286..000000000 --- a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/css/site.css +++ /dev/null @@ -1 +0,0 @@ -/* You can override this file with your own styles */ \ No newline at end of file diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/dependencies.html b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/dependencies.html deleted file mode 100644 index 0e426225c..000000000 --- a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/dependencies.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - Project Dependencies - - - - - - - - - -
- -
-
-
-

Project Dependencies

compile

The following is a list of compile dependencies for this project. These dependencies are required to compile and run the application:

GroupIdArtifactIdVersionTypeLicense
com.google.api-clientgoogle-api-client1.12.0-betajarThe Apache Software License, Version 2.0

Project Transitive Dependencies

The following is a list of transitive dependencies for this project. Transitive dependencies are the dependencies of the project dependencies.

compile

The following is a list of compile dependencies for this project. These dependencies are required to compile and run the application:

GroupIdArtifactIdVersionTypeLicense
com.google.androidandroid1.5_r4jarApache 2.0
com.google.code.findbugsjsr3051.3.9jarThe Apache Software License, Version 2.0
com.google.code.gsongson2.1jarThe Apache Software License, Version 2.0
com.google.guavaguava11.0.1jarThe Apache Software License, Version 2.0
com.google.http-clientgoogle-http-client1.12.0-betajarThe Apache Software License, Version 2.0
com.google.oauth-clientgoogle-oauth-client1.12.0-betajarThe Apache Software License, Version 2.0
com.google.protobufprotobuf-java2.2.0jarNew BSD license
commons-codeccommons-codec1.6jarThe Apache Software License, Version 2.0
commons-loggingcommons-logging1.1.1jarThe Apache Software License, Version 2.0
junitjunit4.8.2jarCommon Public License Version 1.0
org.apache.httpcomponentshttpclient4.0.3jar../LICENSE.txt
org.apache.httpcomponentshttpcore4.0.1jarApache License
org.codehaus.jacksonjackson-core-asl1.9.4jarThe Apache Software License, Version 2.0
org.khronosopengl-apigl1.1-android-2.1_r1jarApache 2.0
xercesxmlParserAPIs2.6.2jar-
xpp3xpp31.1.4cjarIndiana University Extreme! Lab Software License, vesion 1.1.1-Public Domain-Apache Software License, version 1.1

Project Dependency Graph

-

Dependency Tree

Licenses

Apache Software License, version 1.1: MXP1: Xml Pull Parser 3rd Edition (XPP3)

Public Domain: MXP1: Xml Pull Parser 3rd Edition (XPP3)

Unknown: xmlParserAPIs

Apache License: HttpClient, HttpCore

New BSD license: Protocol Buffer Java API

Common Public License Version 1.0: JUnit

Apache 2.0: Google Android Java ME Library (Khronos), Google Android Library

The Apache Software License, Version 2.0: Drive API v2, Commons Codec, Commons Logging, FindBugs-jsr305, Google APIs Client Library for Java, Google HTTP Client Library for Java, Google OAuth Client Library for Java, Gson, Guava: Google Core Libraries for Java, Jackson

Indiana University Extreme! Lab Software License, vesion 1.1.1: MXP1: Xml Pull Parser 3rd Edition (XPP3)

Dependency File Details

FilenameSizeEntriesClassesPackagesJDK RevDebug
android-1.5_r4.jar2.04 MB1,894965411.5debug
google-api-client-1.12.0-beta.jar76.92 kB775691.5debug
jsr305-1.3.9.jar32.24 kB723531.5debug
gson-2.1.jar175.89 kB15814861.5debug
guava-11.0.1.jar1.57 MB1,2901,267121.5debug
google-http-client-1.12.0-beta.jar234.84 kB207177181.5debug
google-oauth-client-1.12.0-beta.jar76.02 kB836571.5debug
protobuf-java-2.2.0.jar312.80 kB15614611.5debug
commons-codec-1.6.jar227.32 kB2187661.5debug
commons-logging-1.1.1.jar59.26 kB422821.1debug
junit-4.8.2.jar231.78 kB267230301.5debug
httpclient-4.0.3.jar286.03 kB267231221.5debug
httpcore-4.0.1.jar168.84 kB181158101.3debug
jackson-core-asl-1.9.4.jar222.96 kB13612081.5debug
opengl-api-gl1.1-android-2.1_r1.jar18.06 kB251321.5debug
xmlParserAPIs-2.6.2.jar121.80 kB238207171.1release
xpp3-1.1.4c.jar117.25 kB7856131.1debug
TotalSizeEntriesClassesPackagesJDK RevDebug
175.92 MB5,3893,9782071.516
compile: 17compile: 5.92 MBcompile: 5,389compile: 3,978compile: 207-compile: 16

Dependency Repository Locations

Repo IDURLReleaseSnapshot
apache.snapshotshttp://people.apache.org/repo/m2-snapshot-repository-Yes-
google-api-serviceshttp://mavenrepo.google-api-java-client.googlecode.com/hg-Yes-
sonatype-nexus-snapshotshttps://oss.sonatype.org/content/repositories/snapshots-Yes-
centralhttp://repo1.maven.org/maven2Yes--

Repository locations for each of the Dependencies.

Artifactapache.snapshotsgoogle-api-servicessonatype-nexus-snapshotscentral
com.google.android:android:jar:1.5_r4---Found at http://repo1.maven.org/maven2
com.google.api-client:google-api-client:jar:1.12.0-beta---Found at http://repo1.maven.org/maven2
com.google.code.findbugs:jsr305:jar:1.3.9---Found at http://repo1.maven.org/maven2
com.google.code.gson:gson:jar:2.1---Found at http://repo1.maven.org/maven2
com.google.guava:guava:jar:11.0.1---Found at http://repo1.maven.org/maven2
com.google.http-client:google-http-client:jar:1.12.0-beta---Found at http://repo1.maven.org/maven2
com.google.oauth-client:google-oauth-client:jar:1.12.0-beta---Found at http://repo1.maven.org/maven2
com.google.protobuf:protobuf-java:jar:2.2.0---Found at http://repo1.maven.org/maven2
commons-codec:commons-codec:jar:1.6---Found at http://repo1.maven.org/maven2
commons-logging:commons-logging:jar:1.1.1---Found at http://repo1.maven.org/maven2
junit:junit:jar:4.8.2---Found at http://repo1.maven.org/maven2
org.apache.httpcomponents:httpclient:jar:4.0.3---Found at http://repo1.maven.org/maven2
org.apache.httpcomponents:httpcore:jar:4.0.1---Found at http://repo1.maven.org/maven2
org.codehaus.jackson:jackson-core-asl:jar:1.9.4---Found at http://repo1.maven.org/maven2
org.khronos:opengl-api:jar:gl1.1-android-2.1_r1---Found at http://repo1.maven.org/maven2
xerces:xmlParserAPIs:jar:2.6.2---Found at http://repo1.maven.org/maven2
xpp3:xpp3:jar:1.1.4c---Found at http://repo1.maven.org/maven2
Totalapache.snapshotsgoogle-api-servicessonatype-nexus-snapshotscentral
17 (compile: 17)00017
-
-
-
-
-
- - - diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/close.gif b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/close.gif deleted file mode 100644 index 1c26bbc52..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/close.gif and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/collapsed.gif b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/collapsed.gif deleted file mode 100644 index 6e7108406..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/collapsed.gif and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/expanded.gif b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/expanded.gif deleted file mode 100644 index 0fef3d89e..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/expanded.gif and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/external.png b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/external.png deleted file mode 100644 index 3f999fc88..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/external.png and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/icon_error_sml.gif b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/icon_error_sml.gif deleted file mode 100644 index 61132ef2b..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/icon_error_sml.gif and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/icon_info_sml.gif b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/icon_info_sml.gif deleted file mode 100644 index c6cb9ad7c..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/icon_info_sml.gif and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/icon_success_sml.gif b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/icon_success_sml.gif deleted file mode 100644 index 52e85a430..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/icon_success_sml.gif and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/icon_warning_sml.gif b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/icon_warning_sml.gif deleted file mode 100644 index 873bbb52c..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/icon_warning_sml.gif and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/logos/build-by-maven-black.png b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/logos/build-by-maven-black.png deleted file mode 100644 index 919fd0f66..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/logos/build-by-maven-black.png and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/logos/build-by-maven-white.png b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/logos/build-by-maven-white.png deleted file mode 100644 index 7d44c9c2e..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/logos/build-by-maven-white.png and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/logos/maven-feather.png b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/logos/maven-feather.png deleted file mode 100644 index b5ada836e..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/logos/maven-feather.png and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/newwindow.png b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/newwindow.png deleted file mode 100644 index 6287f72bd..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/dependencies/images/newwindow.png and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/descriptor.json b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/descriptor.json deleted file mode 100644 index 2733123f1..000000000 --- a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/descriptor.json +++ /dev/null @@ -1,686 +0,0 @@ -{ - "discoveryLink": "./apis/drive/v2/rest", - "kind": "discovery#directoryItem", - "description": "The API to interact with Drive.", - "title": "Drive API", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/drive/v2/rest", - "preferred": true, - "version": "v2", - "icons": { - "x32": "https://ssl.gstatic.com/docs/doclist/images/drive_icon_32.png", - "x16": "https://ssl.gstatic.com/docs/doclist/images/drive_icon_16.png" - }, - "documentationLink": "https://developers.google.com/drive/", - "id": "drive:v2", - "name": "drive", - "files": [ - { - "downloadUrl": "/downloads/drive/v2/30/java/1.12.0-beta/google-api-services-drive-v2-rev30-1.12.0-beta.jar", - "path": "google-api-services-drive-v2-rev30-1.12.0-beta.jar", - "type": "binary", - "timestamp": "2012-12-08 00:32" - }, - { - "downloadUrl": "/downloads/drive/v2/30/java/1.12.0-beta/google-api-services-drive-v2-rev30-1.12.0-beta-javadoc.jar", - "path": "google-api-services-drive-v2-rev30-1.12.0-beta-javadoc.jar", - "type": "documentation", - "timestamp": "2012-12-08 00:33" - }, - { - "downloadUrl": "/downloads/drive/v2/30/java/1.12.0-beta/google-api-services-drive-v2-rev30-1.12.0-beta-sources.jar", - "path": "google-api-services-drive-v2-rev30-1.12.0-beta-sources.jar", - "type": "source", - "timestamp": "2012-12-08 00:32" - }, - { - "path": "google-api-services-drive-v2-rev30-1.12.0-beta.jar.properties", - "type": "android.properties" - } - ], - "revision": 30, - "language": "java", - "language_version": "1.12.0-beta", - "dependencies": [ - { - "files": [ - { - "downloadUrl": "http://google-api-java-client.googlecode.com/files/google-api-java-client-1.12.0-beta.zip", - "type": "bundle" - } - ], - "version": "1.12.0-beta", - "name": "Google API Java Client Bundle", - "environments": [ - "manual" - ] - }, - { - "files": [ - { - "path": "libs/google-api-client-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-api-client-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - }, - { - "path": "libs/google-api-client-1.12.0-beta.jar.properties", - "type": "android-properties" - } - ], - "version": "1.12.0-beta", - "name": "Google APIs Client Library", - "environments": [ - "*" - ] - }, - { - "files": [ - { - "path": "libs/google-api-client-android-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-api-client-android-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - }, - { - "path": "libs/google-api-client-android-1.12.0-beta.jar.properties", - "type": "android-properties" - } - ], - "version": "1.12.0-beta", - "name": "Android platform extensions to the Google APIs Client Library", - "environments": [ - "android" - ] - }, - { - "files": [ - { - "path": "libs/google-api-client-appengine-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-api-client-appengine-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "1.12.0-beta", - "name": "Google App Engine extensions to the Google APIs Client Library", - "environments": [ - "appengine" - ] - }, - { - "files": [ - { - "path": "libs/google-api-client-java6-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-api-client-java6-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "1.12.0-beta", - "name": "Java 6 (and higher) extensions to the Google APIs Client Library", - "environments": [ - "generic" - ] - }, - { - "files": [ - { - "path": "libs/google-oauth-client-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-oauth-client-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - }, - { - "path": "libs/google-oauth-client-1.12.0-beta.jar.properties", - "type": "android-properties" - } - ], - "version": "1.12.0-beta", - "name": "Google OAuth Client Library", - "environments": [ - "*" - ] - }, - { - "files": [ - { - "path": "libs/google-oauth-client-appengine-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-oauth-client-appengine-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "1.12.0-beta", - "name": "Google App Engine extensions to the Google OAuth Client Library", - "environments": [ - "appengine" - ] - }, - { - "files": [ - { - "path": "libs/google-oauth-client-java6-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-oauth-client-java6-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "1.12.0-beta", - "name": "Java 6 (and higher) extensions to the Google OAuth Client Library", - "environments": [ - "generic" - ] - }, - { - "files": [ - { - "path": "libs/google-oauth-client-jetty-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-oauth-client-jetty-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "1.12.0-beta", - "name": "Jetty extensions to the Google OAuth Client Library", - "environments": [ - "generic" - ] - }, - { - "files": [ - { - "path": "libs/google-oauth-client-servlet-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-oauth-client-servlet-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "1.12.0-beta", - "name": "Servlet and JDO extensions to the Google OAuth Client Library", - "environments": [ - "appengine", - "servlet" - ] - }, - { - "files": [ - { - "path": "libs/google-http-client-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-http-client-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - }, - { - "path": "libs/google-http-client-1.12.0-beta.jar.properties", - "type": "android-properties" - } - ], - "version": "1.12.0-beta", - "name": "Google HTTP Client Library", - "environments": [ - "*" - ] - }, - { - "files": [ - { - "path": "libs/google-http-client-android-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-http-client-android-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - }, - { - "path": "libs/google-http-client-android-1.12.0-beta.jar.properties", - "type": "android-properties" - } - ], - "version": "1.12.0-beta", - "name": "Android platform extensions to the Google HTTP Client Library", - "environments": [ - "android" - ] - }, - { - "files": [ - { - "path": "libs/google-http-client-appengine-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-http-client-appengine-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "1.12.0-beta", - "name": "Google App Engine extensions to the Google HTTP Client Library", - "environments": [ - "appengine" - ] - }, - { - "files": [ - { - "path": "libs/google-http-client-gson-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-http-client-gson-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - }, - { - "path": "libs/google-http-client-gson-1.12.0-beta.jar.properties", - "type": "android-properties" - } - ], - "version": "1.12.0-beta", - "name": "GSON extensions to the Google HTTP Client Library", - "environments": [ - "*" - ] - }, - { - "files": [ - { - "path": "libs/google-http-client-jackson-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-http-client-jackson-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - }, - { - "path": "libs/google-http-client-jackson-1.12.0-beta.jar.properties", - "type": "android-properties" - } - ], - "version": "1.12.0-beta", - "name": "Jackson extensions to the Google HTTP Client Library", - "environments": [ - "*" - ] - }, - { - "files": [ - { - "path": "libs/google-http-client-jackson2-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-http-client-jackson2-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - }, - { - "path": "libs/google-http-client-jackson2-1.12.0-beta.jar.properties", - "type": "android-properties" - } - ], - "version": "1.12.0-beta", - "name": "Jackson 2 extensions to the Google HTTP Client Library", - "environments": [ - "*" - ] - }, - { - "files": [ - { - "path": "libs/commons-logging-1.1.1.jar", - "type": "binary" - }, - { - "path": "libs-sources/commons-logging-1.1.1-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "1.1.1", - "name": "Commons Logging", - "environments": [ - "servlet", - "generic" - ] - }, - { - "files": [ - { - "path": "libs/guava-jdk5-13.0.jar", - "type": "binary" - }, - { - "path": "libs-sources/guava-jdk5-13.0-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - }, - { - "path": "libs/guava-jdk5-13.0.jar.properties", - "type": "android-properties" - } - ], - "version": "jdk5-13.0", - "name": "Google Guava", - "environments": [ - "*" - ] - }, - { - "files": [ - { - "path": "libs/gson-2.1.jar", - "type": "binary" - }, - { - "path": "libs-sources/gson-2.1-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - }, - { - "path": "libs/gson-2.1.jar.properties", - "type": "android-properties" - } - ], - "version": "2.1", - "name": "GSON", - "environments": [ - "*" - ] - }, - { - "files": [ - { - "path": "libs/httpclient-4.0.3.jar", - "type": "binary" - }, - { - "path": "libs-sources/httpclient-4.0.3-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "4.0.3", - "name": "HTTP Client", - "environments": [ - "servlet", - "generic" - ] - }, - { - "files": [ - { - "path": "libs/httpcore-4.0.1.jar", - "type": "binary" - }, - { - "path": "libs-sources/httpcore-4.0.1-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "4.0.1", - "name": "HTTP Core", - "environments": [ - "servlet", - "generic" - ] - }, - { - "files": [ - { - "path": "libs/jackson-core-asl-1.9.9.jar", - "type": "binary" - }, - { - "path": "libs-sources/jackson-core-asl-1.9.9-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - }, - { - "path": "libs/jackson-core-asl-1.9.9.jar.properties", - "type": "android-properties" - } - ], - "version": "1.9.9", - "name": "Jackson Core ASL", - "environments": [ - "*" - ] - }, - { - "files": [ - { - "path": "libs/jackson-core-2.0.5.jar", - "type": "binary" - }, - { - "path": "libs-sources/jackson-core-2.0.5-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - }, - { - "path": "libs/jackson-core-2.0.5.jar.properties", - "type": "android-properties" - } - ], - "version": "2.0.5", - "name": "Jackson2 Core", - "environments": [ - "*" - ] - }, - { - "files": [ - { - "path": "libs/jdo2-api-2.3-eb.jar", - "type": "binary" - }, - { - "path": "libs-sources/jdo2-api-2.3-eb-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "2.3-eb", - "name": "JDO2 API", - "environments": [ - "appengine", - "servlet" - ] - }, - { - "files": [ - { - "path": "libs/jetty-6.1.26.jar", - "type": "binary" - }, - { - "path": "libs-sources/jetty-6.1.26-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "6.1.26", - "name": "Jetty", - "environments": [ - "generic" - ] - }, - { - "files": [ - { - "path": "libs/jetty-util-6.1.26.jar", - "type": "binary" - }, - { - "path": "libs-sources/jetty-util-6.1.26-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "6.1.26", - "name": "Jetty Util", - "environments": [ - "generic" - ] - }, - { - "files": [ - { - "path": "libs/transaction-api-1.1.jar", - "type": "binary" - }, - { - "path": "libs-sources/transaction-api-1.1-sources.jar", - "type": "source" - }, - { - "path": "dependencies/CDDL-LICENSE.txt", - "type": "license" - } - ], - "version": "1.1", - "name": "Transaction API", - "environments": [ - "appengine", - "servlet" - ] - }, - { - "files": [ - { - "path": "libs/xpp3-1.1.4c.jar", - "type": "binary" - }, - { - "path": "libs-sources/xpp3-1.1.4c-sources.jar", - "type": "source" - }, - { - "path": "dependencies/xpp3_LICENSE.txt", - "type": "license" - } - ], - "version": "1.1.4c", - "name": "XPP3", - "environments": [ - "appengine", - "servlet", - "generic" - ] - } - ], - "proguard-config": "proguard-google-api-client.txt", - "icon_files": { - "x32": "icons/drive_icon_32.png", - "x16": "icons/drive_icon_16.png" - } -} \ No newline at end of file diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/google-api-services-drive-v2-rev30-1.12.0-beta-javadoc.jar b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/google-api-services-drive-v2-rev30-1.12.0-beta-javadoc.jar deleted file mode 100644 index 534bcbd70..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/google-api-services-drive-v2-rev30-1.12.0-beta-javadoc.jar and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/google-api-services-drive-v2-rev30-1.12.0-beta-sources.jar b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/google-api-services-drive-v2-rev30-1.12.0-beta-sources.jar deleted file mode 100644 index 6361faea1..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/google-api-services-drive-v2-rev30-1.12.0-beta-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/google-api-services-drive-v2-rev30-1.12.0-beta.jar.properties b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/google-api-services-drive-v2-rev30-1.12.0-beta.jar.properties deleted file mode 100644 index 5c3621769..000000000 --- a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/google-api-services-drive-v2-rev30-1.12.0-beta.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/google-api-services-drive-v2-rev30-1.12.0-beta-sources.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/icons/drive_icon_16.png b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/icons/drive_icon_16.png deleted file mode 100644 index 17937dec0..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/icons/drive_icon_16.png and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/icons/drive_icon_32.png b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/icons/drive_icon_32.png deleted file mode 100644 index 43b646694..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/icons/drive_icon_32.png and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/google-api-client-1.12.0-beta-sources.jar b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/google-api-client-1.12.0-beta-sources.jar deleted file mode 100644 index 6c8d980d6..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/google-api-client-1.12.0-beta-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/google-api-client-android-1.12.0-beta-sources.jar b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/google-api-client-android-1.12.0-beta-sources.jar deleted file mode 100644 index 16934a51d..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/google-api-client-android-1.12.0-beta-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/google-http-client-1.12.0-beta-sources.jar b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/google-http-client-1.12.0-beta-sources.jar deleted file mode 100644 index 4507e0a21..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/google-http-client-1.12.0-beta-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/google-http-client-android-1.12.0-beta-sources.jar b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/google-http-client-android-1.12.0-beta-sources.jar deleted file mode 100644 index 7ce36e594..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/google-http-client-android-1.12.0-beta-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/google-http-client-gson-1.12.0-beta-sources.jar b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/google-http-client-gson-1.12.0-beta-sources.jar deleted file mode 100644 index 168df18ae..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/google-http-client-gson-1.12.0-beta-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/google-http-client-jackson-1.12.0-beta-sources.jar b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/google-http-client-jackson-1.12.0-beta-sources.jar deleted file mode 100644 index 377c1dea9..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/google-http-client-jackson-1.12.0-beta-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/google-http-client-jackson2-1.12.0-beta-sources.jar b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/google-http-client-jackson2-1.12.0-beta-sources.jar deleted file mode 100644 index 442a357e2..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/google-http-client-jackson2-1.12.0-beta-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/google-oauth-client-1.12.0-beta-sources.jar b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/google-oauth-client-1.12.0-beta-sources.jar deleted file mode 100644 index bd82679dd..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/google-oauth-client-1.12.0-beta-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/gson-2.1-sources.jar b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/gson-2.1-sources.jar deleted file mode 100644 index 09396a02e..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/gson-2.1-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/guava-jdk5-13.0-sources.jar b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/guava-jdk5-13.0-sources.jar deleted file mode 100644 index c5ee71697..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/guava-jdk5-13.0-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/jackson-core-2.0.5-sources.jar b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/jackson-core-2.0.5-sources.jar deleted file mode 100644 index af5dc6e4d..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/jackson-core-2.0.5-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/jackson-core-asl-1.9.9-sources.jar b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/jackson-core-asl-1.9.9-sources.jar deleted file mode 100644 index af5dc6e4d..000000000 Binary files a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs-sources/jackson-core-asl-1.9.9-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-api-client-1.12.0-beta.jar.properties b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-api-client-1.12.0-beta.jar.properties deleted file mode 100644 index 39c242523..000000000 --- a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-api-client-1.12.0-beta.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/google-api-client-1.12.0-beta-sources.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-api-client-android-1.12.0-beta.jar.properties b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-api-client-android-1.12.0-beta.jar.properties deleted file mode 100644 index 31042993d..000000000 --- a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-api-client-android-1.12.0-beta.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/google-api-client-android-1.12.0-beta-sources.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-http-client-1.12.0-beta.jar.properties b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-http-client-1.12.0-beta.jar.properties deleted file mode 100644 index 22d7a272a..000000000 --- a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-http-client-1.12.0-beta.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/google-http-client-1.12.0-beta-sources.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-http-client-android-1.12.0-beta.jar.properties b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-http-client-android-1.12.0-beta.jar.properties deleted file mode 100644 index b804cc361..000000000 --- a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-http-client-android-1.12.0-beta.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/google-http-client-android-1.12.0-beta-sources.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-http-client-gson-1.12.0-beta.jar.properties b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-http-client-gson-1.12.0-beta.jar.properties deleted file mode 100644 index 3cdc720ab..000000000 --- a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-http-client-gson-1.12.0-beta.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/google-http-client-gson-1.12.0-beta-sources.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-http-client-jackson-1.12.0-beta.jar.properties b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-http-client-jackson-1.12.0-beta.jar.properties deleted file mode 100644 index 0f06bb8c3..000000000 --- a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-http-client-jackson-1.12.0-beta.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/google-http-client-jackson-1.12.0-beta-sources.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-http-client-jackson2-1.12.0-beta.jar.properties b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-http-client-jackson2-1.12.0-beta.jar.properties deleted file mode 100644 index c70f7d815..000000000 --- a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-http-client-jackson2-1.12.0-beta.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/google-http-client-jackson2-1.12.0-beta-sources.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-oauth-client-1.12.0-beta.jar.properties b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-oauth-client-1.12.0-beta.jar.properties deleted file mode 100644 index d8ef90d84..000000000 --- a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-oauth-client-1.12.0-beta.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/google-oauth-client-1.12.0-beta-sources.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/gson-2.1.jar.properties b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/gson-2.1.jar.properties deleted file mode 100644 index cfa21515f..000000000 --- a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/gson-2.1.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/gson-2.1-sources.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/guava-jdk5-13.0.jar.properties b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/guava-jdk5-13.0.jar.properties deleted file mode 100644 index 415299133..000000000 --- a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/guava-jdk5-13.0.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/guava-jdk5-13.0-sources.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/jackson-core-2.0.5.jar.properties b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/jackson-core-2.0.5.jar.properties deleted file mode 100644 index 8ceae8ed1..000000000 --- a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/jackson-core-2.0.5.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/jackson-core-2.0.5-sources.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/jackson-core-asl-1.9.9.jar.properties b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/jackson-core-asl-1.9.9.jar.properties deleted file mode 100644 index 53aca9d0d..000000000 --- a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/jackson-core-asl-1.9.9.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/jackson-core-asl-1.9.9-sources.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/proguard-google-api-client.txt b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/proguard-google-api-client.txt deleted file mode 100644 index ca7616a58..000000000 --- a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/proguard-google-api-client.txt +++ /dev/null @@ -1,25 +0,0 @@ -# ProGuard Configuration file -# -# See http://proguard.sourceforge.net/index.html#manual/usage.html - -# Needed to keep generic types and @Key annotations accessed via reflection - --keepattributes Signature,RuntimeVisibleAnnotations,AnnotationDefault - --keepclassmembers class * { - @com.google.api.client.util.Key ; -} - -# Needed by Guava -# See https://groups.google.com/forum/#!topic/guava-discuss/YCZzeCiIVoI - --dontwarn sun.misc.Unsafe --dontwarn com.google.common.collect.MinMaxPriorityQueue - -# Needed by google-http-client-android when linking against an older platform version - --dontwarn com.google.api.client.extensions.android.** - -# Needed by google-api-client-android when linking against an older platform version - --dontwarn com.google.api.client.googleapis.extensions.android.** diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/readme.html b/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/readme.html deleted file mode 100644 index 2efe6d38c..000000000 --- a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/readme.html +++ /dev/null @@ -1,158 +0,0 @@ - -Drive API v2 Client Library for Java - -

Drive API v2 Client Library for Java

- -

Overview

-

High-level details about this library can be found at -http://code.google.com/p/google-api-java-client -

- -

License

-The license can be found here.
- -

Generated service-specific Library

-The generated service-specific library can be found in the top level directory -of the zip file: -google-api-services-drive-v2-rev30-1.12.0-beta.jar - -

Maven Usage

-Maven users can specify the service-specific generated library in their -project's plugin configuration: -
-<repositories>
-  <repository>
-    <id>googleapis</id>
-    <url>http://mavenrepo.google-api-java-client.googlecode.com/hg/</url>
-  </repository>
-</repositories>
-
-<dependency>
-  <groupId>com.google.apis</groupId>
-  <artifactId>google-api-services-drive</artifactId>
-  <version>v2-rev30-1.12.0-beta</version>
-</dependency>
-
- - -

Eclipse

-A .classpath file snippet that can be included in your project's .classpath has been provided here. -Please only use the classpathentry's you actually need (see below for details). - -

ProGuard

-A ProGuard configuration file proguard-google-api-client.txt -is included for common settings for using the library. On Android projects, you may want to add a reference to -proguard-google-api-client.txt in the project.properties file under the -proguard.config property. - -

Dependencies

-

-Dependent jars for -google-api-services-drive-v2-rev30-1.12.0-beta.jar -can be found in the libs folder and the corresponding source -jars can be found in the libs-sources folder. -

-The dependency structure and licenses can be found in -dependencies.html. -

- -

Dependencies for all Platforms

-The following are the jars from the libs folder required for -applications on all platforms: -
    -
  • google-api-client-1.12.0-beta.jar
  • -
  • google-oauth-client-1.12.0-beta.jar
  • -
  • google-http-client-1.12.0-beta.jar
  • -
  • guava-jdk5-13.0.jar
  • -
  • jsr305-1.3.9.jar
  • -
  • google-http-client-gson-1.12.0-beta.jar (when using GSON) -
      -
    • gson-2.1.jar
    • -
    -
  • -
  • google-http-client-jackson-1.12.0-beta.jar (when using Jackson) -
      -
    • jackson-core-asl-1.9.9.jar
    • -
    -
  • -
  • google-http-client-jackson2-1.12.0-beta.jar (when using Jackson 2) -
      -
    • jackson-core-$2.0.5.jar
    • -
    -
  • -
- -

Android Dependencies

-The following are the jars from the libs folder required for -android applications or a newer compatible version of each dependency: -
    -
  • google-api-client-android-1.12.0-beta.jar (for SDK >= 2.1)
  • -
  • google-http-client-android-1.12.0-beta.jar (for SDK >= 2.1)
  • -
  • [deprecated] google-api-client-android2-1.12.0-beta.jar (for SDK >= 2.1)
  • -
  • [deprecated] google-http-client-android2-1.12.0-beta.jar (for SDK >= 2.1)
  • -
  • [deprecated] google-http-client-android3-1.12.0-beta.jar (for SDK >= 3.0)
  • -
-libs folder also contains properties files that specify the location of source -jars for Android projects in Eclipse.
-Please see the -Android wiki -for the Android Developer's Guide. - -

Google App Engine Dependencies

-The following are the jars from the libs folder required for -Google App Engine applications or a newer compatible version of each dependency: -
    -
  • google-api-client-appengine-1.12.0-beta.jar
  • -
  • google-oauth-client-appengine-1.12.0-beta.jar
  • -
  • google-oauth-client-servlet-1.12.0-beta.jar
  • -
  • google-http-client-appengine-1.12.0-beta.jar
  • -
  • jdo2-api-2.3-eb.jar
  • -
  • transaction-api-1.1.jar
  • -
  • xpp3-1.1.4c.jar
  • -
-Please see the -GoogleAppEngine wiki -for the Google App Engine Developer's Guide. - -

Servlet Dependencies

-The following are the jars from the libs folder required for -Servlet applications or a newer compatible version of each dependency: -
    -
  • google-oauth-client-1.12.0-beta.jar
  • -
  • google-oauth-client-servlet-1.12.0-beta.jar
  • -
  • commons-logging-1.1.1.jar
  • -
  • httpclient-4.0.3.jar
  • -
  • httpcore-4.0.1.jar
  • -
  • jdo2-api-2.3-eb.jar
  • -
  • transaction-api-1.1.jar
  • -
  • xpp3-1.1.4c.jar
  • -
- -

General Purpose Java 5 Environment Dependencies

-The following are the jars from the libs folder required for -general purpose Java 5 applications (or a newer compatible version of each dependency): -
    -
  • google-api-client-java6-1.12.0-beta.jar
  • -
  • google-oauth-client-java6-1.12.0-beta.jar
  • -
      -
    • google-oauth-client-jetty-${project.oauth.version}.jar (for Jetty 6) -
        -
      • jetty-${jettyVersion}
      • -
      • jetty-util-${jettyUtilVersion}
      • -
      -
    • -
    -
  • commons-logging-1.1.1.jar
  • -
  • httpclient-4.0.3.jar
  • -
  • httpcore-4.0.1.jar
  • -
  • xpp3-1.1.4c.jar
  • -
- - - - diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/LICENSE.txt b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/LICENSE.txt deleted file mode 100644 index d64569567..000000000 --- a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/LICENSE.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/classpath-include b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/classpath-include deleted file mode 100644 index 97fea11f4..000000000 --- a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/classpath-include +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/BSD-LICENSE.txt b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/BSD-LICENSE.txt deleted file mode 100644 index dcdcc4234..000000000 --- a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/BSD-LICENSE.txt +++ /dev/null @@ -1,27 +0,0 @@ -BSD License - -Copyright (c) 2000-2006, www.hamcrest.org -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list of -conditions and the following disclaimer. Redistributions in binary form must reproduce -the above copyright notice, this list of conditions and the following disclaimer in -the documentation and/or other materials provided with the distribution. - -Neither the name of Hamcrest nor the names of its contributors may be used to endorse -or promote products derived from this software without specific prior written -permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY -WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -DAMAGE. diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/css/maven-base.css b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/css/maven-base.css deleted file mode 100644 index f39e42c48..000000000 --- a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/css/maven-base.css +++ /dev/null @@ -1,151 +0,0 @@ -body { - margin: 0px; - padding: 0px; -} -img { - border:none; -} -table { - padding:0px; - width: 100%; - margin-left: -2px; - margin-right: -2px; -} -acronym { - cursor: help; - border-bottom: 1px dotted #feb; -} -table.bodyTable th, table.bodyTable td { - padding: 2px 4px 2px 4px; - vertical-align: top; -} -div.clear{ - clear:both; - visibility: hidden; -} -div.clear hr{ - display: none; -} -#bannerLeft, #bannerRight { - font-size: xx-large; - font-weight: bold; -} -#bannerLeft img, #bannerRight img { - margin: 0px; -} -.xleft, #bannerLeft img { - float:left; -} -.xright, #bannerRight { - float:right; -} -#banner { - padding: 0px; -} -#banner img { - border: none; -} -#breadcrumbs { - padding: 3px 10px 3px 10px; -} -#leftColumn { - width: 170px; - float:left; - overflow: auto; -} -#bodyColumn { - margin-right: 1.5em; - margin-left: 197px; -} -#legend { - padding: 8px 0 8px 0; -} -#navcolumn { - padding: 8px 4px 0 8px; -} -#navcolumn h5 { - margin: 0; - padding: 0; - font-size: small; -} -#navcolumn ul { - margin: 0; - padding: 0; - font-size: small; -} -#navcolumn li { - list-style-type: none; - background-image: none; - background-repeat: no-repeat; - background-position: 0 0.4em; - padding-left: 16px; - list-style-position: outside; - line-height: 1.2em; - font-size: smaller; -} -#navcolumn li.expanded { - background-image: url(../images/expanded.gif); -} -#navcolumn li.collapsed { - background-image: url(../images/collapsed.gif); -} -#poweredBy { - text-align: center; -} -#navcolumn img { - margin-top: 10px; - margin-bottom: 3px; -} -#poweredBy img { - display:block; - margin: 20px 0 20px 17px; -} -#search img { - margin: 0px; - display: block; -} -#search #q, #search #btnG { - border: 1px solid #999; - margin-bottom:10px; -} -#search form { - margin: 0px; -} -#lastPublished { - font-size: x-small; -} -.navSection { - margin-bottom: 2px; - padding: 8px; -} -.navSectionHead { - font-weight: bold; - font-size: x-small; -} -.section { - padding: 4px; -} -#footer { - padding: 3px 10px 3px 10px; - font-size: x-small; -} -#breadcrumbs { - font-size: x-small; - margin: 0pt; -} -.source { - padding: 12px; - margin: 1em 7px 1em 7px; -} -.source pre { - margin: 0px; - padding: 0px; -} -#navcolumn img.imageLink, .imageLink { - padding-left: 0px; - padding-bottom: 0px; - padding-top: 0px; - padding-right: 2px; - border: 0px; - margin: 0px; -} diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/css/maven-theme.css b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/css/maven-theme.css deleted file mode 100644 index ec29c893c..000000000 --- a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/css/maven-theme.css +++ /dev/null @@ -1,141 +0,0 @@ -body { - padding: 0px 0px 10px 0px; -} -body, td, select, input, li{ - font-family: Verdana, Helvetica, Arial, sans-serif; - font-size: 13px; -} -code{ - font-family: Courier, monospace; - font-size: 13px; -} -a { - text-decoration: none; -} -a:link { - color:#36a; -} -a:visited { - color:#47a; -} -a:active, a:hover { - color:#69c; -} -#legend li.externalLink { - background: url(../images/external.png) left top no-repeat; - padding-left: 18px; -} -a.externalLink, a.externalLink:link, a.externalLink:visited, a.externalLink:active, a.externalLink:hover { - background: url(../images/external.png) right center no-repeat; - padding-right: 18px; -} -#legend li.newWindow { - background: url(../images/newwindow.png) left top no-repeat; - padding-left: 18px; -} -a.newWindow, a.newWindow:link, a.newWindow:visited, a.newWindow:active, a.newWindow:hover { - background: url(../images/newwindow.png) right center no-repeat; - padding-right: 18px; -} -h2 { - padding: 4px 4px 4px 6px; - border: 1px solid #999; - color: #900; - background-color: #ddd; - font-weight:900; - font-size: x-large; -} -h3 { - padding: 4px 4px 4px 6px; - border: 1px solid #aaa; - color: #900; - background-color: #eee; - font-weight: normal; - font-size: large; -} -h4 { - padding: 4px 4px 4px 6px; - border: 1px solid #bbb; - color: #900; - background-color: #fff; - font-weight: normal; - font-size: large; -} -h5 { - padding: 4px 4px 4px 6px; - color: #900; - font-size: normal; -} -p { - line-height: 1.3em; - font-size: small; -} -#breadcrumbs { - border-top: 1px solid #aaa; - border-bottom: 1px solid #aaa; - background-color: #ccc; -} -#leftColumn { - margin: 10px 0 0 5px; - border: 1px solid #999; - background-color: #eee; -} -#navcolumn h5 { - font-size: smaller; - border-bottom: 1px solid #aaaaaa; - padding-top: 2px; - color: #000; -} - -table.bodyTable th { - color: white; - background-color: #bbb; - text-align: left; - font-weight: bold; -} - -table.bodyTable th, table.bodyTable td { - font-size: 1em; -} - -table.bodyTable tr.a { - background-color: #ddd; -} - -table.bodyTable tr.b { - background-color: #eee; -} - -.source { - border: 1px solid #999; -} -dl { - padding: 4px 4px 4px 6px; - border: 1px solid #aaa; - background-color: #ffc; -} -dt { - color: #900; -} -#organizationLogo img, #projectLogo img, #projectLogo span{ - margin: 8px; -} -#banner { - border-bottom: 1px solid #fff; -} -.errormark, .warningmark, .donemark, .infomark { - background: url(../images/icon_error_sml.gif) no-repeat; -} - -.warningmark { - background-image: url(../images/icon_warning_sml.gif); -} - -.donemark { - background-image: url(../images/icon_success_sml.gif); -} - -.infomark { - background-image: url(../images/icon_info_sml.gif); -} - diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/css/print.css b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/css/print.css deleted file mode 100644 index a5e7bd95f..000000000 --- a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/css/print.css +++ /dev/null @@ -1,7 +0,0 @@ -#banner, #footer, #leftcol, #breadcrumbs, .docs #toc, .docs .courtesylinks, #leftColumn, #navColumn { - display: none !important; -} -#bodyColumn, body.docs div.docs { - margin: 0 !important; - border: none !important -} diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/css/site.css b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/css/site.css deleted file mode 100644 index 055e7e286..000000000 --- a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/css/site.css +++ /dev/null @@ -1 +0,0 @@ -/* You can override this file with your own styles */ \ No newline at end of file diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/dependencies.html b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/dependencies.html deleted file mode 100644 index f262d16d0..000000000 --- a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/dependencies.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - Project Dependencies - - - - - - - - - -
- -
-
-
-

Project Dependencies

compile

The following is a list of compile dependencies for this project. These dependencies are required to compile and run the application:

GroupIdArtifactIdVersionTypeLicense
com.google.api-clientgoogle-api-client1.12.0-betajarThe Apache Software License, Version 2.0

Project Transitive Dependencies

The following is a list of transitive dependencies for this project. Transitive dependencies are the dependencies of the project dependencies.

compile

The following is a list of compile dependencies for this project. These dependencies are required to compile and run the application:

GroupIdArtifactIdVersionTypeLicense
com.google.androidandroid1.5_r4jarApache 2.0
com.google.code.findbugsjsr3051.3.9jarThe Apache Software License, Version 2.0
com.google.code.gsongson2.1jarThe Apache Software License, Version 2.0
com.google.guavaguava11.0.1jarThe Apache Software License, Version 2.0
com.google.http-clientgoogle-http-client1.12.0-betajarThe Apache Software License, Version 2.0
com.google.oauth-clientgoogle-oauth-client1.12.0-betajarThe Apache Software License, Version 2.0
com.google.protobufprotobuf-java2.2.0jarNew BSD license
commons-codeccommons-codec1.6jarThe Apache Software License, Version 2.0
commons-loggingcommons-logging1.1.1jarThe Apache Software License, Version 2.0
junitjunit4.8.2jarCommon Public License Version 1.0
org.apache.httpcomponentshttpclient4.0.3jar../LICENSE.txt
org.apache.httpcomponentshttpcore4.0.1jarApache License
org.codehaus.jacksonjackson-core-asl1.9.4jarThe Apache Software License, Version 2.0
org.khronosopengl-apigl1.1-android-2.1_r1jarApache 2.0
xercesxmlParserAPIs2.6.2jar-
xpp3xpp31.1.4cjarIndiana University Extreme! Lab Software License, vesion 1.1.1-Public Domain-Apache Software License, version 1.1

Project Dependency Graph

-

Dependency Tree

Licenses

Apache Software License, version 1.1: MXP1: Xml Pull Parser 3rd Edition (XPP3)

Public Domain: MXP1: Xml Pull Parser 3rd Edition (XPP3)

Unknown: xmlParserAPIs

Apache License: HttpClient, HttpCore

New BSD license: Protocol Buffer Java API

Common Public License Version 1.0: JUnit

Apache 2.0: Google Android Java ME Library (Khronos), Google Android Library

The Apache Software License, Version 2.0: Fusion Tables API v1, Commons Codec, Commons Logging, FindBugs-jsr305, Google APIs Client Library for Java, Google HTTP Client Library for Java, Google OAuth Client Library for Java, Gson, Guava: Google Core Libraries for Java, Jackson

Indiana University Extreme! Lab Software License, vesion 1.1.1: MXP1: Xml Pull Parser 3rd Edition (XPP3)

Dependency File Details

FilenameSizeEntriesClassesPackagesJDK RevDebug
android-1.5_r4.jar2.04 MB1,894965411.5debug
google-api-client-1.12.0-beta.jar76.92 kB775691.5debug
jsr305-1.3.9.jar32.24 kB723531.5debug
gson-2.1.jar175.89 kB15814861.5debug
guava-11.0.1.jar1.57 MB1,2901,267121.5debug
google-http-client-1.12.0-beta.jar234.84 kB207177181.5debug
google-oauth-client-1.12.0-beta.jar76.02 kB836571.5debug
protobuf-java-2.2.0.jar312.80 kB15614611.5debug
commons-codec-1.6.jar227.32 kB2187661.5debug
commons-logging-1.1.1.jar59.26 kB422821.1debug
junit-4.8.2.jar231.78 kB267230301.5debug
httpclient-4.0.3.jar286.03 kB267231221.5debug
httpcore-4.0.1.jar168.84 kB181158101.3debug
jackson-core-asl-1.9.4.jar222.96 kB13612081.5debug
opengl-api-gl1.1-android-2.1_r1.jar18.06 kB251321.5debug
xmlParserAPIs-2.6.2.jar121.80 kB238207171.1release
xpp3-1.1.4c.jar117.25 kB7856131.1debug
TotalSizeEntriesClassesPackagesJDK RevDebug
175.92 MB5,3893,9782071.516
compile: 17compile: 5.92 MBcompile: 5,389compile: 3,978compile: 207-compile: 16

Dependency Repository Locations

Repo IDURLReleaseSnapshot
apache.snapshotshttp://people.apache.org/repo/m2-snapshot-repository-Yes-
google-api-serviceshttp://mavenrepo.google-api-java-client.googlecode.com/hg-Yes-
sonatype-nexus-snapshotshttps://oss.sonatype.org/content/repositories/snapshots-Yes-
centralhttp://repo1.maven.org/maven2Yes--

Repository locations for each of the Dependencies.

Artifactapache.snapshotsgoogle-api-servicessonatype-nexus-snapshotscentral
com.google.android:android:jar:1.5_r4---Found at http://repo1.maven.org/maven2
com.google.api-client:google-api-client:jar:1.12.0-beta---Found at http://repo1.maven.org/maven2
com.google.code.findbugs:jsr305:jar:1.3.9---Found at http://repo1.maven.org/maven2
com.google.code.gson:gson:jar:2.1---Found at http://repo1.maven.org/maven2
com.google.guava:guava:jar:11.0.1---Found at http://repo1.maven.org/maven2
com.google.http-client:google-http-client:jar:1.12.0-beta---Found at http://repo1.maven.org/maven2
com.google.oauth-client:google-oauth-client:jar:1.12.0-beta---Found at http://repo1.maven.org/maven2
com.google.protobuf:protobuf-java:jar:2.2.0---Found at http://repo1.maven.org/maven2
commons-codec:commons-codec:jar:1.6---Found at http://repo1.maven.org/maven2
commons-logging:commons-logging:jar:1.1.1---Found at http://repo1.maven.org/maven2
junit:junit:jar:4.8.2---Found at http://repo1.maven.org/maven2
org.apache.httpcomponents:httpclient:jar:4.0.3---Found at http://repo1.maven.org/maven2
org.apache.httpcomponents:httpcore:jar:4.0.1---Found at http://repo1.maven.org/maven2
org.codehaus.jackson:jackson-core-asl:jar:1.9.4---Found at http://repo1.maven.org/maven2
org.khronos:opengl-api:jar:gl1.1-android-2.1_r1---Found at http://repo1.maven.org/maven2
xerces:xmlParserAPIs:jar:2.6.2---Found at http://repo1.maven.org/maven2
xpp3:xpp3:jar:1.1.4c---Found at http://repo1.maven.org/maven2
Totalapache.snapshotsgoogle-api-servicessonatype-nexus-snapshotscentral
17 (compile: 17)00017
-
-
-
-
-
- - - diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/close.gif b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/close.gif deleted file mode 100644 index 1c26bbc52..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/close.gif and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/collapsed.gif b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/collapsed.gif deleted file mode 100644 index 6e7108406..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/collapsed.gif and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/expanded.gif b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/expanded.gif deleted file mode 100644 index 0fef3d89e..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/expanded.gif and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/external.png b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/external.png deleted file mode 100644 index 3f999fc88..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/external.png and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/icon_error_sml.gif b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/icon_error_sml.gif deleted file mode 100644 index 61132ef2b..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/icon_error_sml.gif and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/icon_info_sml.gif b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/icon_info_sml.gif deleted file mode 100644 index c6cb9ad7c..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/icon_info_sml.gif and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/icon_success_sml.gif b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/icon_success_sml.gif deleted file mode 100644 index 52e85a430..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/icon_success_sml.gif and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/icon_warning_sml.gif b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/icon_warning_sml.gif deleted file mode 100644 index 873bbb52c..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/icon_warning_sml.gif and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/logos/build-by-maven-black.png b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/logos/build-by-maven-black.png deleted file mode 100644 index 919fd0f66..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/logos/build-by-maven-black.png and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/logos/build-by-maven-white.png b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/logos/build-by-maven-white.png deleted file mode 100644 index 7d44c9c2e..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/logos/build-by-maven-white.png and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/logos/maven-feather.png b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/logos/maven-feather.png deleted file mode 100644 index b5ada836e..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/logos/maven-feather.png and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/newwindow.png b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/newwindow.png deleted file mode 100644 index 6287f72bd..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/dependencies/images/newwindow.png and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/descriptor.json b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/descriptor.json deleted file mode 100644 index fe8e5d8a0..000000000 --- a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/descriptor.json +++ /dev/null @@ -1,686 +0,0 @@ -{ - "discoveryLink": "./apis/fusiontables/v1/rest", - "kind": "discovery#directoryItem", - "description": "API for working with Fusion Tables data.", - "title": "Fusion Tables API", - "discoveryRestUrl": "https://www.googleapis.com/discovery/v1/apis/fusiontables/v1/rest", - "preferred": true, - "version": "v1", - "icons": { - "x32": "http://www.google.com/images/icons/product/search-32.gif", - "x16": "http://www.google.com/images/icons/product/search-16.gif" - }, - "documentationLink": "https://developers.google.com/fusiontables", - "id": "fusiontables:v1", - "name": "fusiontables", - "files": [ - { - "downloadUrl": "/downloads/fusiontables/v1/16/java/1.12.0-beta/google-api-services-fusiontables-v1-rev16-1.12.0-beta.jar", - "path": "google-api-services-fusiontables-v1-rev16-1.12.0-beta.jar", - "type": "binary", - "timestamp": "2013-01-18 00:53" - }, - { - "downloadUrl": "/downloads/fusiontables/v1/16/java/1.12.0-beta/google-api-services-fusiontables-v1-rev16-1.12.0-beta-javadoc.jar", - "path": "google-api-services-fusiontables-v1-rev16-1.12.0-beta-javadoc.jar", - "type": "documentation", - "timestamp": "2013-01-18 00:53" - }, - { - "downloadUrl": "/downloads/fusiontables/v1/16/java/1.12.0-beta/google-api-services-fusiontables-v1-rev16-1.12.0-beta-sources.jar", - "path": "google-api-services-fusiontables-v1-rev16-1.12.0-beta-sources.jar", - "type": "source", - "timestamp": "2013-01-18 00:53" - }, - { - "path": "google-api-services-fusiontables-v1-rev16-1.12.0-beta.jar.properties", - "type": "android.properties" - } - ], - "revision": 16, - "language": "java", - "language_version": "1.12.0-beta", - "dependencies": [ - { - "files": [ - { - "downloadUrl": "http://google-api-java-client.googlecode.com/files/google-api-java-client-1.12.0-beta.zip", - "type": "bundle" - } - ], - "version": "1.12.0-beta", - "name": "Google API Java Client Bundle", - "environments": [ - "manual" - ] - }, - { - "files": [ - { - "path": "libs/google-api-client-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-api-client-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - }, - { - "path": "libs/google-api-client-1.12.0-beta.jar.properties", - "type": "android-properties" - } - ], - "version": "1.12.0-beta", - "name": "Google APIs Client Library", - "environments": [ - "*" - ] - }, - { - "files": [ - { - "path": "libs/google-api-client-android-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-api-client-android-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - }, - { - "path": "libs/google-api-client-android-1.12.0-beta.jar.properties", - "type": "android-properties" - } - ], - "version": "1.12.0-beta", - "name": "Android platform extensions to the Google APIs Client Library", - "environments": [ - "android" - ] - }, - { - "files": [ - { - "path": "libs/google-api-client-appengine-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-api-client-appengine-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "1.12.0-beta", - "name": "Google App Engine extensions to the Google APIs Client Library", - "environments": [ - "appengine" - ] - }, - { - "files": [ - { - "path": "libs/google-api-client-java6-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-api-client-java6-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "1.12.0-beta", - "name": "Java 6 (and higher) extensions to the Google APIs Client Library", - "environments": [ - "generic" - ] - }, - { - "files": [ - { - "path": "libs/google-oauth-client-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-oauth-client-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - }, - { - "path": "libs/google-oauth-client-1.12.0-beta.jar.properties", - "type": "android-properties" - } - ], - "version": "1.12.0-beta", - "name": "Google OAuth Client Library", - "environments": [ - "*" - ] - }, - { - "files": [ - { - "path": "libs/google-oauth-client-appengine-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-oauth-client-appengine-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "1.12.0-beta", - "name": "Google App Engine extensions to the Google OAuth Client Library", - "environments": [ - "appengine" - ] - }, - { - "files": [ - { - "path": "libs/google-oauth-client-java6-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-oauth-client-java6-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "1.12.0-beta", - "name": "Java 6 (and higher) extensions to the Google OAuth Client Library", - "environments": [ - "generic" - ] - }, - { - "files": [ - { - "path": "libs/google-oauth-client-jetty-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-oauth-client-jetty-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "1.12.0-beta", - "name": "Jetty extensions to the Google OAuth Client Library", - "environments": [ - "generic" - ] - }, - { - "files": [ - { - "path": "libs/google-oauth-client-servlet-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-oauth-client-servlet-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "1.12.0-beta", - "name": "Servlet and JDO extensions to the Google OAuth Client Library", - "environments": [ - "appengine", - "servlet" - ] - }, - { - "files": [ - { - "path": "libs/google-http-client-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-http-client-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - }, - { - "path": "libs/google-http-client-1.12.0-beta.jar.properties", - "type": "android-properties" - } - ], - "version": "1.12.0-beta", - "name": "Google HTTP Client Library", - "environments": [ - "*" - ] - }, - { - "files": [ - { - "path": "libs/google-http-client-android-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-http-client-android-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - }, - { - "path": "libs/google-http-client-android-1.12.0-beta.jar.properties", - "type": "android-properties" - } - ], - "version": "1.12.0-beta", - "name": "Android platform extensions to the Google HTTP Client Library", - "environments": [ - "android" - ] - }, - { - "files": [ - { - "path": "libs/google-http-client-appengine-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-http-client-appengine-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "1.12.0-beta", - "name": "Google App Engine extensions to the Google HTTP Client Library", - "environments": [ - "appengine" - ] - }, - { - "files": [ - { - "path": "libs/google-http-client-gson-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-http-client-gson-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - }, - { - "path": "libs/google-http-client-gson-1.12.0-beta.jar.properties", - "type": "android-properties" - } - ], - "version": "1.12.0-beta", - "name": "GSON extensions to the Google HTTP Client Library", - "environments": [ - "*" - ] - }, - { - "files": [ - { - "path": "libs/google-http-client-jackson-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-http-client-jackson-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - }, - { - "path": "libs/google-http-client-jackson-1.12.0-beta.jar.properties", - "type": "android-properties" - } - ], - "version": "1.12.0-beta", - "name": "Jackson extensions to the Google HTTP Client Library", - "environments": [ - "*" - ] - }, - { - "files": [ - { - "path": "libs/google-http-client-jackson2-1.12.0-beta.jar", - "type": "binary" - }, - { - "path": "libs-sources/google-http-client-jackson2-1.12.0-beta-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - }, - { - "path": "libs/google-http-client-jackson2-1.12.0-beta.jar.properties", - "type": "android-properties" - } - ], - "version": "1.12.0-beta", - "name": "Jackson 2 extensions to the Google HTTP Client Library", - "environments": [ - "*" - ] - }, - { - "files": [ - { - "path": "libs/commons-logging-1.1.1.jar", - "type": "binary" - }, - { - "path": "libs-sources/commons-logging-1.1.1-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "1.1.1", - "name": "Commons Logging", - "environments": [ - "servlet", - "generic" - ] - }, - { - "files": [ - { - "path": "libs/guava-jdk5-13.0.jar", - "type": "binary" - }, - { - "path": "libs-sources/guava-jdk5-13.0-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - }, - { - "path": "libs/guava-jdk5-13.0.jar.properties", - "type": "android-properties" - } - ], - "version": "jdk5-13.0", - "name": "Google Guava", - "environments": [ - "*" - ] - }, - { - "files": [ - { - "path": "libs/gson-2.1.jar", - "type": "binary" - }, - { - "path": "libs-sources/gson-2.1-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - }, - { - "path": "libs/gson-2.1.jar.properties", - "type": "android-properties" - } - ], - "version": "2.1", - "name": "GSON", - "environments": [ - "*" - ] - }, - { - "files": [ - { - "path": "libs/httpclient-4.0.3.jar", - "type": "binary" - }, - { - "path": "libs-sources/httpclient-4.0.3-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "4.0.3", - "name": "HTTP Client", - "environments": [ - "servlet", - "generic" - ] - }, - { - "files": [ - { - "path": "libs/httpcore-4.0.1.jar", - "type": "binary" - }, - { - "path": "libs-sources/httpcore-4.0.1-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "4.0.1", - "name": "HTTP Core", - "environments": [ - "servlet", - "generic" - ] - }, - { - "files": [ - { - "path": "libs/jackson-core-asl-1.9.9.jar", - "type": "binary" - }, - { - "path": "libs-sources/jackson-core-asl-1.9.9-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - }, - { - "path": "libs/jackson-core-asl-1.9.9.jar.properties", - "type": "android-properties" - } - ], - "version": "1.9.9", - "name": "Jackson Core ASL", - "environments": [ - "*" - ] - }, - { - "files": [ - { - "path": "libs/jackson-core-2.0.5.jar", - "type": "binary" - }, - { - "path": "libs-sources/jackson-core-2.0.5-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - }, - { - "path": "libs/jackson-core-2.0.5.jar.properties", - "type": "android-properties" - } - ], - "version": "2.0.5", - "name": "Jackson2 Core", - "environments": [ - "*" - ] - }, - { - "files": [ - { - "path": "libs/jdo2-api-2.3-eb.jar", - "type": "binary" - }, - { - "path": "libs-sources/jdo2-api-2.3-eb-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "2.3-eb", - "name": "JDO2 API", - "environments": [ - "appengine", - "servlet" - ] - }, - { - "files": [ - { - "path": "libs/jetty-6.1.26.jar", - "type": "binary" - }, - { - "path": "libs-sources/jetty-6.1.26-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "6.1.26", - "name": "Jetty", - "environments": [ - "generic" - ] - }, - { - "files": [ - { - "path": "libs/jetty-util-6.1.26.jar", - "type": "binary" - }, - { - "path": "libs-sources/jetty-util-6.1.26-sources.jar", - "type": "source" - }, - { - "path": "dependencies/APACHE-LICENSE.txt", - "type": "license" - } - ], - "version": "6.1.26", - "name": "Jetty Util", - "environments": [ - "generic" - ] - }, - { - "files": [ - { - "path": "libs/transaction-api-1.1.jar", - "type": "binary" - }, - { - "path": "libs-sources/transaction-api-1.1-sources.jar", - "type": "source" - }, - { - "path": "dependencies/CDDL-LICENSE.txt", - "type": "license" - } - ], - "version": "1.1", - "name": "Transaction API", - "environments": [ - "appengine", - "servlet" - ] - }, - { - "files": [ - { - "path": "libs/xpp3-1.1.4c.jar", - "type": "binary" - }, - { - "path": "libs-sources/xpp3-1.1.4c-sources.jar", - "type": "source" - }, - { - "path": "dependencies/xpp3_LICENSE.txt", - "type": "license" - } - ], - "version": "1.1.4c", - "name": "XPP3", - "environments": [ - "appengine", - "servlet", - "generic" - ] - } - ], - "proguard-config": "proguard-google-api-client.txt", - "icon_files": { - "x32": "icons/search-32.gif", - "x16": "icons/search-16.gif" - } -} \ No newline at end of file diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/google-api-services-fusiontables-v1-rev16-1.12.0-beta-javadoc.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/google-api-services-fusiontables-v1-rev16-1.12.0-beta-javadoc.jar deleted file mode 100644 index a9e65f5a6..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/google-api-services-fusiontables-v1-rev16-1.12.0-beta-javadoc.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/google-api-services-fusiontables-v1-rev16-1.12.0-beta-sources.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/google-api-services-fusiontables-v1-rev16-1.12.0-beta-sources.jar deleted file mode 100644 index 4ac7d895f..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/google-api-services-fusiontables-v1-rev16-1.12.0-beta-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/google-api-services-fusiontables-v1-rev16-1.12.0-beta.jar.properties b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/google-api-services-fusiontables-v1-rev16-1.12.0-beta.jar.properties deleted file mode 100644 index b15f6df09..000000000 --- a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/google-api-services-fusiontables-v1-rev16-1.12.0-beta.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/google-api-services-fusiontables-v1-rev16-1.12.0-beta-sources.jar diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/icons/search-16.gif b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/icons/search-16.gif deleted file mode 100644 index 8de3eea2e..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/icons/search-16.gif and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/icons/search-32.gif b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/icons/search-32.gif deleted file mode 100644 index 8aa96f148..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/icons/search-32.gif and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/google-api-client-1.12.0-beta-sources.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/google-api-client-1.12.0-beta-sources.jar deleted file mode 100644 index 6c8d980d6..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/google-api-client-1.12.0-beta-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/google-api-client-android-1.12.0-beta-sources.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/google-api-client-android-1.12.0-beta-sources.jar deleted file mode 100644 index 16934a51d..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/google-api-client-android-1.12.0-beta-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/google-http-client-1.12.0-beta-sources.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/google-http-client-1.12.0-beta-sources.jar deleted file mode 100644 index 4507e0a21..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/google-http-client-1.12.0-beta-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/google-http-client-android-1.12.0-beta-sources.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/google-http-client-android-1.12.0-beta-sources.jar deleted file mode 100644 index 7ce36e594..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/google-http-client-android-1.12.0-beta-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/google-http-client-gson-1.12.0-beta-sources.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/google-http-client-gson-1.12.0-beta-sources.jar deleted file mode 100644 index 168df18ae..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/google-http-client-gson-1.12.0-beta-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/google-http-client-jackson-1.12.0-beta-sources.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/google-http-client-jackson-1.12.0-beta-sources.jar deleted file mode 100644 index 377c1dea9..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/google-http-client-jackson-1.12.0-beta-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/google-http-client-jackson2-1.12.0-beta-sources.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/google-http-client-jackson2-1.12.0-beta-sources.jar deleted file mode 100644 index 442a357e2..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/google-http-client-jackson2-1.12.0-beta-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/google-oauth-client-1.12.0-beta-sources.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/google-oauth-client-1.12.0-beta-sources.jar deleted file mode 100644 index bd82679dd..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/google-oauth-client-1.12.0-beta-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/gson-2.1-sources.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/gson-2.1-sources.jar deleted file mode 100644 index 09396a02e..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/gson-2.1-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/guava-jdk5-13.0-sources.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/guava-jdk5-13.0-sources.jar deleted file mode 100644 index c5ee71697..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/guava-jdk5-13.0-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/jackson-core-2.0.5-sources.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/jackson-core-2.0.5-sources.jar deleted file mode 100644 index af5dc6e4d..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/jackson-core-2.0.5-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/jackson-core-asl-1.9.9-sources.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/jackson-core-asl-1.9.9-sources.jar deleted file mode 100644 index af5dc6e4d..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs-sources/jackson-core-asl-1.9.9-sources.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-api-client-1.12.0-beta.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-api-client-1.12.0-beta.jar deleted file mode 100644 index c85862626..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-api-client-1.12.0-beta.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-api-client-1.12.0-beta.jar.properties b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-api-client-1.12.0-beta.jar.properties deleted file mode 100644 index 39c242523..000000000 --- a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-api-client-1.12.0-beta.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/google-api-client-1.12.0-beta-sources.jar diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-api-client-android-1.12.0-beta.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-api-client-android-1.12.0-beta.jar deleted file mode 100644 index cb7cfe8bc..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-api-client-android-1.12.0-beta.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-api-client-android-1.12.0-beta.jar.properties b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-api-client-android-1.12.0-beta.jar.properties deleted file mode 100644 index 31042993d..000000000 --- a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-api-client-android-1.12.0-beta.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/google-api-client-android-1.12.0-beta-sources.jar diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-1.12.0-beta.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-1.12.0-beta.jar deleted file mode 100644 index 6ff05049f..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-1.12.0-beta.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-1.12.0-beta.jar.properties b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-1.12.0-beta.jar.properties deleted file mode 100644 index 22d7a272a..000000000 --- a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-1.12.0-beta.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/google-http-client-1.12.0-beta-sources.jar diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-android-1.12.0-beta.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-android-1.12.0-beta.jar deleted file mode 100644 index 1ed253346..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-android-1.12.0-beta.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-android-1.12.0-beta.jar.properties b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-android-1.12.0-beta.jar.properties deleted file mode 100644 index b804cc361..000000000 --- a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-android-1.12.0-beta.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/google-http-client-android-1.12.0-beta-sources.jar diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-gson-1.12.0-beta.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-gson-1.12.0-beta.jar deleted file mode 100644 index 7a2e064e7..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-gson-1.12.0-beta.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-gson-1.12.0-beta.jar.properties b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-gson-1.12.0-beta.jar.properties deleted file mode 100644 index 3cdc720ab..000000000 --- a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-gson-1.12.0-beta.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/google-http-client-gson-1.12.0-beta-sources.jar diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-jackson-1.12.0-beta.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-jackson-1.12.0-beta.jar deleted file mode 100644 index 52c2209d9..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-jackson-1.12.0-beta.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-jackson-1.12.0-beta.jar.properties b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-jackson-1.12.0-beta.jar.properties deleted file mode 100644 index 0f06bb8c3..000000000 --- a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-jackson-1.12.0-beta.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/google-http-client-jackson-1.12.0-beta-sources.jar diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-jackson2-1.12.0-beta.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-jackson2-1.12.0-beta.jar deleted file mode 100644 index 9415c7b23..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-jackson2-1.12.0-beta.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-jackson2-1.12.0-beta.jar.properties b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-jackson2-1.12.0-beta.jar.properties deleted file mode 100644 index c70f7d815..000000000 --- a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-http-client-jackson2-1.12.0-beta.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/google-http-client-jackson2-1.12.0-beta-sources.jar diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-oauth-client-1.12.0-beta.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-oauth-client-1.12.0-beta.jar deleted file mode 100644 index dad2abe4f..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-oauth-client-1.12.0-beta.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-oauth-client-1.12.0-beta.jar.properties b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-oauth-client-1.12.0-beta.jar.properties deleted file mode 100644 index d8ef90d84..000000000 --- a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/google-oauth-client-1.12.0-beta.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/google-oauth-client-1.12.0-beta-sources.jar diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/gson-2.1.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/gson-2.1.jar deleted file mode 100644 index 83c5c994b..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/gson-2.1.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/gson-2.1.jar.properties b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/gson-2.1.jar.properties deleted file mode 100644 index cfa21515f..000000000 --- a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/gson-2.1.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/gson-2.1-sources.jar diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/guava-jdk5-13.0.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/guava-jdk5-13.0.jar deleted file mode 100644 index 85881e5de..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/guava-jdk5-13.0.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/guava-jdk5-13.0.jar.properties b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/guava-jdk5-13.0.jar.properties deleted file mode 100644 index 415299133..000000000 --- a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/guava-jdk5-13.0.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/guava-jdk5-13.0-sources.jar diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/jackson-core-2.0.5.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/jackson-core-2.0.5.jar deleted file mode 100644 index 51d1fdeb4..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/jackson-core-2.0.5.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/jackson-core-2.0.5.jar.properties b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/jackson-core-2.0.5.jar.properties deleted file mode 100644 index 8ceae8ed1..000000000 --- a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/jackson-core-2.0.5.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/jackson-core-2.0.5-sources.jar diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/jackson-core-asl-1.9.9.jar b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/jackson-core-asl-1.9.9.jar deleted file mode 100644 index d75843d1c..000000000 Binary files a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/jackson-core-asl-1.9.9.jar and /dev/null differ diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/jackson-core-asl-1.9.9.jar.properties b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/jackson-core-asl-1.9.9.jar.properties deleted file mode 100644 index 53aca9d0d..000000000 --- a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/libs/jackson-core-asl-1.9.9.jar.properties +++ /dev/null @@ -1 +0,0 @@ -src=../libs-sources/jackson-core-asl-1.9.9-sources.jar diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/proguard-google-api-client.txt b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/proguard-google-api-client.txt deleted file mode 100644 index ca7616a58..000000000 --- a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/proguard-google-api-client.txt +++ /dev/null @@ -1,25 +0,0 @@ -# ProGuard Configuration file -# -# See http://proguard.sourceforge.net/index.html#manual/usage.html - -# Needed to keep generic types and @Key annotations accessed via reflection - --keepattributes Signature,RuntimeVisibleAnnotations,AnnotationDefault - --keepclassmembers class * { - @com.google.api.client.util.Key ; -} - -# Needed by Guava -# See https://groups.google.com/forum/#!topic/guava-discuss/YCZzeCiIVoI - --dontwarn sun.misc.Unsafe --dontwarn com.google.common.collect.MinMaxPriorityQueue - -# Needed by google-http-client-android when linking against an older platform version - --dontwarn com.google.api.client.extensions.android.** - -# Needed by google-api-client-android when linking against an older platform version - --dontwarn com.google.api.client.googleapis.extensions.android.** diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/readme.html b/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/readme.html deleted file mode 100644 index 6c9d8092e..000000000 --- a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/readme.html +++ /dev/null @@ -1,158 +0,0 @@ - -Fusion Tables API v1 Client Library for Java - -

Fusion Tables API v1 Client Library for Java

- -

Overview

-

High-level details about this library can be found at -http://code.google.com/p/google-api-java-client -

- -

License

-The license can be found here.
- -

Generated service-specific Library

-The generated service-specific library can be found in the top level directory -of the zip file: -google-api-services-fusiontables-v1-rev16-1.12.0-beta.jar - -

Maven Usage

-Maven users can specify the service-specific generated library in their -project's plugin configuration: -
-<repositories>
-  <repository>
-    <id>googleapis</id>
-    <url>http://mavenrepo.google-api-java-client.googlecode.com/hg/</url>
-  </repository>
-</repositories>
-
-<dependency>
-  <groupId>com.google.apis</groupId>
-  <artifactId>google-api-services-fusiontables</artifactId>
-  <version>v1-rev16-1.12.0-beta</version>
-</dependency>
-
- - -

Eclipse

-A .classpath file snippet that can be included in your project's .classpath has been provided here. -Please only use the classpathentry's you actually need (see below for details). - -

ProGuard

-A ProGuard configuration file proguard-google-api-client.txt -is included for common settings for using the library. On Android projects, you may want to add a reference to -proguard-google-api-client.txt in the project.properties file under the -proguard.config property. - -

Dependencies

-

-Dependent jars for -google-api-services-fusiontables-v1-rev16-1.12.0-beta.jar -can be found in the libs folder and the corresponding source -jars can be found in the libs-sources folder. -

-The dependency structure and licenses can be found in -dependencies.html. -

- -

Dependencies for all Platforms

-The following are the jars from the libs folder required for -applications on all platforms: -
    -
  • google-api-client-1.12.0-beta.jar
  • -
  • google-oauth-client-1.12.0-beta.jar
  • -
  • google-http-client-1.12.0-beta.jar
  • -
  • guava-jdk5-13.0.jar
  • -
  • jsr305-1.3.9.jar
  • -
  • google-http-client-gson-1.12.0-beta.jar (when using GSON) -
      -
    • gson-2.1.jar
    • -
    -
  • -
  • google-http-client-jackson-1.12.0-beta.jar (when using Jackson) -
      -
    • jackson-core-asl-1.9.9.jar
    • -
    -
  • -
  • google-http-client-jackson2-1.12.0-beta.jar (when using Jackson 2) -
      -
    • jackson-core-$2.0.5.jar
    • -
    -
  • -
- -

Android Dependencies

-The following are the jars from the libs folder required for -android applications or a newer compatible version of each dependency: -
    -
  • google-api-client-android-1.12.0-beta.jar (for SDK >= 2.1)
  • -
  • google-http-client-android-1.12.0-beta.jar (for SDK >= 2.1)
  • -
  • [deprecated] google-api-client-android2-1.12.0-beta.jar (for SDK >= 2.1)
  • -
  • [deprecated] google-http-client-android2-1.12.0-beta.jar (for SDK >= 2.1)
  • -
  • [deprecated] google-http-client-android3-1.12.0-beta.jar (for SDK >= 3.0)
  • -
-libs folder also contains properties files that specify the location of source -jars for Android projects in Eclipse.
-Please see the -Android wiki -for the Android Developer's Guide. - -

Google App Engine Dependencies

-The following are the jars from the libs folder required for -Google App Engine applications or a newer compatible version of each dependency: -
    -
  • google-api-client-appengine-1.12.0-beta.jar
  • -
  • google-oauth-client-appengine-1.12.0-beta.jar
  • -
  • google-oauth-client-servlet-1.12.0-beta.jar
  • -
  • google-http-client-appengine-1.12.0-beta.jar
  • -
  • jdo2-api-2.3-eb.jar
  • -
  • transaction-api-1.1.jar
  • -
  • xpp3-1.1.4c.jar
  • -
-Please see the -GoogleAppEngine wiki -for the Google App Engine Developer's Guide. - -

Servlet Dependencies

-The following are the jars from the libs folder required for -Servlet applications or a newer compatible version of each dependency: -
    -
  • google-oauth-client-1.12.0-beta.jar
  • -
  • google-oauth-client-servlet-1.12.0-beta.jar
  • -
  • commons-logging-1.1.1.jar
  • -
  • httpclient-4.0.3.jar
  • -
  • httpcore-4.0.1.jar
  • -
  • jdo2-api-2.3-eb.jar
  • -
  • transaction-api-1.1.jar
  • -
  • xpp3-1.1.4c.jar
  • -
- -

General Purpose Java 5 Environment Dependencies

-The following are the jars from the libs folder required for -general purpose Java 5 applications (or a newer compatible version of each dependency): -
    -
  • google-api-client-java6-1.12.0-beta.jar
  • -
  • google-oauth-client-java6-1.12.0-beta.jar
  • -
      -
    • google-oauth-client-jetty-${project.oauth.version}.jar (for Jetty 6) -
        -
      • jetty-${jettyVersion}
      • -
      • jetty-util-${jettyUtilVersion}
      • -
      -
    • -
    -
  • commons-logging-1.1.1.jar
  • -
  • httpclient-4.0.3.jar
  • -
  • httpcore-4.0.1.jar
  • -
  • xpp3-1.1.4c.jar
  • -
- - - - diff --git a/MyTracks/.google_apis/gdata-spreadsheet-2.1/gdata-spreadsheet-3.0/descriptor.json b/MyTracks/.google_apis/gdata-spreadsheet-2.1/gdata-spreadsheet-3.0/descriptor.json deleted file mode 100644 index a98797cc4..000000000 --- a/MyTracks/.google_apis/gdata-spreadsheet-2.1/gdata-spreadsheet-3.0/descriptor.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "kind": "discovery#directoryItem", - "id": "gdata-spreadsheet:3.0", - "name": "gdata-spreadsheet", - "version": "2.1", - "title": "Spreadsheets", - "publisher": "Google", - "description": "With Google Spreadsheets, you can easily create, share, and edit spreadsheets online. The Google Spreadsheets APIs provide a framework for developers to programatically interface with and extend Google Spreadsheets.", - "downloadLink": "static/gdata-spreadsheet-3.0.zip", - "icons": { - "x16": "icons/gdata-spreadsheet-16.png" - }, - "tosLink": "http://code.google.com/terms.html", - "releaseDate": "2009-11-05", - "documentationLink": "http://code.google.com/apis/spreadsheets/data/3.0/developers_guide.html", - "preferred": true -} diff --git a/MyTracks/.google_apis/gdata-spreadsheet-2.1/gdata-spreadsheet-3.0/gdata-spreadsheet-3.0-javadoc.jar b/MyTracks/.google_apis/gdata-spreadsheet-2.1/gdata-spreadsheet-3.0/gdata-spreadsheet-3.0-javadoc.jar deleted file mode 100644 index d1368a9df..000000000 Binary files a/MyTracks/.google_apis/gdata-spreadsheet-2.1/gdata-spreadsheet-3.0/gdata-spreadsheet-3.0-javadoc.jar and /dev/null differ diff --git a/MyTracks/.google_apis/gdata-spreadsheet-2.1/gdata-spreadsheet-3.0/gdata-spreadsheet-3.0-src.jar b/MyTracks/.google_apis/gdata-spreadsheet-2.1/gdata-spreadsheet-3.0/gdata-spreadsheet-3.0-src.jar deleted file mode 100644 index 2476663c8..000000000 Binary files a/MyTracks/.google_apis/gdata-spreadsheet-2.1/gdata-spreadsheet-3.0/gdata-spreadsheet-3.0-src.jar and /dev/null differ diff --git a/MyTracks/.google_apis/gdata-spreadsheet-2.1/gdata-spreadsheet-3.0/icons/gdata-spreadsheet-16.png b/MyTracks/.google_apis/gdata-spreadsheet-2.1/gdata-spreadsheet-3.0/icons/gdata-spreadsheet-16.png deleted file mode 100644 index 6c6fbbce5..000000000 Binary files a/MyTracks/.google_apis/gdata-spreadsheet-2.1/gdata-spreadsheet-3.0/icons/gdata-spreadsheet-16.png and /dev/null differ diff --git a/MyTracks/.idea/.name b/MyTracks/.idea/.name new file mode 100644 index 000000000..1848c1927 --- /dev/null +++ b/MyTracks/.idea/.name @@ -0,0 +1 @@ +MyTracks \ No newline at end of file diff --git a/MyTracks/.idea/compiler.xml b/MyTracks/.idea/compiler.xml new file mode 100644 index 000000000..96cc43efa --- /dev/null +++ b/MyTracks/.idea/compiler.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MyTracks/.idea/copyright/profiles_settings.xml b/MyTracks/.idea/copyright/profiles_settings.xml new file mode 100644 index 000000000..c7d1c5a83 --- /dev/null +++ b/MyTracks/.idea/copyright/profiles_settings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/MyTracks/.idea/encodings.xml b/MyTracks/.idea/encodings.xml new file mode 100644 index 000000000..97626ba45 --- /dev/null +++ b/MyTracks/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/MyTracks/.idea/misc.xml b/MyTracks/.idea/misc.xml new file mode 100644 index 000000000..415b16671 --- /dev/null +++ b/MyTracks/.idea/misc.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MyTracks/.idea/modules.xml b/MyTracks/.idea/modules.xml new file mode 100644 index 000000000..aae932955 --- /dev/null +++ b/MyTracks/.idea/modules.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/MyTracks/.idea/runConfigurations.xml b/MyTracks/.idea/runConfigurations.xml new file mode 100644 index 000000000..7f68460d8 --- /dev/null +++ b/MyTracks/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/MyTracks/.idea/vcs.xml b/MyTracks/.idea/vcs.xml new file mode 100644 index 000000000..6564d52db --- /dev/null +++ b/MyTracks/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/MyTracks/.project b/MyTracks/.project deleted file mode 100644 index 81b2d0da6..000000000 --- a/MyTracks/.project +++ /dev/null @@ -1,34 +0,0 @@ - - - MyTracks - - - MyTracks - - - - com.android.ide.eclipse.adt.ResourceManagerBuilder - - - - - com.android.ide.eclipse.adt.PreCompilerBuilder - - - - - org.eclipse.jdt.core.javabuilder - - - - - com.android.ide.eclipse.adt.ApkBuilder - - - - - - com.android.ide.eclipse.adt.AndroidNature - org.eclipse.jdt.core.javanature - - diff --git a/MyTracks/.settings/com.google.gdt.eclipse.managedapis.prefs b/MyTracks/.settings/com.google.gdt.eclipse.managedapis.prefs deleted file mode 100644 index bca0ae043..000000000 --- a/MyTracks/.settings/com.google.gdt.eclipse.managedapis.prefs +++ /dev/null @@ -1,2 +0,0 @@ -COPY_CLASSPATH_ENTRIES_TARGET_PATH=libs -eclipse.preferences.version=1 diff --git a/MyTracks/.settings/org.eclipse.jdt.core.prefs b/MyTracks/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index f7f54abd1..000000000 --- a/MyTracks/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,401 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -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.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_annotations_on_field=1585 -org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field.count_dependent=1585|-1|1585 -org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable=1585 -org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable.count_dependent=1585|-1|1585 -org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method=1585 -org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method.count_dependent=1585|-1|1585 -org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package=1585 -org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package.count_dependent=1585|-1|1585 -org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter=1040 -org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter.count_dependent=1040|-1|1040 -org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type=1585 -org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type.count_dependent=1585|-1|1585 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression.count_dependent=16|-1|16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation.count_dependent=16|-1|16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=48 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant.count_dependent=16|-1|16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call.count_dependent=16|-1|16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation.count_dependent=16|-1|16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression.count_dependent=16|-1|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_binary_expression.count_dependent=16|-1|16 -org.eclipse.jdt.core.formatter.alignment_for_cascading_method_invocation_with_arguments=16 -org.eclipse.jdt.core.formatter.alignment_for_cascading_method_invocation_with_arguments.count_dependent=16|-1|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_enum_constants.count_dependent=0|-1|0 -org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 -org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer.count_dependent=16|-1|16 -org.eclipse.jdt.core.formatter.alignment_for_field_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_for_statement=16 -org.eclipse.jdt.core.formatter.alignment_for_generic_type_arguments=16 -org.eclipse.jdt.core.formatter.alignment_for_generic_type_arguments.count_dependent=16|-1|16 -org.eclipse.jdt.core.formatter.alignment_for_local_variable_declaration=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_multiple_fields.count_dependent=16|-1|16 -org.eclipse.jdt.core.formatter.alignment_for_new_anonymous_class=0 -org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration.count_dependent=16|-1|16 -org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration.count_dependent=16|-1|16 -org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 -org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 -org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation.count_dependent=16|-1|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_enum_declaration.count_dependent=16|-1|16 -org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration.count_dependent=16|-1|16 -org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration.count_dependent=16|-1|16 -org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration.count_dependent=16|-1|16 -org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=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.comment_new_line_at_start_of_html_paragraph=true -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.force_if_else_statement_brace=false -org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false -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_comment_prefix=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_try=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_semicolon_in_try_resources=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_try=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_try=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_semicolon_in_try_resources=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=false -org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false -org.eclipse.jdt.core.formatter.lineSplit=100 -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.sort_local_variable_annotations=false -org.eclipse.jdt.core.formatter.sort_member_annotations=false -org.eclipse.jdt.core.formatter.sort_package_annotations=false -org.eclipse.jdt.core.formatter.sort_parameter_annotations=false -org.eclipse.jdt.core.formatter.sort_type_annotations=false -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_before_or_operator_multicatch=true -org.eclipse.jdt.core.formatter.wrap_comment_inline_tags=false -org.eclipse.jdt.core.formatter.wrap_non_simple_local_variable_annotation=true -org.eclipse.jdt.core.formatter.wrap_non_simple_member_annotation=true -org.eclipse.jdt.core.formatter.wrap_non_simple_package_annotation=true -org.eclipse.jdt.core.formatter.wrap_non_simple_parameter_annotation=false -org.eclipse.jdt.core.formatter.wrap_non_simple_type_annotation=true -org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true -org.eclipse.jdt.core.formatter.wrap_prefer_two_fragments=false diff --git a/MyTracks/.settings/org.eclipse.jdt.ui.prefs b/MyTracks/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index ef8d656cf..000000000 --- a/MyTracks/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,61 +0,0 @@ -#Tue Jul 17 10:22:06 PDT 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -formatter_profile=_My Tracks -formatter_settings_version=13 -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 diff --git a/MyTracks/MyTracks.iml b/MyTracks/MyTracks.iml new file mode 100644 index 000000000..b70b83a6a --- /dev/null +++ b/MyTracks/MyTracks.iml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MyTracks/MyTracks.launch b/MyTracks/MyTracks.launch deleted file mode 100644 index 5d64dfff5..000000000 --- a/MyTracks/MyTracks.launch +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/MyTracks/build.gradle b/MyTracks/build.gradle new file mode 100644 index 000000000..37b7f3ee9 --- /dev/null +++ b/MyTracks/build.gradle @@ -0,0 +1,15 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.5.0' + } +} + +allprojects { + repositories { + jcenter() + } +} diff --git a/MyTracks/googleplayservices_lib/build.gradle b/MyTracks/googleplayservices_lib/build.gradle new file mode 100644 index 000000000..f7c2ea1a9 --- /dev/null +++ b/MyTracks/googleplayservices_lib/build.gradle @@ -0,0 +1,22 @@ +apply plugin: 'com.android.library' + +android { + compileSdkVersion 8 + buildToolsVersion "23.0.2" + + defaultConfig { + minSdkVersion 8 + targetSdkVersion 8 + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' + } + } +} + +dependencies { + compile files('libs/google-play-services.jar') +} diff --git a/MyTracks/googleplayservices_lib/googleplayservices_lib.iml b/MyTracks/googleplayservices_lib/googleplayservices_lib.iml new file mode 100644 index 000000000..aa2acfab7 --- /dev/null +++ b/MyTracks/googleplayservices_lib/googleplayservices_lib.iml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MyTracks/googleplayservices_lib/libs/google-play-services.jar b/MyTracks/googleplayservices_lib/libs/google-play-services.jar new file mode 100644 index 000000000..7839fe301 Binary files /dev/null and b/MyTracks/googleplayservices_lib/libs/google-play-services.jar differ diff --git a/MyTracks/googleplayservices_lib/src/main/AndroidManifest.xml b/MyTracks/googleplayservices_lib/src/main/AndroidManifest.xml new file mode 100644 index 000000000..2e6aa673e --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/MyTracks/googleplayservices_lib/src/main/java/android/UnusedStub.java b/MyTracks/googleplayservices_lib/src/main/java/android/UnusedStub.java new file mode 100644 index 000000000..d546b0ba9 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/java/android/UnusedStub.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android; + +// Stub java file to make inclusion into some IDE's work. +public final class UnusedStub { + private UnusedStub() { } +} diff --git a/MyTracks/googleplayservices_lib/src/main/res/color/common_signin_btn_text_dark.xml b/MyTracks/googleplayservices_lib/src/main/res/color/common_signin_btn_text_dark.xml new file mode 100644 index 000000000..a615ba274 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/color/common_signin_btn_text_dark.xml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/MyTracks/googleplayservices_lib/src/main/res/color/common_signin_btn_text_light.xml b/MyTracks/googleplayservices_lib/src/main/res/color/common_signin_btn_text_light.xml new file mode 100644 index 000000000..662066899 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/color/common_signin_btn_text_light.xml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_disabled_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_disabled_dark.9.png new file mode 100644 index 000000000..0f9e7917e Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_disabled_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_dark.9.png new file mode 100644 index 000000000..570e43225 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_light.9.png new file mode 100644 index 000000000..570e43225 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_disabled_focus_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_disabled_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_disabled_light.9.png new file mode 100644 index 000000000..0f9e7917e Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_disabled_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_focus_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_focus_dark.9.png new file mode 100644 index 000000000..f507b9f7d Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_focus_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_focus_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_focus_light.9.png new file mode 100644 index 000000000..d5625e5fc Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_focus_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_normal_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_normal_dark.9.png new file mode 100644 index 000000000..aea3c0d16 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_normal_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_normal_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_normal_light.9.png new file mode 100644 index 000000000..849e89f3a Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_normal_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_pressed_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_pressed_dark.9.png new file mode 100644 index 000000000..f4ab2f2a5 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_pressed_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_pressed_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_pressed_light.9.png new file mode 100644 index 000000000..9fe611d68 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_icon_pressed_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_disabled_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_disabled_dark.9.png new file mode 100644 index 000000000..bbcde39cf Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_disabled_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_disabled_focus_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_disabled_focus_dark.9.png new file mode 100644 index 000000000..53957b698 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_disabled_focus_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_disabled_focus_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_disabled_focus_light.9.png new file mode 100644 index 000000000..53957b698 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_disabled_focus_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_disabled_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_disabled_light.9.png new file mode 100644 index 000000000..bbcde39cf Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_disabled_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_focus_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_focus_dark.9.png new file mode 100644 index 000000000..000d12e8e Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_focus_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_focus_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_focus_light.9.png new file mode 100644 index 000000000..d9279405c Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_focus_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_normal_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_normal_dark.9.png new file mode 100644 index 000000000..67f263c80 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_normal_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_normal_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_normal_light.9.png new file mode 100644 index 000000000..96324c52f Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_normal_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_pressed_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_pressed_dark.9.png new file mode 100644 index 000000000..e4503128f Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_pressed_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_pressed_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_pressed_light.9.png new file mode 100644 index 000000000..fb94b7761 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-hdpi/common_signin_btn_text_pressed_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_disabled_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_disabled_dark.9.png new file mode 100644 index 000000000..dddcbebf1 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_disabled_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_dark.9.png new file mode 100644 index 000000000..58b75bd7d Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_light.9.png new file mode 100644 index 000000000..58b75bd7d Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_disabled_focus_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_disabled_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_disabled_light.9.png new file mode 100644 index 000000000..dddcbebf1 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_disabled_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_focus_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_focus_dark.9.png new file mode 100644 index 000000000..7d9ed7834 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_focus_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_focus_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_focus_light.9.png new file mode 100644 index 000000000..0ca401d37 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_focus_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_normal_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_normal_dark.9.png new file mode 100644 index 000000000..f2c3f5571 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_normal_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_normal_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_normal_light.9.png new file mode 100644 index 000000000..83b4fc9d6 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_normal_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_pressed_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_pressed_dark.9.png new file mode 100644 index 000000000..dd74fe876 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_pressed_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_pressed_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_pressed_light.9.png new file mode 100644 index 000000000..b7dc7aac7 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_icon_pressed_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_disabled_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_disabled_dark.9.png new file mode 100644 index 000000000..efdfe2e61 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_disabled_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_disabled_focus_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_disabled_focus_dark.9.png new file mode 100644 index 000000000..c7650b09e Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_disabled_focus_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_disabled_focus_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_disabled_focus_light.9.png new file mode 100644 index 000000000..c7650b09e Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_disabled_focus_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_disabled_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_disabled_light.9.png new file mode 100644 index 000000000..efdfe2e61 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_disabled_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_focus_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_focus_dark.9.png new file mode 100644 index 000000000..8c76283e5 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_focus_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_focus_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_focus_light.9.png new file mode 100644 index 000000000..abd26bcd4 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_focus_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_normal_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_normal_dark.9.png new file mode 100644 index 000000000..28181c338 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_normal_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_normal_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_normal_light.9.png new file mode 100644 index 000000000..34957fad5 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_normal_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_pressed_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_pressed_dark.9.png new file mode 100644 index 000000000..e923ee9c7 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_pressed_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_pressed_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_pressed_light.9.png new file mode 100644 index 000000000..34cf6bbad Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-mdpi/common_signin_btn_text_pressed_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_disabled_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_disabled_dark.9.png new file mode 100644 index 000000000..9044a118a Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_disabled_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_dark.9.png new file mode 100644 index 000000000..e94a49b0a Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_light.9.png new file mode 100644 index 000000000..e94a49b0a Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_disabled_focus_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_disabled_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_disabled_light.9.png new file mode 100644 index 000000000..9044a118a Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_disabled_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_focus_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_focus_dark.9.png new file mode 100644 index 000000000..bfe4f0463 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_focus_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_focus_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_focus_light.9.png new file mode 100644 index 000000000..876884fad Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_focus_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_normal_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_normal_dark.9.png new file mode 100644 index 000000000..b3e6dd5b4 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_normal_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_normal_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_normal_light.9.png new file mode 100644 index 000000000..5a888f28f Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_normal_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_pressed_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_pressed_dark.9.png new file mode 100644 index 000000000..d0f7b4cbf Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_pressed_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_pressed_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_pressed_light.9.png new file mode 100644 index 000000000..0db6b0645 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_icon_pressed_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_disabled_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_disabled_dark.9.png new file mode 100644 index 000000000..d182b5e2c Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_disabled_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_dark.9.png new file mode 100644 index 000000000..47e2aeaf3 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_light.9.png new file mode 100644 index 000000000..47e2aeaf3 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_disabled_focus_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_disabled_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_disabled_light.9.png new file mode 100644 index 000000000..d182b5e2c Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_disabled_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_focus_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_focus_dark.9.png new file mode 100644 index 000000000..64e970687 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_focus_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_focus_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_focus_light.9.png new file mode 100644 index 000000000..0fd8cdda1 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_focus_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_normal_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_normal_dark.9.png new file mode 100644 index 000000000..3427b4768 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_normal_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_normal_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_normal_light.9.png new file mode 100644 index 000000000..31e38c4c1 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_normal_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_pressed_dark.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_pressed_dark.9.png new file mode 100644 index 000000000..e6a788073 Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_pressed_dark.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_pressed_light.9.png b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_pressed_light.9.png new file mode 100644 index 000000000..972962dcf Binary files /dev/null and b/MyTracks/googleplayservices_lib/src/main/res/drawable-xhdpi/common_signin_btn_text_pressed_light.9.png differ diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable/common_signin_btn_icon_dark.xml b/MyTracks/googleplayservices_lib/src/main/res/drawable/common_signin_btn_icon_dark.xml new file mode 100644 index 000000000..dd1cf679f --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/drawable/common_signin_btn_icon_dark.xml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable/common_signin_btn_icon_light.xml b/MyTracks/googleplayservices_lib/src/main/res/drawable/common_signin_btn_icon_light.xml new file mode 100644 index 000000000..abf412bda --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/drawable/common_signin_btn_icon_light.xml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable/common_signin_btn_text_dark.xml b/MyTracks/googleplayservices_lib/src/main/res/drawable/common_signin_btn_text_dark.xml new file mode 100644 index 000000000..2d92217cd --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/drawable/common_signin_btn_text_dark.xml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/MyTracks/googleplayservices_lib/src/main/res/drawable/common_signin_btn_text_light.xml b/MyTracks/googleplayservices_lib/src/main/res/drawable/common_signin_btn_text_light.xml new file mode 100644 index 000000000..810c02112 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/drawable/common_signin_btn_text_light.xml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-af/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-af/strings.xml new file mode 100644 index 000000000..005421f2d --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-af/strings.xml @@ -0,0 +1,19 @@ + + + "Kry Google Play-dienste" + "Hierdie program sal nie loop sonder Google Play-dienste nie, wat nie op jou foon is nie." + "Hierdie program sal nie loop sonder Google Play-dienste nie, wat nie op jou tablet is nie." + "Kry Google Play-dienste" + "Aktiveer Google Play-dienste" + "Hierdie program sal nie werk tensy jy Google Play-dienste aktiveer nie." + "Aktiveer Google Play-dienste" + "Dateer Google Play-dienste op" + "Hierdie program sal nie loop nie, tensy jy Google Play-dienste opdateer." + "Onbekende probleem met Google Play-dienste." + "Google Play-dienste" + "Google Play-dienste, waarop sommige van jou programme staatmaak, werk nie met jou toestel nie. Kontak asseblief die vervaardiger vir bystand." + "Dateer op" + "Meld aan" + "Meld aan met Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-am/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-am/strings.xml new file mode 100644 index 000000000..a253c224c --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-am/strings.xml @@ -0,0 +1,19 @@ + + + "Google Play አገልግሎቶችን አግኝ" + "ይህ መተግበሪያ ያለ Google Play አገልግሎቶች አይሰራም፣ እነሱ ደግሞ ስልክዎ ላይ የሉም።" + "ይህ መተግበሪያ ያለ Google Play አገልግሎቶች አይሰራም፣ እነሱ ደግሞ ጡባዊዎ ላይ የሉም።" + "Google Play አገልግሎቶችን አግኝ" + "Google Play አገልግሎቶችን አንቃ" + "Google Play አገልግሎቶችን እስካላነቁ ድረስ ይህ መተግበሪያ አይሰራም።" + "Google Play አገልግሎቶችን አንቃ" + "Google Play አገልግሎቶችን ያዘምኑ" + "Google Play አገልግሎቶችን እስኪያዘምኑ ድረስ ይህ መተግበሪያ አይሰራም።" + "በGoogle Play አገልግሎቶች ላይ ያልታወቀ ችግር።" + "Google Play አገልግሎቶች" + "የGoogle Play አገልግሎቶች፣ አንዳንድ መተግበሪያዎችዎ በእሱ ላይ ጥገኛ የሆኑት፣ በመሣሪያዎ አይደገፍም። እባክዎ ለእርዳታ አምራቹን ያግኙ።" + "ያዘምኑ" + "ግባ" + "በGoogle ይግቡ" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-ar/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-ar/strings.xml new file mode 100644 index 000000000..bd27a3a2f --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-ar/strings.xml @@ -0,0 +1,19 @@ + + + "الحصول على خدمات Google Play" + "لن يتم تشغيل هذا التطبيق بدون خدمات Google Play، والتي لا تتوفر في هاتفك." + "لن يتم تشغيل هذا التطبيق بدون خدمات Google Play، والتي لا تتوفر في جهازك اللوحي." + "الحصول على خدمات Google Play" + "تمكين خدمات Google Play" + "لن يعمل هذا التطبيق ما لم يتم تمكين خدمات Google Play." + "تمكين خدمات Google Play" + "تحديث خدمات Google Play" + "لن يتم تشغيل هذا التطبيق ما لم تحدِّث خدمات Google Play." + "حدثت مشكلة غير معروفة في خدمات Google Play." + "خدمات Google Play" + "خدمات Google Play التي تستجيب لها بعض تطبيقاتك لا تعمل على جهازك. يُرجى الاتصال بجهة التصنيع للحصول على المساعدة." + "تحديث" + "تسجيل الدخول" + "تسجيل الدخول باستخدام Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-be/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-be/strings.xml new file mode 100644 index 000000000..8c2fafb94 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-be/strings.xml @@ -0,0 +1,19 @@ + + + "Атрымаць службы Google Play" + "Гэта прыкладанне не будзе працаваць без службаў Google Play, якіх няма ў вашым тэлефоне." + "Гэта прыкладанне не будзе працаваць без службаў Google Play, якіх няма на вашым планшэце." + "Атрымаць службы Google Play" + "Уключыць службы Google Play" + "Гэта прыкладанне не будзе працаваць, пакуль вы не ўключыце службы Google Play." + "Уключыць службы Google Play" + "Абнаўленне службаў Google Play" + "Гэта прыкладанне не будзе працаваць падчас абнаўлення службаў Google Play." + "Невядомая праблема са службамі Google Play." + "Службы Google Play" + "Службы Google Play, да якiх прывязаны некаторыя прыкладаннi, не падтрымлiваюцца на вашай прыладзе. Па дапамогу звярнiцеся да вытворцы." + "Абнавіць" + "Увайсцi" + "Увайсці ў Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-bg/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-bg/strings.xml new file mode 100644 index 000000000..4a623bdcf --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-bg/strings.xml @@ -0,0 +1,19 @@ + + + "Изтегляне на услугите за Google Play" + "Това приложение няма да се изпълнява без услугите за Google Play, които липсват в телефона ви." + "Това приложение няма да се изпълнява без услугите за Google Play, които липсват в таблета ви." + "Услуги за Google Play: Изтегл." + "Активиране на услугите за Google Play" + "Това приложение няма да работи, освен ако не активирате услугите за Google Play." + "Услуги за Google Play: Актив." + "Актуализиране на услугите за Google Play" + "Това приложение няма да се изпълнява, освен ако не актуализирате услугите за Google Play." + "Неизвестен проблем с услугите за Google Play." + "Услуги за Google Play" + "Услугите за Google Play, на които разчитат някои от приложенията ви, не се поддържат от устройството ви. Моля, свържете се с производителя за помощ." + "Актуализиране" + "Вход" + "Вход с Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-ca/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-ca/strings.xml new file mode 100644 index 000000000..6eed55793 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-ca/strings.xml @@ -0,0 +1,19 @@ + + + "Baixa els serveis de Google Play" + "Aquesta aplicació no s\'executarà si el telèfon no té instal·lats els serveis de Google Play." + "Aquesta aplicació no funcionarà si la tauleta no té instal·lats els serveis de Google Play." + "Baixa els serveis de Google Play" + "Activa els serveis de Google Play" + "Aquesta aplicació no funcionarà si no actives els serveis de Google Play." + "Activa els serveis de Google Play" + "Actualitza els serveis de Google Play" + "Aquesta aplicació no s\'executarà si no actualitzes els serveis de Google Play." + "Error desconegut relacionat amb els serveis de Google Play." + "Serveis de Google Play" + "El teu dispositiu no és compatible amb els serveis de Google Play, en què es basen les teves aplicacions. Per obtenir assistència, contacta amb el fabricant." + "Actualitza" + "Inicia sessió" + "Inicia sessió amb Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-cs/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-cs/strings.xml new file mode 100644 index 000000000..5a315bdd2 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-cs/strings.xml @@ -0,0 +1,19 @@ + + + "Instalovat služby Google Play" + "Ke spuštění této aplikace jsou potřeba služby Google Play, které v telefonu nemáte." + "Ke spuštění této aplikace jsou potřeba služby Google Play, které v tabletu nemáte." + "Instalovat služby Google Play" + "Aktivovat služby Google Play" + "Ke spuštění této aplikace je třeba aktivovat služby Google Play." + "Aktivovat služby Google Play" + "Aktualizace služeb Google Play" + "Ke spuštění této aplikace je třeba aktualizovat služby Google Play." + "Nastal neznámý problém se službami Google Play." + "Služby Google Play" + "Některé vaše aplikace vyžadují služby Google Play, které ve vašem zařízení nejsou podporovány. S žádostí o pomoc se prosím obraťte na výrobce." + "Aktualizovat" + "Přihlásit se" + "Přihlásit se účtem Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-da/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-da/strings.xml new file mode 100644 index 000000000..8fa545570 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-da/strings.xml @@ -0,0 +1,19 @@ + + + "Hent Google Play-tjenester" + "Denne app kan ikke køre uden Google Play-tjenester, som mangler på din telefon." + "Denne app kan ikke køre uden Google Play-tjenester, som mangler på din tablet." + "Hent Google Play-tjenester" + "Aktivér Google Play-tjenester" + "Denne app virker ikke, medmindre du aktiverer Google Play-tjenester." + "Aktivér Google Play-tjenester" + "Opdater Google Play-tjenester" + "Denne app kan ikke køre, medmindre du opdaterer Google Play-tjenester." + "Ukendt problem med Google Play-tjenester." + "Google Play-tjenester" + "Google Play-tjenester, som nogle af dine applikationer er afhængige af, understøttes ikke af din enhed. Kontakt producenten for at få hjælp." + "Opdater" + "Log ind" + "Log ind med Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-de/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-de/strings.xml new file mode 100644 index 000000000..6b2bf6648 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-de/strings.xml @@ -0,0 +1,19 @@ + + + "Google Play-Dienste installieren" + "Zur Nutzung dieser App sind Google Play-Dienste erforderlich, die auf Ihrem Telefon nicht installiert sind." + "Zur Nutzung dieser App sind Google Play-Dienste erforderlich, die auf Ihrem Tablet nicht installiert sind." + "Google Play-Dienste installieren" + "Google Play-Dienste aktivieren" + "Diese App funktioniert nur, wenn Sie die Google Play-Dienste aktivieren." + "Google Play-Dienste aktivieren" + "Google Play-Dienste aktualisieren" + "Diese App wird nur ausgeführt, wenn Sie die Google Play-Dienste aktualisieren." + "Unbekanntes Problem mit Google Play-Diensten" + "Google Play-Dienste" + "Google Play-Dienste, auf denen einige Ihrer Apps basieren, werden von diesem Gerät nicht unterstützt. Wenden Sie sich für weitere Informationen an den Hersteller." + "Aktualisieren" + "Anmelden" + "Über Google anmelden" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-el/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-el/strings.xml new file mode 100644 index 000000000..f8c3ebd2e --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-el/strings.xml @@ -0,0 +1,19 @@ + + + "Λήψη υπηρεσιών Google Play" + "Αυτή η εφαρμογή δεν θα εκτελεστεί χωρίς τις υπηρεσίες Google Play, οι οποίες λείπουν από το τηλέφωνό σας." + "Αυτή η εφαρμογή δεν θα εκτελεστεί χωρίς τις υπηρεσίες Google Play, οι οποίες λείπουν από το tablet σας." + "Λήψη υπηρεσιών Google Play" + "Ενεργοποίηση υπηρεσιών Google Play" + "Αυτή η εφαρμογή δεν θα λειτουργήσει εάν δεν έχετε ενεργοποιήσει τις υπηρεσίες Google Play." + "Ενεργοπ. υπηρεσιών Google Play" + "Ενημέρωση υπηρεσιών Google Play" + "Αυτή η εφαρμογή θα εκτελεστεί αφού ενημερώσετε τις υπηρεσίες Google Play." + "Άγνωστο πρόβλημα με τις υπηρεσίες Google Play." + "Υπηρεσίες Google Play" + "Οι υπηρεσίες Google Play, στις οποίες βασίζονται ορισμένες από τις εφαρμογές σας, δεν υποστηρίζονται στη συσκευή σας. Επικοινωνήστε με τον κατασκευαστή για υποστήριξη." + "Ενημέρωση" + "Σύνδεση" + "Συνδεθείτε στο Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-en-rGB/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-en-rGB/strings.xml new file mode 100644 index 000000000..0cd4bacf3 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-en-rGB/strings.xml @@ -0,0 +1,19 @@ + + + "Get Google Play services" + "This app won\'t run without Google Play services, which are missing from your phone." + "This app won\'t run without Google Play services, which are missing from your tablet." + "Get Google Play services" + "Enable Google Play services" + "This app won\'t work unless you enable Google Play services." + "Enable Google Play services" + "Update Google Play services" + "This app won\'t run unless you update Google Play services." + "Unknown issue with Google Play services." + "Google Play services" + "Google Play services, which some of your applications rely on, is not supported by your device. Please contact the manufacturer for assistance." + "Update" + "Sign in" + "Sign in with Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-es-rUS/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-es-rUS/strings.xml new file mode 100644 index 000000000..40d46deeb --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-es-rUS/strings.xml @@ -0,0 +1,19 @@ + + + "Obtener Google Play Services" + "Esta aplicación no se ejecutará si no instalasGoogle Play Services en tu dispositivo." + "Esta aplicación no se ejecutará si no instalas Google Play Services en tu tableta." + "Descargar Google Play Services" + "Activar Google Play Services" + "Esta aplicación no funcionará si no activas Google Play Services." + "Activar Google Play Services" + "Actualizar Google Play Services" + "Esta aplicación no se ejecutará si no actualizas Google Play Services." + "Error desconocido relacionado con Google Play Services" + "Google Play Services" + "Google Play Services, del cual dependen algunas de tus aplicaciones, no es compatible con tu dispositivo. Comunícate con el fabricante para obtener ayuda." + "Actualizar" + "Acceder" + "Acceder con Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-es/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-es/strings.xml new file mode 100644 index 000000000..8494fe6d9 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-es/strings.xml @@ -0,0 +1,19 @@ + + + "Descargar servicios de Google Play" + "Esta aplicación no se ejecutará si tu teléfono no tiene instalados los servicios de Google Play." + "Esta aplicación no se ejecutará si tu tablet no tiene instalados los servicios de Google Play." + "Descargar servicios de Google Play" + "Habilitar servicios de Google Play" + "Esta aplicación no funcionará si no habilitas los servicios de Google Play." + "Habilitar servicios de Google Play" + "Actualizar servicios de Google Play" + "Esta aplicación no se ejecutará si no actualizas los servicios de Google Play." + "Error desconocido relacionado con los servicios de Google Play" + "Servicios de Google Play" + "Tu dispositivo no es compatible con los servicios de Google Play, de los cuales dependen tus aplicaciones. Para obtener asistencia, ponte en contacto el fabricante." + "Actualizar" + "Iniciar sesión" + "Iniciar sesión con Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-et/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-et/strings.xml new file mode 100644 index 000000000..3ea66d292 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-et/strings.xml @@ -0,0 +1,19 @@ + + + "Hankige Google Play teenused" + "Selle rakenduse käitamiseks on vaja Google Play teenuseid, mida teie telefonis pole." + "Selle rakenduse käitamiseks on vaja Google Play teenuseid, mida teie tahvelarvutis pole." + "Hankige Google Play teenused" + "Lubage Google Play teenused" + "See rakendus ei tööta, kui te ei luba Google Play teenuseid." + "Lubage Google Play teenused" + "Värskendage Google Play teenuseid" + "Seda rakendust ei saa käitada, kui te ei värskenda Google Play teenuseid." + "Google Play teenuste tundmatu probleem." + "Google Play teenused" + "Teie seade ei toeta Google Play teenuseid, millele mõni teie rakendustest toetub. Abi saamiseks võtke ühendust tootjaga." + "Värskenda" + "Logi sisse" + "Logi sisse Google\'iga" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-fa/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-fa/strings.xml new file mode 100644 index 000000000..144be38c2 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-fa/strings.xml @@ -0,0 +1,19 @@ + + + "دریافت خدمات Google Play" + "این برنامه بدون خدمات Google Play اجرا نمی‌شود، این خدمات در تلفن شما وجود ندارد." + "این برنامه بدون خدمات Google Play اجرا نمی‌شود، این خدمات در رایانهٔ لوحی شما وجود ندارد." + "دریافت خدمات Google Play" + "فعال کردن خدمات Google Play" + "تا زمانی‌که خدمات Google Play را فعال نکنید این برنامه کار نمی‌کند." + "فعال کردن خدمات Google Play" + "به‌روزرسانی خدمات Google Play" + "تا زمانی‌که خدمات Google Play را به‌روز نکنید این برنامه کار نمی‌کند." + "مشکل نامشخص در خدمات Google Play." + "خدمات Google Play" + "خدمات Google Play، که برخی از برنامه‌های شما به آن وابسته است، توسط دستگاه شما پشتیبانی نمی‌شود. لطفاً برای دریافت کمک با سازنده تماس بگیرید." + "به‌روزرسانی" + "ورود به سیستم" + "ورود به سیستم با Google‎" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-fi/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-fi/strings.xml new file mode 100644 index 000000000..75d40e4a8 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-fi/strings.xml @@ -0,0 +1,19 @@ + + + "Asenna Google Play -palvelut" + "Tämä sovellus ei toimi ilman Google Play -palveluita, jotka puuttuvat puhelimesta." + "Tämä sovellus ei toimi ilman Google Play -palveluita, jotka puuttuvat tablet-laitteesta." + "Asenna Google Play -palvelut" + "Ota Google Play -palvelut käyttöön" + "Tämä sovellus ei toimi, ellet ota Google Play -palveluita käyttöön." + "Ota Google Play -palv. käyttöön" + "Päivitä Google Play -palvelut" + "Tämä sovellus ei toimi, ellet päivitä Google Play -palveluita." + "Tuntematon ongelma käytettäessä Google Play -palveluita." + "Google Play -palvelut" + "Google Play -palveluita, joita osa sovelluksistasi käyttää, ei tueta laitteellasi. Pyydä ohjeita laitteen valmistajalta." + "Päivitä" + "Kirjaudu" + "Kirjaudu Google-tiliin" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-fr/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-fr/strings.xml new file mode 100644 index 000000000..caaed744e --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-fr/strings.xml @@ -0,0 +1,19 @@ + + + "Installer les services Google Play" + "Cette application ne fonctionnera pas sans les services Google Play, qui ne sont pas installés sur votre téléphone." + "Cette application ne fonctionnera pas sans les services Google Play, qui ne sont pas installés sur votre tablette." + "Installer services Google Play" + "Activer les services Google Play" + "Cette application ne fonctionnera pas tant que vous n\'aurez pas activé les services Google Play." + "Activer services Google Play" + "Mettre à jour les services Google Play" + "Cette application ne fonctionnera pas tant que vous n\'aurez pas mis à jour les services Google Play." + "Problème inconnu avec les services Google Play." + "Services Google Play" + "Les services Google Play, dont dépendent certaines de vos applications, ne sont pas compatibles avec votre appareil. Veuillez contacter le fabricant pour obtenir de l\'aide." + "Mettre à jour" + "Connexion" + "Se connecter avec Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-hi/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-hi/strings.xml new file mode 100644 index 000000000..62e00e5df --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-hi/strings.xml @@ -0,0 +1,19 @@ + + + "Google Play सेवाएं पाएं" + "यह एप्लिकेशन Google Play सेवाओं के बिना नहीं चलेगा, जो आपके फ़ोन में नहीं हैं." + "यह एप्लिकेशन Google Play सेवाओं के बिना नहीं चलेगा, जो आपके टेबलेट में नहीं हैं." + "Google Play सेवाएं पाएं" + "Google Play सेवाएं सक्षम करें" + "जब तक आप Google Play सेवाएं सक्षम नहीं करते, तब तक यह एप्लिकेशन कार्य नहीं करेगा." + "Google Play सेवाएं सक्षम करें" + "Google Play सेवाएं अपडेट करें" + "जब तक आप Google Play सेवाओं को अपडेट नहीं करते, तब तक यह एप्लिकेशन नहीं चलेगा." + "Google Play सेवाओं के साथ अज्ञात समस्या." + "Google Play सेवाएं" + "Google Play सेवाएं, जिन पर आपके कुछ एप्लिकेशन निर्भर करते हैं, आपके उपकरण द्वारा समर्थित नहीं हैं. कृपया सहायता के लिए निर्माता से संपर्क करें." + "अपडेट करें" + "साइन इन करें" + "Google से साइन इन करें" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-hr/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-hr/strings.xml new file mode 100644 index 000000000..bf5a6f921 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-hr/strings.xml @@ -0,0 +1,19 @@ + + + "Preuzmi usluge za Google Play" + "Ova aplikacija neće funkcionirati bez usluga za Google Play, koje nisu instalirane na vašem telefonu." + "Ova aplikacija neće funkcionirati bez usluga za Google Play, koje nisu instalirane na vašem tabletnom računalu." + "Preuzmi usluge za Google Play" + "Omogući usluge za Google Play" + "Ova aplikacija neće raditi ako ne omogućite usluge za Google Play." + "Omogući usluge za Google Play" + "Ažuriraj usluge za Google Play" + "Ova se aplikacija neće pokrenuti ako ne ažurirate usluge za Google Play." + "Nepoznata poteškoća s uslugama za Google Play." + "Usluge za Google Play" + "Usluge za Google Play, koje su potrebne za funkcioniranje nekih vaših aplikacija, nisu podržane na vašem uređaju. Pomoć potražite od proizvođača." + "Ažuriranje" + "Prijava" + "Prijava uslugom Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-hu/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-hu/strings.xml new file mode 100644 index 000000000..1563e625d --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-hu/strings.xml @@ -0,0 +1,19 @@ + + + "Play Szolgáltatások telepítése" + "Az alkalmazás működéséhez a Google Play Szolgáltatások szükségesek, ezek nincsenek telepítve a telefonon." + "Az alkalmazás működéséhez a Google Play Szolgáltatások szükségesek, ezek nincsenek telepítve a táblagépen." + "Play Szolgáltatások telepítése" + "Google Play Szolgáltatások aktiválása" + "Az alkalmazás csak akkor fog működni, ha engedélyezi a Google Play Szolgáltatásokat." + "Play Szolgáltatások aktiválása" + "Play Szolgáltatások frissítése" + "Az alkalmazás csak akkor fog működni, ha frissíti a Google Play Szolgáltatásokat." + "Ismeretlen hiba a Google Play Szolgáltatásokban." + "Google Play Szolgáltatások" + "A Google Play Szolgáltatásokat, amelyre egyes alkalmazások támaszkodnak, nem támogatja az eszköz. Segítségért forduljon az eszköz gyártójához." + "Frissítés" + "Belépés" + "Google-bejelentkezés" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-in/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-in/strings.xml new file mode 100644 index 000000000..d51a4e423 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-in/strings.xml @@ -0,0 +1,19 @@ + + + "Dapatkan layanan Google Play" + "Aplikasi ini tidak akan berjalan tanpa layanan Google Play, yang tidak ada di ponsel Anda." + "Aplikasi ini tidak akan berjalan tanpa layanan Google Play, yang tidak ada di tablet Anda." + "Dapatkan layanan Google Play" + "Aktifkan layanan Google Play" + "Aplikasi ini tidak akan bekerja sampai Anda mengaktifkan layanan Google Play." + "Aktifkan layanan Google Play" + "Perbarui layanan Google Play" + "Aplikasi ini tidak akan berjalan sampai Anda memperbarui layanan Google Play." + "Masalah tidak diketahui pada layanan Google Play." + "Layanan Google Play" + "Layanan Google Play, yang diandalkan oleh beberapa aplikasi Anda, tidak didukung oleh perangkat Anda. Hubungi pabrikan untuk mendapatkan bantuan." + "Perbarui" + "Masuk" + "Masuk dengan Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-it/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-it/strings.xml new file mode 100644 index 000000000..f75eb69f6 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-it/strings.xml @@ -0,0 +1,19 @@ + + + "Installa Google Play Services" + "L\'app non funzionerà senza Google Play Services, non presente sul tuo telefono." + "L\'app non funzionerà senza Google Play Services, non presente sul tuo tablet." + "Installa Google Play Services" + "Attiva Google Play Services" + "L\'app non funzionerà se non attivi Google Play Services." + "Attiva Google Play Services" + "Aggiorna Google Play Services" + "L\'app non funzionerà se non aggiorni Google Play Services." + "Problema sconosciuto con Google Play Services." + "Google Play Services" + "La piattaforma Google Play Services, su cui sono basate alcune delle tue applicazioni, non è supportata dal dispositivo in uso. Per assistenza, contatta il produttore." + "Aggiorna" + "Accedi" + "Accedi con Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-iw/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-iw/strings.xml new file mode 100644 index 000000000..25a4cba98 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-iw/strings.xml @@ -0,0 +1,19 @@ + + + "קבל את שירותי Google Play" + "יישום זה לא יפעל ללא שירותי Google Play, החסרים בטלפון שלך." + "יישום זה לא יפעל ללא שירותי Google Play, החסרים בטאבלט שלך." + "קבל את שירותי Google Play" + "הפעלת שירותי Google Play" + "יישום זה לא יעבוד אם לא תפעיל את שירותי Google Play." + "הפעל את שירותי Google Play" + "עדכון שירותי Google Play" + "יישום זה לא יפעל אם לא תעדכן את שירותי Google Play." + "בעיה לא ידועה בשירותי Google Play." + "שירותי Google Play" + "שירותי Google Play, שחלק מהיישומים שלך מתבססים עליהם, אינם נתמכים על ידי המכשיר שברשותך. צור קשר עם היצרן לקבלת סיוע." + "עדכן" + "היכנס" + "היכנס באמצעות Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-ja/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-ja/strings.xml new file mode 100644 index 000000000..f520ffac7 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-ja/strings.xml @@ -0,0 +1,19 @@ + + + "Play開発者サービスの入手" + "このアプリの実行にはGoogle Play開発者サービスが必要ですが、お使いの携帯端末にはインストールされていません。" + "このアプリの実行にはGoogle Play開発者サービスが必要ですが、お使いのタブレットにはインストールされていません。" + "Play開発者サービスの入手" + "Play開発者サービスの有効化" + "このアプリの実行には、Google Play開発者サービスの有効化が必要です。" + "Play開発者サービスの有効化" + "Play開発者サービスの更新" + "このアプリの実行には、Google Play開発者サービスの更新が必要です。" + "Google Play開発者サービスで原因不明の問題が発生しました。" + "Google Play開発者サービス" + "一部のアプリが使用しているGoogle Play開発者サービスは、お使いの端末ではサポートされていません。詳しくは、端末メーカーまでお問い合わせください。" + "更新" + "ログイン" + "Googleでログイン" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-ko/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-ko/strings.xml new file mode 100644 index 000000000..b2ccd7760 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-ko/strings.xml @@ -0,0 +1,19 @@ + + + "Google Play 서비스 설치" + "휴대전화에 Google Play 서비스가 설치되어 있어야 이 앱이 실행됩니다." + "태블릿에 Google Play 서비스가 설치되어 있어야 이 앱이 실행됩니다." + "Google Play 서비스 설치" + "Google Play 서비스 사용" + "Google Play 서비스를 사용하도록 설정해야 이 앱이 작동합니다." + "Google Play 서비스 사용" + "Google Play 서비스 업데이트" + "Google Play 서비스를 업데이트해야만 이 앱이 실행됩니다." + "Google Play 서비스에 알 수 없는 문제가 발생했습니다." + "Google Play 서비스" + "일부 사용자 애플리케이션에 필요한 Google Play 서비스가 사용자 기기에서 지원되지 않습니다. 기기 제조업체에 문의하시기 바랍니다." + "업데이트" + "로그인" + "Google 계정으로 로그인" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-lt/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-lt/strings.xml new file mode 100644 index 000000000..ea9003f81 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-lt/strings.xml @@ -0,0 +1,19 @@ + + + "Gauti „Google Play“ paslaugų" + "Ši programa neveiks be „Google Play“ paslaugų, kurios neįdiegtos telefone." + "Ši programa neveiks be „Google Play“ paslaugų, kurios neįdiegtos planšetiniame kompiuteryje." + "Gauti „Google Play“ paslaugų" + "Įgalinti „Google Play“ paslaugas" + "Ši programa neveiks, jei neįgalinsite „Google Play“ paslaugų." + "Įgal. „Google Play“ paslaugas" + "Atnaujinti „Google Play“ paslaugas" + "Ši programa neveiks, jei neatnaujinsite „Google Play“ paslaugų." + "Nežinoma „Google Play“ paslaugų problema." + "„Google Play“ paslaugos" + "Jūsų įrenginys nepalaiko „Google Play“ paslaugų, kuriomis remiasi kai kurios programos. Jei reikia pagalbos, susisiekite su gamintoju." + "Atnaujinti" + "Prisij." + "Prisij. naud. „Google“" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-lv/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-lv/strings.xml new file mode 100644 index 000000000..62b9dc793 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-lv/strings.xml @@ -0,0 +1,19 @@ + + + "Google Play pakalpojumu iegūšana" + "Lai šī lietotne darbotos, tālrunī ir jāinstalē Google Play pakalpojumi." + "Lai šī lietotne darbotos, planšetdatorā ir jāinstalē Google Play pakalpojumi." + "Iegūt Google Play pakalpojumus" + "Google Play pakalpojumu iespējošana" + "Lai šī lietotne darbotos, iespējojiet Google Play pakalpojumus." + "Iespējot Google Play pakalpojumus" + "Google Play pakalpojumu atjaunināšana" + "Lai šī lietotne darbotos, atjauniniet Google Play pakalpojumus." + "Nezināma problēma ar Google Play pakalpojumiem." + "Google Play pakalpojumi" + "Jūsu ierīce neatbalsta Google Play pakalpojumus, kuri nepieciešami dažu jūsu lietojumprogrammu darbībai. Lūdzu, sazinieties ar ražotāju, lai saņemtu palīdzību." + "Atjaunināt" + "Pierakst." + "Pierakstīties Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-ms/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-ms/strings.xml new file mode 100644 index 000000000..fece41f09 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-ms/strings.xml @@ -0,0 +1,19 @@ + + + "Dapatkan perkhidmatan Google Play" + "Apl ini tidak akan berfungsi tanpa perkhidmatan Google Play dan apl ini tiada pada telefon anda." + "Apl ini tidak akan berfungsi tanpa perkhidmatan Google Play dan apl ini tiada pada tablet anda." + "Dapatkan perkhidmatan Google Play" + "Dayakan perkhidmatan Google Play" + "Apl ini tidak akan berfungsi kecuali anda mendayakan perkhidmatan Google Play." + "Dayakan perkhidmatan Google Play" + "Kemas kini perkhidmatan Google Play" + "Apl ini tidak akan berfungsi kecuali anda mengemas kini perkhidmatan Google Play." + "Isu tidak diketahui dengan perkhidmatan Google Play." + "Perkhidmatan Google Play" + "Peranti anda tidak menyokong perkhidmatan Google Play, sedangkan sesetengah aplikasi anda memerlukannya. Sila hubungi pengilang untuk bantuan." + "Kemas kini" + "Log masuk" + "Log masuk dengan Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-nb/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-nb/strings.xml new file mode 100644 index 000000000..566006226 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-nb/strings.xml @@ -0,0 +1,19 @@ + + + "Installer Google Play Tjenester" + "Denne appen kan ikke kjøres uten Google Play Tjenester, som ikke er installert på telefonen din." + "Denne appen kan ikke kjøres uten Google Play Tjenester, som ikke er installert på nettbrettet ditt." + "Installer Google Play Tjenester" + "Aktiver Google Play Tjenester" + "Denne appen fungerer ikke med mindre du aktiverer Google Play Tjenester." + "Aktiver Google Play Tjenester" + "Oppdater Google Play Tjenester" + "Denne appen kan ikke kjøres før du oppdaterer Google Play Tjenester." + "Det oppsto et ukjent problem med Google Play Tjenester." + "Google Play-tjenester" + "Google Play Tjenester, som noen av appene er avhengige av, støttes ikke av enheten. Ta kontakt med produsenten for å få hjelp." + "Oppdater" + "Logg på" + "Logg inn med Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-nl/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-nl/strings.xml new file mode 100644 index 000000000..b1e5b24e1 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-nl/strings.xml @@ -0,0 +1,19 @@ + + + "Google Play-services ophalen" + "Deze app kan niet worden uitgevoerd zonder Google Play-services die ontbreken op uw telefoon." + "Deze app kan niet worden uitgevoerd zonder Google Play-services die ontbreken op uw tablet." + "Google Play-services ophalen" + "Google Play-services inschakelen" + "Deze app werkt niet, tenzij u Google Play-services inschakelt." + "Google Play-services inschak." + "Google Play-services bijwerken" + "Deze app kan niet worden uitgevoerd, tenzij u Google Play-services bijwerkt." + "Onbekend probleem met Google Play-services." + "Google Play-services" + "Google Play-services, dat vereist is voor een aantal van uw applicaties, wordt niet ondersteund door uw apparaat. Neem contact op met de fabrikant voor ondersteuning." + "Bijwerken" + "Inloggen" + "Inloggen met Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-pl/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-pl/strings.xml new file mode 100644 index 000000000..7fdac73f9 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-pl/strings.xml @@ -0,0 +1,19 @@ + + + "Pobierz Usługi Google Play" + "Ta aplikacja nie będzie działać bez Usług Google Play, których nie masz na telefonie." + "Ta aplikacja nie będzie działać bez Usług Google Play, których nie masz na tablecie." + "Pobierz Usługi Google Play" + "Włącz Usługi Google Play" + "Ta aplikacja nie będzie działać, jeśli nie włączysz Usług Google Play." + "Włącz Usługi Google Play" + "Aktualizuj Usługi Google Play" + "Ta aplikacja nie będzie działać, jeśli nie zaktualizujesz Usług Google Play." + "Nieznany problem z Usługami Google Play." + "Usługi Google Play" + "Usługi Google Play, od których zależy działanie niektórych aplikacji, nie są obsługiwane na Twoim urządzeniu. Skontaktuj się z producentem, by uzyskać pomoc." + "Aktualizuj" + "Zaloguj się" + "Zaloguj się przez Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-pt-rBR/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-pt-rBR/strings.xml new file mode 100644 index 000000000..3eb33f8a6 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-pt-rBR/strings.xml @@ -0,0 +1,19 @@ + + + "Instale o Google Play Services" + "Este aplicativo não funciona sem o Google Play Services, que não está instalado em seu telefone." + "Este aplicativo não funciona sem o Google Play Services, que não está instalado em seu tablet." + "Instalar o Google Play Services" + "Ative o Google Play Services" + "Este aplicativo só funciona com o Google Play Services ativado." + "Ativar o Google Play Services" + "Atualize o Google Play Services" + "Este aplicativo só funciona com uma versão atualizada do Google Play Services." + "Problema desconhecido com o Google Play Services." + "Play Services" + "O Google Play Services, necessário para alguns dos aplicativos, não é compatível com seu dispositivo. Entre em contato com o fabricante para obter assistência." + "Atualizar" + "Login" + "Fazer login com o Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-pt-rPT/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-pt-rPT/strings.xml new file mode 100644 index 000000000..ae5d6217b --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-pt-rPT/strings.xml @@ -0,0 +1,19 @@ + + + "Obter serviços do Google Play" + "Esta aplicação não será executada sem os serviços do Google Play, que estão em falta no seu telemóvel." + "Esta aplicação não será executada sem os serviços do Google Play, que estão em falta no seu tablet." + "Obter serviços do Google Play" + "Ativar serviços do Google Play" + "Esta aplicação não funcionará enquanto não ativar os serviços do Google Play." + "Ativar serviços do Google Play" + "Atualizar serviços do Google Play" + "Esta aplicação não será executada enquanto não atualizar os serviços do Google Play." + "Problema desconhecido nos serviços do Google Play." + "Serviços do Google Play" + "Os serviços do Google Play, dos quais dependem algumas das suas aplicações, não são suportados pelo seu dispositivo. Contacte o fabricante para obter assistência." + "Atualizar" + "Inic. ses." + "Inic. sessão com o Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-pt/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-pt/strings.xml new file mode 100644 index 000000000..3eb33f8a6 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-pt/strings.xml @@ -0,0 +1,19 @@ + + + "Instale o Google Play Services" + "Este aplicativo não funciona sem o Google Play Services, que não está instalado em seu telefone." + "Este aplicativo não funciona sem o Google Play Services, que não está instalado em seu tablet." + "Instalar o Google Play Services" + "Ative o Google Play Services" + "Este aplicativo só funciona com o Google Play Services ativado." + "Ativar o Google Play Services" + "Atualize o Google Play Services" + "Este aplicativo só funciona com uma versão atualizada do Google Play Services." + "Problema desconhecido com o Google Play Services." + "Play Services" + "O Google Play Services, necessário para alguns dos aplicativos, não é compatível com seu dispositivo. Entre em contato com o fabricante para obter assistência." + "Atualizar" + "Login" + "Fazer login com o Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-ro/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-ro/strings.xml new file mode 100644 index 000000000..751b66a97 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-ro/strings.xml @@ -0,0 +1,19 @@ + + + "Descărcaţi Servicii Google Play" + "Această aplicaţie nu poate rula fără Servicii Google Play, care lipsesc de pe telefon." + "Această aplicaţie nu poate rula fără Servicii Google Play, care lipsesc de pe tabletă." + "Obţineţi Servicii Google Play" + "Activaţi Servicii Google Play" + "Această aplicaţie nu va funcţiona decât dacă activaţi Servicii Google Play." + "Activaţi Servicii Google Play" + "Actualizaţi Servicii Google Play" + "Această aplicaţie nu poate rula decât dacă actualizaţi Servicii Google Play." + "Problemă necunoscută privind Servicii Google Play." + "Servicii Google Play" + "Gadgetul nu acceptă serviciile Google Play, pe care se bazează unele dintre aplicații. Pentru asistență, contactați producătorul gadgetului." + "Actualizaţi" + "Conectați" + "Conectați-vă cu Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-ru/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-ru/strings.xml new file mode 100644 index 000000000..f92ef7d5a --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-ru/strings.xml @@ -0,0 +1,19 @@ + + + "Установите Сервисы Google Play" + "Для работы этого приложения требуется установить Сервисы Google Play." + "Для работы этого приложения требуется установить Сервисы Google Play." + "Установить" + "Включите Сервисы Google Play" + "Для работы этого приложения требуется включить Сервисы Google Play." + "Включить" + "Обновите Сервисы Google Play" + "Для работы этого приложения требуется обновить Сервисы Google Play." + "Неизвестная ошибка с Сервисами Google Play." + "Сервисы Google Play" + "Сервисы Google Play, необходимые для работы некоторых приложений, не поддерживаются на вашем устройстве. Обратитесь к производителю." + "Обновить" + "Войти" + "Войти в аккаунт Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-sk/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-sk/strings.xml new file mode 100644 index 000000000..0b7e18c42 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-sk/strings.xml @@ -0,0 +1,19 @@ + + + "Inštalovať služby Google Play" + "Na spustenie tejto aplikácie sa vyžadujú služby Google Play, ktoré v telefóne nemáte." + "Na spustenie tejto aplikácie sa vyžadujú služby Google Play, ktoré v tablete nemáte." + "Inštalovať služby Google Play" + "Povoliť služby Google Play" + "Táto aplikácia bude fungovať až po povolení služieb Google Play." + "Povoliť služby Google Play" + "Aktualizovať služby Google Play" + "Túto aplikáciu bude možné spustiť až po aktualizácii služieb Google Play." + "Neznámy problém so službami Google Play." + "Služby Google Play" + "Niektoré vaše aplikácie vyžadujú služby Google Play, ktoré vo vašom zariadení nie sú podporované. Ak potrebujete pomoc, kontaktujte výrobcu." + "Aktualizovať" + "Prihlásiť sa" + "Prihlásiť sa do účtu Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-sl/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-sl/strings.xml new file mode 100644 index 000000000..c14175e00 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-sl/strings.xml @@ -0,0 +1,19 @@ + + + "Namestite storitve Google Play" + "Ta aplikacija ne deluje brez storitev Google Play, ki jih ni v telefonu." + "Ta aplikacija ne deluje brez storitev Google Play, ki jih ni v tabličnem računalniku." + "Namestite storitve Google Play" + "Omogočite storitve Google Play" + "Aplikacija ne bo delovala, če ne omogočite storitev Google Play." + "Omogočite storitve Google Play" + "Posodobite storitve Google Play" + "Ta aplikacija ne deluje, če ne posodobite storitev Google Play." + "Neznana težava s storitvami Google Play." + "Storitve Google Play" + "Vaša naprava na podpira storitev Google Play, ki jih potrebujejo nekatere od vaših aplikacij. Za pomoč se obrnite na izdelovalca." + "Posodobi" + "Prijava" + "Prijavite se v Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-sr/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-sr/strings.xml new file mode 100644 index 000000000..06cd24094 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-sr/strings.xml @@ -0,0 +1,19 @@ + + + "Преузимање Google Play услуга" + "Ова апликација не може да се покрене без Google Play услуга, које недостају на телефону." + "Ова апликација не може да се покрене без Google Play услуга, које недостају на таблету." + "Преузми Google Play услуге" + "Омогућавање Google Play услуга" + "Ова апликација неће функционисати ако не омогућите Google Play услуге." + "Омогући Google Play услуге" + "Ажурирање Google Play услуга" + "Ова апликација не може да се покрене ако не ажурирате Google Play услуге." + "Непознат проблем са Google Play услугама." + "Google Play услуге" + "Google Play услуге, које су потребне за функционисање неких од апликација, нису подржане на уређају. Контактирајте произвођача да бисте добили помоћ." + "Ажурирај" + "Пријави ме" + "Пријави ме преко Google-а" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-sv/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-sv/strings.xml new file mode 100644 index 000000000..4f80eccb6 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-sv/strings.xml @@ -0,0 +1,19 @@ + + + "Hämta Google Play Tjänster" + "Den här appen kan inte köras utan Google Play Tjänster, som saknas på mobilen." + "Den här appen kan inte köras utan Google Play Tjänster, som saknas på surfplattan." + "Hämta Google Play Tjänster" + "Aktivera Google Play Tjänster" + "Du måste aktivera Google Play Tjänster för att den här appen ska fungera." + "Aktivera Google Play Tjänster" + "Uppdatera Google Play Tjänster" + "Du måste uppdatera Google Play Tjänster innan du kan köra den här appen." + "Okänt problem med Google Play Tjänster" + "Google Play-tjänster" + "Några av dina appar använder Google Play-tjänster som inte stöds av din enhet. Kontakta tillverkaren om du vill ha hjälp." + "Uppdatera" + "Logga in" + "Logga in med Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-sw/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-sw/strings.xml new file mode 100644 index 000000000..e945d7a88 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-sw/strings.xml @@ -0,0 +1,19 @@ + + + "Pata huduma za Google Play" + "Programu hii haiwezi kuendeshwa bila huduma za Google Play, ambazo hazipo kwenye simu yako." + "Programu hii haiwezi kuendeshwa bila huduma za Google Play, ambazo hazipo kwenye kompyuta yako ndogo." + "Pata huduma za Google Play" + "Wezesha huduma za Google Play" + "Programu hii haitafanya kazi mpaka utakapowezesha huduma za Google Play." + "Wezesha huduma za Google Play" + "Sasisha huduma za Google Play" + "Programu hii haiwezi kuendeshwa mpaka utakaposasisha huduma za Google Play." + "Suala lisilojulikana na huduma za Google Play." + "Huduma za Google Play" + "Huduma za Google Play, ambazo baadhi ya programu zako zinategemea, si linganifu na kifaa chako. Tafadhali wasiliana na mtengenezaji kwa usaidizi." + "Sasisha" + "Ingia" + "Ingia ukitumia Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-th/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-th/strings.xml new file mode 100644 index 000000000..f277b3ec5 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-th/strings.xml @@ -0,0 +1,19 @@ + + + "รับบริการ Google Play" + "แอปพลิเคชันนี้จะไม่ทำงานหากไม่มีบริการ Google Play ซึ่งไม่มีในโทรศัพท์ของคุณ" + "แอปพลิเคชันนี้จะไม่ทำงานหากไม่มีบริการ Google Play ซึ่งไม่มีในแท็บเล็ตของคุณ" + "รับบริการ Google Play" + "เปิดใช้งานบริการ Google Play" + "แอปพลิเคชันนี้จะไม่ทำงานจนกว่าคุณจะเปิดใช้งานบริการ Google Play" + "เปิดใช้งานบริการ Google Play" + "อัปเดตบริการ Google Play" + "แอปพลิเคชันนี้จะไม่ทำงานจนกว่าคุณจะอัปเดตบริการ Google Play" + "ปัญหาที่ไม่รู้จักของบริการ Google Play" + "บริการ Google Play" + "บริการ Google Play ซึ่งใช้งานในบางแอปพลิเคชัน ไม่ได้รับการสนับสนุนโดยอุปกรณ์ของคุณ โปรดติดต่อผู้ผลิตเพื่อขอรับความช่วยเหลือ" + "อัปเดต" + "ลงชื่อใช้" + "ลงชื่อเข้าใช้ด้วย Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-tl/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-tl/strings.xml new file mode 100644 index 000000000..4b0a92e80 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-tl/strings.xml @@ -0,0 +1,19 @@ + + + "Kumuha ng mga serbisyo ng Google Play" + "Hindi tatakbo ang app na ito nang wala ang mga serbisyo ng Google Play, na wala sa iyong telepono." + "Hindi gagana ang app na ito nang wala ang mga serbisyo ng Google Play, na wala sa iyong tablet." + "Kumuha ng Google Play services" + "Paganahin ang Google Play services" + "Hindi gagana ang app na ito maliban kung papaganahin mo ang mga serbisyo ng Google Play." + "Enable Google Play services" + "I-update ang mga serbisyo ng Google Play" + "Hindi gagana ang app na ito maliban kung i-a-update mo ang mga serbisyo ng Google Play." + "May hindi alam na isyu sa mga serbisyo ng Google Play." + "Mga serbisyo ng Google Play" + "Ang mga serbisyo ng Google Play, kung saan nakadepende ang ilan sa iyong mga application, ay hindi sinusuportahan ng iyong device. Mangyaring makipag-ugnay sa manufacturer para sa tulong." + "I-update" + "Sign in" + "Mag-sign in sa Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-tr/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-tr/strings.xml new file mode 100644 index 000000000..d495d7397 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-tr/strings.xml @@ -0,0 +1,19 @@ + + + "Google Play hizmetlerini edinin" + "Google Play Hizmetleri telefonunuzda yok ve bu uygulama Google Play Hizmetleri olmadan çalışmaz." + "Google Play Hizmetleri tabletinizde yok ve bu uygulama Google Play Hizmetleri olmadan çalışmaz." + "Google Play hizmetlerini edin" + "Google Play hizmetlerini etkinleştir" + "Bu uygulama, Google Play Hizmetleri etkinleştirilmeden çalışmaz" + "Google Play hizmetlerini etkinleştir" + "Google Play hizmetlerini güncelle" + "Bu uygulama Google Play Hizmetleri güncellenmeden çalışmaz." + "Google Play hizmetleriyle ilgili bilinmeyen sorun." + "Google Play hizmetleri" + "Cihazınız, uygulamalarınızdan bazıları için gerekli olan Google Play hizmetlerini desteklemiyor. Lütfen yardım için üreticiyle iletişim kurun." + "Güncelle" + "Oturum aç" + "Google\'da oturum aç" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-uk/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-uk/strings.xml new file mode 100644 index 000000000..c4caf97aa --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-uk/strings.xml @@ -0,0 +1,19 @@ + + + "Установити Google Play Послуги" + "Ця програма не запуститься без Google Play Послуг, яких немає у вашому телефоні." + "Ця програма не запуститься без Google Play Послуг, яких немає на вашому планшетному ПК." + "Установити Google Play Послуги" + "Увімкнути Google Play Послуги" + "Ця програма не працюватиме, поки ви не ввімкнете Google Play Послуги." + "Увімкнути Google Play Послуги" + "Оновити Google Play Послуги" + "Ця програма не запуститься, поки ви не оновите Google Play Послуги." + "Google Play Послуги – невідома проблема." + "Сервіси Google Play" + "Ваш пристрій не підтримує Сервіси Google Play, від яких залежить робота деяких програм. Зверніться по допомогу до виробника." + "Оновити" + "Увійти" + "Увійти в обл.запис Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-vi/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-vi/strings.xml new file mode 100644 index 000000000..e39c5c7fa --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-vi/strings.xml @@ -0,0 +1,19 @@ + + + "Cài đặt dịch vụ của Google Play" + "Ứng dụng này sẽ không chạy nếu không có dịch vụ của Google Play. Điện thoại của bạn bị thiếu dịch vụ này." + "Ứng dụng này sẽ không chạy nếu không có dịch vụ của Google Play. Máy tính bảng của bạn bị thiếu dịch vụ này." + "Cài đặt dịch vụ của Google Play" + "Bật dịch vụ của Google Play" + "Ứng dụng này sẽ không hoạt động trừ khi bạn bật dịch vụ của Google Play." + "Bật dịch vụ của Google Play" + "Cập nhật dịch vụ của Google Play" + "Ứng dụng này sẽ không chạy trừ khi bạn cập nhật dịch vụ của Google Play." + "Sự cố không xác định với dịch vụ của Google Play." + "Dịch vụ của Google Play" + "Các dịch vụ của Google Play mà một số ứng dụng của bạn dựa vào không được thiết bị của bạn hỗ trợ. Vui lòng liên hệ với nhà sản xuất để được hỗ trợ." + "Cập nhật" + "Đăng nhập" + "Đăng nhập bằng Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-zh-rCN/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-zh-rCN/strings.xml new file mode 100644 index 000000000..6c7d79c6b --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-zh-rCN/strings.xml @@ -0,0 +1,19 @@ + + + "获取 Google Play 服务" + "您的手机中没有 Google Play 服务,您必须先安装该服务才能运行此应用。" + "您的平板电脑中没有 Google Play 服务,您必须先安装该服务才能运行此应用。" + "获取 Google Play 服务" + "启用 Google Play 服务" + "您必须先启用 Google Play 服务才能运行此应用。" + "启用 Google Play 服务" + "更新 Google Play 服务" + "您必须先更新 Google Play 服务才能运行此应用。" + "Google Play 服务出现未知问题。" + "Google Play 服务" + "您的设备不支持部分应用所依赖的 Google Play 服务。请与设备制造商联系,以寻求帮助。" + "更新" + "登录" + "使用 Google 帐户登录" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-zh-rTW/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-zh-rTW/strings.xml new file mode 100644 index 000000000..7065b0033 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-zh-rTW/strings.xml @@ -0,0 +1,19 @@ + + + "取得 Google Play 服務" + "您的手機並未安裝 Google Play 服務,所以無法執行這個應用程式。" + "您的平板電腦並未安裝 Google Play 服務,所以無法執行這個應用程式。" + "取得 Google Play 服務" + "啟用 Google Play 服務" + "您必須啟用 Google Play 服務,這個應用程式才能運作。" + "啟用 Google Play 服務" + "更新 Google Play 服務" + "您必須更新 Google Play 服務,才能執行這個應用程式。" + "Google Play 服務發生不明問題。" + "Google Play 服務" + "您的裝置不支援部分應用程式所需的 Google Play 服務。如需協助,請與您的裝置製造商聯絡。" + "更新" + "登入" + "使用 Google 帳戶登入" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values-zu/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values-zu/strings.xml new file mode 100644 index 000000000..1f33ab6c1 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values-zu/strings.xml @@ -0,0 +1,19 @@ + + + "Thola amasevisi e-Google Play" + "Lolu hlelo lokusebenza ngeke lusebenze ngaphandle kwamasevisi e-Google Play, angekho efonini yakho." + "Lolu hlelo lokusebenza ngeke lusebenze ngaphandle kwamasevisi e-Google Play, angekho kuthebulethi yakho." + "Thola amasevisi e-Google Play" + "Nika amandla amasevisi e-Google Play" + "Lolu hlelo lokusebenza ngeke lusebenze ngaphandle nje kokuthi unike amandla amasevisi e-Google Play." + "Nika amandla amasevisi e-Google Play" + "Buyekeza amasevisi e-Google Play" + "Lolu hlelo lokusebenza ngeke lusebenze ngaphandle nje kokuthi ubuyekeze amasevisi e-Google Play." + "Indaba engaziwa yamasevisi we-Google Play" + "Amasevisi we-Google Play" + "Amasevisi we-Google Play, okungukuthi ezinye izinhlelo zakho zithembele kuwo, awasekelwe yidivayisi yakho. Sicela uxhumane nomkhiqizi ukuze uthole usizo." + "Isibuyekezo" + "Ngena ngemvume" + "Ngena ngemvume nge-Google" + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values/colors.xml b/MyTracks/googleplayservices_lib/src/main/res/values/colors.xml new file mode 100644 index 000000000..9d72a2c73 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values/colors.xml @@ -0,0 +1,14 @@ + + + + @android:color/white + @android:color/white + #FFAAAAAA + @android:color/white + #FF737373 + @android:color/white + #FFAAAAAA + #FF737373 + #FFDD4B39 + #d2d2d2 + \ No newline at end of file diff --git a/MyTracks/googleplayservices_lib/src/main/res/values/maps_attrs.xml b/MyTracks/googleplayservices_lib/src/main/res/values/maps_attrs.xml new file mode 100644 index 000000000..aaf65c529 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values/maps_attrs.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MyTracks/googleplayservices_lib/src/main/res/values/strings.xml b/MyTracks/googleplayservices_lib/src/main/res/values/strings.xml new file mode 100644 index 000000000..64f2bd049 --- /dev/null +++ b/MyTracks/googleplayservices_lib/src/main/res/values/strings.xml @@ -0,0 +1,88 @@ + + + + + Get Google Play services + + + This app won\'t run without Google Play services, which are missing from your phone. + + + This app won\'t run without Google Play services, which are missing from your tablet. + + + Get Google Play services + + + Enable Google Play services + + + This app won\'t work unless you enable Google Play services. + + + Enable Google Play services + + + Update Google Play services + + + This app won\'t run unless you update Google Play services. + + + Unknown issue with Google Play services. + + + Google Play services + + + Google Play services, which some of your applications rely on, is not supported by your device. Please contact the manufacturer for assistance. + + + Update + + + Sign in + + + Sign in with Google + + + + Install/Update/Enable Google Play services + + + Google Play services error + + + Requested by %1$s + + + + + + + + + AgeUnder13 + + AgeUnknown + + UnknownRestriction + + + + diff --git a/MyTracks/gradle/wrapper/gradle-wrapper.jar b/MyTracks/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..05ef575b0 Binary files /dev/null and b/MyTracks/gradle/wrapper/gradle-wrapper.jar differ diff --git a/MyTracks/gradle/wrapper/gradle-wrapper.properties b/MyTracks/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..f23df6e46 --- /dev/null +++ b/MyTracks/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Wed Oct 21 11:34:03 PDT 2015 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip diff --git a/MyTracks/gradlew b/MyTracks/gradlew new file mode 100644 index 000000000..9d82f7891 --- /dev/null +++ b/MyTracks/gradlew @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/MyTracks/gradlew.bat b/MyTracks/gradlew.bat new file mode 100644 index 000000000..aec99730b --- /dev/null +++ b/MyTracks/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/MyTracks/libs/README.txt b/MyTracks/libs/README.txt deleted file mode 100644 index 35a849f96..000000000 --- a/MyTracks/libs/README.txt +++ /dev/null @@ -1,43 +0,0 @@ -The libraries contained here in binary format are licensed according to their -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. - -Android Support Package: -android-support-v4.jar (version 13) - -Ant+: -antlib.jar - from Android_ANT_SDK_20120625.zip - -Google APIs Client Library for Java: -google-api-client-1.12.0-beta.jar -google-api-client-android-1.12.0-beta.jar -google-api-services-drive-v2-rev30-1.12.0-beta.jar -google-api-services-fusiontables-v1-rev16-1.12.0-beta.jar -google-http-client-1.12.0-beta.jar -google-http-client-android-1.12.0-beta.jar -google-http-client-gson-1.12.0-beta.jar -google-http-client-jackson-1.12.0-beta.jar -google-http-client-jackson2-1.12.0-beta.jar -google-oauth-client-1.12.0-beta.jar -gson-2.1.jar -jackson-core-2.0.5.jar -jackson-core-asl-1.9.9.jar - -Google GData API: -gdata-client-1.0.jar -gdata-client-meta-1.0.jar -gdata-core-1.0.jar -gdata-spreadsheet-3.0.jar -gdata-spreadsheet-meta-3.0.jar - -Google API Client Library for Java and Google GData API: -guava-jdk5-13.0.jar -jsr305.jar - -Google Analytics: -libGoogleAnalytics.jar -- see http://code.google.com/apis/analytics/docs/mobile/android.html - -Google Common: -google-common.jar \ No newline at end of file diff --git a/MyTracks/libs/gdata-client-1.0.jar b/MyTracks/libs/gdata-client-1.0.jar deleted file mode 100644 index 2ae38cc66..000000000 Binary files a/MyTracks/libs/gdata-client-1.0.jar and /dev/null differ diff --git a/MyTracks/libs/gdata-spreadsheet-3.0.jar b/MyTracks/libs/gdata-spreadsheet-3.0.jar deleted file mode 100644 index 85fb7c85f..000000000 Binary files a/MyTracks/libs/gdata-spreadsheet-3.0.jar and /dev/null differ diff --git a/MyTracks/libs/gdata-spreadsheet-meta-3.0.jar b/MyTracks/libs/gdata-spreadsheet-meta-3.0.jar deleted file mode 100644 index 7babe6c66..000000000 Binary files a/MyTracks/libs/gdata-spreadsheet-meta-3.0.jar and /dev/null differ diff --git a/MyTracks/libs/google-api-client-1.12.0-beta.jar b/MyTracks/libs/google-api-client-1.12.0-beta.jar deleted file mode 100644 index c85862626..000000000 Binary files a/MyTracks/libs/google-api-client-1.12.0-beta.jar and /dev/null differ diff --git a/MyTracks/libs/google-api-client-android-1.12.0-beta.jar b/MyTracks/libs/google-api-client-android-1.12.0-beta.jar deleted file mode 100644 index cb7cfe8bc..000000000 Binary files a/MyTracks/libs/google-api-client-android-1.12.0-beta.jar and /dev/null differ diff --git a/MyTracks/libs/google-api-services-drive-v2-rev30-1.12.0-beta.jar b/MyTracks/libs/google-api-services-drive-v2-rev30-1.12.0-beta.jar deleted file mode 100644 index 6e17009b4..000000000 Binary files a/MyTracks/libs/google-api-services-drive-v2-rev30-1.12.0-beta.jar and /dev/null differ diff --git a/MyTracks/libs/google-api-services-fusiontables-v1-rev16-1.12.0-beta.jar b/MyTracks/libs/google-api-services-fusiontables-v1-rev16-1.12.0-beta.jar deleted file mode 100644 index 07866f15f..000000000 Binary files a/MyTracks/libs/google-api-services-fusiontables-v1-rev16-1.12.0-beta.jar and /dev/null differ diff --git a/MyTracks/libs/google-http-client-1.12.0-beta.jar b/MyTracks/libs/google-http-client-1.12.0-beta.jar deleted file mode 100644 index 6ff05049f..000000000 Binary files a/MyTracks/libs/google-http-client-1.12.0-beta.jar and /dev/null differ diff --git a/MyTracks/libs/google-http-client-android-1.12.0-beta.jar b/MyTracks/libs/google-http-client-android-1.12.0-beta.jar deleted file mode 100644 index 1ed253346..000000000 Binary files a/MyTracks/libs/google-http-client-android-1.12.0-beta.jar and /dev/null differ diff --git a/MyTracks/libs/google-http-client-gson-1.12.0-beta.jar b/MyTracks/libs/google-http-client-gson-1.12.0-beta.jar deleted file mode 100644 index 7a2e064e7..000000000 Binary files a/MyTracks/libs/google-http-client-gson-1.12.0-beta.jar and /dev/null differ diff --git a/MyTracks/libs/google-http-client-jackson-1.12.0-beta.jar b/MyTracks/libs/google-http-client-jackson-1.12.0-beta.jar deleted file mode 100644 index 52c2209d9..000000000 Binary files a/MyTracks/libs/google-http-client-jackson-1.12.0-beta.jar and /dev/null differ diff --git a/MyTracks/libs/google-http-client-jackson2-1.12.0-beta.jar b/MyTracks/libs/google-http-client-jackson2-1.12.0-beta.jar deleted file mode 100644 index 9415c7b23..000000000 Binary files a/MyTracks/libs/google-http-client-jackson2-1.12.0-beta.jar and /dev/null differ diff --git a/MyTracks/libs/google-oauth-client-1.12.0-beta.jar b/MyTracks/libs/google-oauth-client-1.12.0-beta.jar deleted file mode 100644 index dad2abe4f..000000000 Binary files a/MyTracks/libs/google-oauth-client-1.12.0-beta.jar and /dev/null differ diff --git a/MyTracks/libs/gson-2.1.jar b/MyTracks/libs/gson-2.1.jar deleted file mode 100644 index 83c5c994b..000000000 Binary files a/MyTracks/libs/gson-2.1.jar and /dev/null differ diff --git a/MyTracks/libs/guava-jdk5-13.0.jar b/MyTracks/libs/guava-jdk5-13.0.jar deleted file mode 100644 index 85881e5de..000000000 Binary files a/MyTracks/libs/guava-jdk5-13.0.jar and /dev/null differ diff --git a/MyTracks/libs/jackson-core-2.0.5.jar b/MyTracks/libs/jackson-core-2.0.5.jar deleted file mode 100644 index 51d1fdeb4..000000000 Binary files a/MyTracks/libs/jackson-core-2.0.5.jar and /dev/null differ diff --git a/MyTracks/libs/jackson-core-asl-1.9.9.jar b/MyTracks/libs/jackson-core-asl-1.9.9.jar deleted file mode 100644 index d75843d1c..000000000 Binary files a/MyTracks/libs/jackson-core-asl-1.9.9.jar and /dev/null differ diff --git a/MyTracks/libs/jsr305.jar b/MyTracks/libs/jsr305.jar deleted file mode 100644 index cf5f56167..000000000 Binary files a/MyTracks/libs/jsr305.jar and /dev/null differ diff --git a/MyTracks/local.properties b/MyTracks/local.properties new file mode 100644 index 000000000..ac7c16536 --- /dev/null +++ b/MyTracks/local.properties @@ -0,0 +1,7 @@ +## This file must *NOT* be checked into Version Control Systems, +# as it contains information specific to your local configuration. +# +# Location of the SDK. This is only used by Gradle. +# +#Tue Feb 16 19:46:56 CET 2016 +sdk.dir=C\:\\Users\\Clems\\AppData\\Local\\Android\\Sdk diff --git a/MyTracks/myTracks/build.gradle b/MyTracks/myTracks/build.gradle new file mode 100644 index 000000000..2636bbc03 --- /dev/null +++ b/MyTracks/myTracks/build.gradle @@ -0,0 +1,53 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 17 + buildToolsVersion "23.0.2" + + defaultConfig { + applicationId "com.google.android.maps.mytracks" + minSdkVersion 8 + targetSdkVersion 19 + + testApplicationId "com.google.android.maps.mytracks.test" + testInstrumentationRunner "android.test.InstrumentationTestRunner" + } + + buildTypes { + release { + minifyEnabled true + proguardFiles 'proguard.cfg', 'proguard-google-api-client.txt' + } + } +} + +dependencies { + compile project(':myTracksLib') + compile project(':googleplayservices_lib') + compile files('libs/android-support-v4.jar') + compile files('libs/antlib.jar') + compile files('libs/gdata-client-1.0.jar') + compile files('libs/gdata-client-meta-1.0.jar') + compile files('libs/gdata-core-1.0.jar') + compile files('libs/gdata-spreadsheet-3.0.jar') + compile files('libs/gdata-spreadsheet-meta-3.0.jar') + compile files('libs/google-api-client-1.12.0-beta.jar') + compile files('libs/google-api-client-android-1.12.0-beta.jar') + compile files('libs/google-api-services-drive-v2-rev30-1.12.0-beta.jar') + compile files('libs/google-api-services-fusiontables-v1-rev16-1.12.0-beta.jar') + compile files('libs/google-common.jar') + compile files('libs/google-http-client-1.12.0-beta.jar') + compile files('libs/google-http-client-android-1.12.0-beta.jar') + compile files('libs/google-http-client-gson-1.12.0-beta.jar') + compile files('libs/google-http-client-jackson-1.12.0-beta.jar') + compile files('libs/google-http-client-jackson2-1.12.0-beta.jar') + compile files('libs/google-oauth-client-1.12.0-beta.jar') + compile files('libs/gson-2.1.jar') + compile files('libs/guava-jdk5-13.0.jar') + compile files('libs/jackson-core-2.0.5.jar') + compile files('libs/jackson-core-asl-1.9.9.jar') + compile files('libs/jsr305.jar') + compile files('libs/libGoogleAnalytics.jar') + androidTestCompile files('libs/AndroidMockGenerator.jar') + androidTestCompile files('libs/robotium-solo-3.3.jar') +} diff --git a/MyTracks/myTracks/libs/AndroidMockGenerator.jar b/MyTracks/myTracks/libs/AndroidMockGenerator.jar new file mode 100644 index 000000000..ef8b3612c Binary files /dev/null and b/MyTracks/myTracks/libs/AndroidMockGenerator.jar differ diff --git a/MyTracks/libs/android-support-v4.jar b/MyTracks/myTracks/libs/android-support-v4.jar similarity index 100% rename from MyTracks/libs/android-support-v4.jar rename to MyTracks/myTracks/libs/android-support-v4.jar diff --git a/MyTracks/libs/antlib.jar b/MyTracks/myTracks/libs/antlib.jar similarity index 100% rename from MyTracks/libs/antlib.jar rename to MyTracks/myTracks/libs/antlib.jar diff --git a/MyTracks/.google_apis/gdata-spreadsheet-2.1/gdata-spreadsheet-3.0/gdata-client-1.0.jar b/MyTracks/myTracks/libs/gdata-client-1.0.jar similarity index 100% rename from MyTracks/.google_apis/gdata-spreadsheet-2.1/gdata-spreadsheet-3.0/gdata-client-1.0.jar rename to MyTracks/myTracks/libs/gdata-client-1.0.jar diff --git a/MyTracks/libs/gdata-client-meta-1.0.jar b/MyTracks/myTracks/libs/gdata-client-meta-1.0.jar similarity index 100% rename from MyTracks/libs/gdata-client-meta-1.0.jar rename to MyTracks/myTracks/libs/gdata-client-meta-1.0.jar diff --git a/MyTracks/libs/gdata-core-1.0.jar b/MyTracks/myTracks/libs/gdata-core-1.0.jar similarity index 100% rename from MyTracks/libs/gdata-core-1.0.jar rename to MyTracks/myTracks/libs/gdata-core-1.0.jar diff --git a/MyTracks/.google_apis/gdata-spreadsheet-2.1/gdata-spreadsheet-3.0/gdata-spreadsheet-3.0.jar b/MyTracks/myTracks/libs/gdata-spreadsheet-3.0.jar similarity index 100% rename from MyTracks/.google_apis/gdata-spreadsheet-2.1/gdata-spreadsheet-3.0/gdata-spreadsheet-3.0.jar rename to MyTracks/myTracks/libs/gdata-spreadsheet-3.0.jar diff --git a/MyTracks/.google_apis/gdata-spreadsheet-2.1/gdata-spreadsheet-3.0/gdata-spreadsheet-meta-3.0.jar b/MyTracks/myTracks/libs/gdata-spreadsheet-meta-3.0.jar similarity index 100% rename from MyTracks/.google_apis/gdata-spreadsheet-2.1/gdata-spreadsheet-3.0/gdata-spreadsheet-meta-3.0.jar rename to MyTracks/myTracks/libs/gdata-spreadsheet-meta-3.0.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-api-client-1.12.0-beta.jar b/MyTracks/myTracks/libs/google-api-client-1.12.0-beta.jar similarity index 100% rename from MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-api-client-1.12.0-beta.jar rename to MyTracks/myTracks/libs/google-api-client-1.12.0-beta.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-api-client-android-1.12.0-beta.jar b/MyTracks/myTracks/libs/google-api-client-android-1.12.0-beta.jar similarity index 100% rename from MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-api-client-android-1.12.0-beta.jar rename to MyTracks/myTracks/libs/google-api-client-android-1.12.0-beta.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/google-api-services-drive-v2-rev30-1.12.0-beta.jar b/MyTracks/myTracks/libs/google-api-services-drive-v2-rev30-1.12.0-beta.jar similarity index 100% rename from MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/google-api-services-drive-v2-rev30-1.12.0-beta.jar rename to MyTracks/myTracks/libs/google-api-services-drive-v2-rev30-1.12.0-beta.jar diff --git a/MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/google-api-services-fusiontables-v1-rev16-1.12.0-beta.jar b/MyTracks/myTracks/libs/google-api-services-fusiontables-v1-rev16-1.12.0-beta.jar similarity index 100% rename from MyTracks/.google_apis/fusiontables-v1r16lv1.12.0-beta/fusiontables/google-api-services-fusiontables-v1-rev16-1.12.0-beta.jar rename to MyTracks/myTracks/libs/google-api-services-fusiontables-v1-rev16-1.12.0-beta.jar diff --git a/MyTracks/libs/google-common.jar b/MyTracks/myTracks/libs/google-common.jar similarity index 100% rename from MyTracks/libs/google-common.jar rename to MyTracks/myTracks/libs/google-common.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-http-client-1.12.0-beta.jar b/MyTracks/myTracks/libs/google-http-client-1.12.0-beta.jar similarity index 100% rename from MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-http-client-1.12.0-beta.jar rename to MyTracks/myTracks/libs/google-http-client-1.12.0-beta.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-http-client-android-1.12.0-beta.jar b/MyTracks/myTracks/libs/google-http-client-android-1.12.0-beta.jar similarity index 100% rename from MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-http-client-android-1.12.0-beta.jar rename to MyTracks/myTracks/libs/google-http-client-android-1.12.0-beta.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-http-client-gson-1.12.0-beta.jar b/MyTracks/myTracks/libs/google-http-client-gson-1.12.0-beta.jar similarity index 100% rename from MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-http-client-gson-1.12.0-beta.jar rename to MyTracks/myTracks/libs/google-http-client-gson-1.12.0-beta.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-http-client-jackson-1.12.0-beta.jar b/MyTracks/myTracks/libs/google-http-client-jackson-1.12.0-beta.jar similarity index 100% rename from MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-http-client-jackson-1.12.0-beta.jar rename to MyTracks/myTracks/libs/google-http-client-jackson-1.12.0-beta.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-http-client-jackson2-1.12.0-beta.jar b/MyTracks/myTracks/libs/google-http-client-jackson2-1.12.0-beta.jar similarity index 100% rename from MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-http-client-jackson2-1.12.0-beta.jar rename to MyTracks/myTracks/libs/google-http-client-jackson2-1.12.0-beta.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-oauth-client-1.12.0-beta.jar b/MyTracks/myTracks/libs/google-oauth-client-1.12.0-beta.jar similarity index 100% rename from MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/google-oauth-client-1.12.0-beta.jar rename to MyTracks/myTracks/libs/google-oauth-client-1.12.0-beta.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/gson-2.1.jar b/MyTracks/myTracks/libs/gson-2.1.jar similarity index 100% rename from MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/gson-2.1.jar rename to MyTracks/myTracks/libs/gson-2.1.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/guava-jdk5-13.0.jar b/MyTracks/myTracks/libs/guava-jdk5-13.0.jar similarity index 100% rename from MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/guava-jdk5-13.0.jar rename to MyTracks/myTracks/libs/guava-jdk5-13.0.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/jackson-core-2.0.5.jar b/MyTracks/myTracks/libs/jackson-core-2.0.5.jar similarity index 100% rename from MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/jackson-core-2.0.5.jar rename to MyTracks/myTracks/libs/jackson-core-2.0.5.jar diff --git a/MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/jackson-core-asl-1.9.9.jar b/MyTracks/myTracks/libs/jackson-core-asl-1.9.9.jar similarity index 100% rename from MyTracks/.google_apis/drive-v2r30lv1.12.0-beta/drive/libs/jackson-core-asl-1.9.9.jar rename to MyTracks/myTracks/libs/jackson-core-asl-1.9.9.jar diff --git a/MyTracks/.google_apis/gdata-spreadsheet-2.1/gdata-spreadsheet-3.0/jsr305.jar b/MyTracks/myTracks/libs/jsr305.jar similarity index 100% rename from MyTracks/.google_apis/gdata-spreadsheet-2.1/gdata-spreadsheet-3.0/jsr305.jar rename to MyTracks/myTracks/libs/jsr305.jar diff --git a/MyTracks/libs/libGoogleAnalytics.jar b/MyTracks/myTracks/libs/libGoogleAnalytics.jar similarity index 100% rename from MyTracks/libs/libGoogleAnalytics.jar rename to MyTracks/myTracks/libs/libGoogleAnalytics.jar diff --git a/MyTracks/myTracks/libs/robotium-solo-3.3.jar b/MyTracks/myTracks/libs/robotium-solo-3.3.jar new file mode 100644 index 000000000..0fd942110 Binary files /dev/null and b/MyTracks/myTracks/libs/robotium-solo-3.3.jar differ diff --git a/MyTracks/lint.xml b/MyTracks/myTracks/lint.xml similarity index 95% rename from MyTracks/lint.xml rename to MyTracks/myTracks/lint.xml index 5003301c4..792ee5c02 100644 --- a/MyTracks/lint.xml +++ b/MyTracks/myTracks/lint.xml @@ -1,4 +1,4 @@ - + diff --git a/MyTracks/myTracks/myTracks.iml b/MyTracks/myTracks/myTracks.iml new file mode 100644 index 000000000..a7b1aea20 --- /dev/null +++ b/MyTracks/myTracks/myTracks.iml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MyTracks/proguard-google-api-client.txt b/MyTracks/myTracks/proguard-google-api-client.txt similarity index 100% rename from MyTracks/proguard-google-api-client.txt rename to MyTracks/myTracks/proguard-google-api-client.txt diff --git a/MyTracks/proguard.cfg b/MyTracks/myTracks/proguard.cfg similarity index 100% rename from MyTracks/proguard.cfg rename to MyTracks/myTracks/proguard.cfg diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/BootReceiverTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/BootReceiverTest.java new file mode 100644 index 000000000..9c70a7af6 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/BootReceiverTest.java @@ -0,0 +1,91 @@ +/* + * Copyright 2012 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.services.TrackRecordingService; + +import android.app.ActivityManager; +import android.app.ActivityManager.RunningServiceInfo; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.test.AndroidTestCase; + +import java.util.List; + +/** + * Tests for the BootReceiver. + * + * @author Youtao Liu + */ +public class BootReceiverTest extends AndroidTestCase { + private static final String SERVICE_NAME = "com.google.android.apps.mytracks.services.TrackRecordingService"; + + /** + * Tests the behavior when receive notification which is the phone boot. + */ + public void testOnReceive_startService() { + // Make sure no TrackRecordingService + Intent stopIntent = new Intent(getContext(), TrackRecordingService.class); + getContext().stopService(stopIntent); + assertFalse(isServiceExisted(getContext(), SERVICE_NAME)); + + BootReceiver bootReceiver = new BootReceiver(); + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_BOOT_COMPLETED); + bootReceiver.onReceive(getContext(), intent); + // Check if the service is started + assertTrue(isServiceExisted(getContext(), SERVICE_NAME)); + } + + /** + * Tests the behavior when receive notification which is not the phone boot. + */ + public void testOnReceive_noStartService() { + // Make sure no TrackRecordingService + Intent stopIntent = new Intent(getContext(), TrackRecordingService.class); + getContext().stopService(stopIntent); + assertFalse(isServiceExisted(getContext(), SERVICE_NAME)); + + BootReceiver bootReceiver = new BootReceiver(); + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_BUG_REPORT); + bootReceiver.onReceive(getContext(), intent); + // Check if the service is not started + assertFalse(isServiceExisted(getContext(), SERVICE_NAME)); + } + + /** + * Checks if a service is started in a context. + * + * @param context the context for checking a service + * @param serviceName the service name to find if existed + */ + private boolean isServiceExisted(Context context, String serviceName) { + ActivityManager activityManager = (ActivityManager) context + .getSystemService(Context.ACTIVITY_SERVICE); + List serviceList = activityManager + .getRunningServices(Integer.MAX_VALUE); + for (int i = 0; i < serviceList.size(); i++) { + RunningServiceInfo serviceInfo = serviceList.get(i); + ComponentName componentName = serviceInfo.service; + if (componentName.getClassName().equals(serviceName)) { + return true; + } + } + return false; + } +} \ No newline at end of file diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/ChartValueSeriesTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/ChartValueSeriesTest.java new file mode 100644 index 000000000..22ce64224 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/ChartValueSeriesTest.java @@ -0,0 +1,80 @@ +/* + * 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. + */ +package com.google.android.apps.mytracks; + +import com.google.android.maps.mytracks.R; + +import android.test.AndroidTestCase; + +/** + * Tests {@link ChartValueSeries}. + * + * @author Sandor Dornbush + */ +public class ChartValueSeriesTest extends AndroidTestCase { + private ChartValueSeries series; + + @Override + protected void setUp() throws Exception { + series = new ChartValueSeries(getContext(), + Integer.MIN_VALUE, + Integer.MAX_VALUE, + new int[] {100, 1000 }, + R.string.description_elevation_metric, + R.string.description_elevation_imperial, + R.color.chart_elevation_fill, + R.color.chart_elevation_border); + } + + public void testInitialConditions() { + assertEquals(1, series.getInterval()); + assertEquals(0, series.getMinMarkerValue()); + assertEquals(5, series.getMaxMarkerValue()); + assertTrue(series.isEnabled()); + } + + public void testEnabled() { + series.setEnabled(false); + assertFalse(series.isEnabled()); + } + + public void testSmallUpdates() { + series.update(0); + series.update(10); + series.updateDimension(); + assertEquals(100, series.getInterval()); + assertEquals(0, series.getMinMarkerValue()); + assertEquals(500, series.getMaxMarkerValue()); + } + + public void testBigUpdates() { + series.update(0); + series.update(901); + series.updateDimension(); + assertEquals(1000, series.getInterval()); + assertEquals(0, series.getMinMarkerValue()); + assertEquals(5000, series.getMaxMarkerValue()); + } + + public void testNotZeroBasedUpdates() { + series.update(220); + series.update(250); + series.updateDimension(); + assertEquals(100, series.getInterval()); + assertEquals(200, series.getMinMarkerValue()); + assertEquals(700, series.getMaxMarkerValue()); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/TrackStubUtils.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/TrackStubUtils.java new file mode 100644 index 000000000..ea0ac573f --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/TrackStubUtils.java @@ -0,0 +1,91 @@ +/* + * Copyright 2012 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.MyTracksLocation; +import com.google.android.apps.mytracks.content.Sensor.SensorDataSet; +import com.google.android.apps.mytracks.content.Track; + +import android.location.Location; + +/** + * Commons utilities for creating stubs of track, location. The class will be + * enriched if needs more similar stubs for test. + * + * @author Youtao Liu + */ +public class TrackStubUtils { + + static final String LOCATION_PROVIDER = "gps"; + public static final double INITIAL_LATITUDE = 22; + public static final double INITIAL_LONGITUDE = 22; + public static final double INITIAL_ALTITUDE = 22; + static final float INITIAL_ACCURACY = 5; + static final float INITIAL_SPEED = 10; + public static final long INITIAL_TIME = 1000L; + static final float INITIAL_BEARING = 3.0f; + // Used to change the value of latitude, longitude, and altitude. + static final double DIFFERENCE = 0.01; + + /** + * Gets a a {@link Track} stub with specified number of locations. + * + * @param numberOfLocations the number of locations for the track + * @return a track stub. + */ + public static Track createTrack(int numberOfLocations) { + Track track = new Track(); + for (int i = 0; i < numberOfLocations; i++) { + track.addLocation(createMyTracksLocation(INITIAL_LATITUDE + i * DIFFERENCE, INITIAL_LONGITUDE + + i * DIFFERENCE, INITIAL_ALTITUDE + i * DIFFERENCE)); + } + + return track; + } + + /** + * Create a MyTracks location with default values. + * + * @return a track stub. + */ + public static MyTracksLocation createMyTracksLocation() { + return createMyTracksLocation(INITIAL_LATITUDE, INITIAL_LONGITUDE, INITIAL_ALTITUDE); + } + + /** + * Creates a {@link MyTracksLocation} stub with specified values. + * + * @return a MyTracksLocation stub. + */ + public static MyTracksLocation createMyTracksLocation(double latitude, double longitude, + double altitude) { + // Initial Location + Location loc = new Location(LOCATION_PROVIDER); + loc.setLatitude(latitude); + loc.setLongitude(longitude); + loc.setAltitude(altitude); + loc.setAccuracy(INITIAL_ACCURACY); + loc.setSpeed(INITIAL_SPEED); + loc.setTime(INITIAL_TIME); + loc.setBearing(INITIAL_BEARING); + SensorDataSet sd = SensorDataSet.newBuilder().build(); + MyTracksLocation myTracksLocation = new MyTracksLocation(loc, sd); + + return myTracksLocation; + } + +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/content/DescriptionGeneratorImplTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/content/DescriptionGeneratorImplTest.java new file mode 100644 index 000000000..2542881ca --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/content/DescriptionGeneratorImplTest.java @@ -0,0 +1,198 @@ +/* + * Copyright 2012 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.android.apps.mytracks.content; + +import com.google.android.apps.mytracks.stats.TripStatistics; +import com.google.android.apps.mytracks.util.StringUtils; +import com.google.android.maps.mytracks.R; + +import android.test.AndroidTestCase; + +/** + * Tests for {@link DescriptionGeneratorImpl}. + * + * @author Jimmy Shih + */ +public class DescriptionGeneratorImplTest extends AndroidTestCase { + + private static final long START_TIME = 1288721514000L; + private DescriptionGeneratorImpl descriptionGenerator; + + @Override + protected void setUp() throws Exception { + descriptionGenerator = new DescriptionGeneratorImpl(getContext()); + } + + /** + * Tests {@link DescriptionGeneratorImpl#generateTrackDescription(Track, + * java.util.Vector, java.util.Vector, boolean)}. + */ + public void testGenerateTrackDescription() { + Track track = new Track(); + TripStatistics stats = new TripStatistics(); + stats.setTotalDistance(20000); + stats.setTotalTime(600000); + stats.setMovingTime(300000); + stats.setMaxSpeed(100); + stats.setMaxElevation(550); + stats.setMinElevation(-500); + stats.setTotalElevationGain(6000); + stats.setMaxGrade(0.42); + stats.setMinGrade(0.11); + stats.setStartTime(START_TIME); + track.setTripStatistics(stats); + track.setCategory("hiking"); + String expected = "Created by" + + " Google My Tracks on Android

" + + "Name: -
" + + "Activity type: hiking
" + + "Description: -
" + + "Total distance: 20.00 km (12.4 mi)
" + + "Total time: 10:00
" + + "Moving time: 05:00
" + + "Average speed: 120.00 km/h (74.6 mi/h)
" + + "Average moving speed: 240.00 km/h (149.1 mi/h)
" + + "Max speed: 360.00 km/h (223.7 mi/h)
" + + "Average pace: 0:30 min/km (0:48 min/mi)
" + + "Average moving pace: 0:15 min/km (0:24 min/mi)
" + + "Fastest pace: 0:10 min/km (0:16 min/mi)
" + + "Max elevation: 550 m (1804 ft)
" + + "Min elevation: -500 m (-1640 ft)
" + + "Elevation gain: 6000 m (19685 ft)
" + + "Max grade: 42 %
" + + "Min grade: 11 %
" + + "Recorded: " + StringUtils.formatDateTime(getContext(), START_TIME) + "
"; + assertEquals(expected, descriptionGenerator.generateTrackDescription(track, null, null, true)); + } + + /** + * Tests {@link DescriptionGeneratorImpl#generateWaypointDescription(TripStatistics)}. + */ + public void testGenerateWaypointDescription() { + Waypoint waypoint = new Waypoint(); + TripStatistics stats = new TripStatistics(); + stats.setTotalDistance(20000); + stats.setTotalTime(600000); + stats.setMovingTime(300000); + stats.setMaxSpeed(100); + stats.setMaxElevation(550); + stats.setMinElevation(-500); + stats.setTotalElevationGain(6000); + stats.setMaxGrade(0.42); + stats.setMinGrade(0.11); + stats.setStartTime(START_TIME); + waypoint.setTripStatistics(stats); + String expected = "Total distance: 20.00 km (12.4 mi)\n" + + "Total time: 10:00\n" + + "Moving time: 05:00\n" + + "Average speed: 120.00 km/h (74.6 mi/h)\n" + + "Average moving speed: 240.00 km/h (149.1 mi/h)\n" + + "Max speed: 360.00 km/h (223.7 mi/h)\n" + + "Average pace: 0:30 min/km (0:48 min/mi)\n" + + "Average moving pace: 0:15 min/km (0:24 min/mi)\n" + + "Fastest pace: 0:10 min/km (0:16 min/mi)\n" + + "Max elevation: 550 m (1804 ft)\n" + + "Min elevation: -500 m (-1640 ft)\n" + + "Elevation gain: 6000 m (19685 ft)\n" + + "Max grade: 42 %\n" + + "Min grade: 11 %\n" + + "Recorded: " + StringUtils.formatDateTime(getContext(), START_TIME) + "\n"; + assertEquals( + expected, descriptionGenerator.generateWaypointDescription(waypoint.getTripStatistics())); + } + + /** + * Tests {@link DescriptionGeneratorImpl#writeDistance(double, StringBuilder, + * int, String)}. + */ + public void testWriteDistance() { + StringBuilder builder = new StringBuilder(); + descriptionGenerator.writeDistance(1100, builder, R.string.description_total_distance, "
"); + assertEquals("Total distance: 1.10 km (0.7 mi)
", builder.toString()); + } + + /** + * Tests {@link DescriptionGeneratorImpl#writeTime(long, StringBuilder, int, + * String)}. + */ + public void testWriteTime() { + StringBuilder builder = new StringBuilder(); + descriptionGenerator.writeTime(1000, builder, R.string.description_total_time, "
"); + assertEquals("Total time: 00:01
", builder.toString()); + } + + /** + * Tests {@link DescriptionGeneratorImpl#writeSpeed(double, StringBuilder, + * int, String)}. + */ + public void testWriteSpeed() { + StringBuilder builder = new StringBuilder(); + descriptionGenerator.writeSpeed(1.1, builder, R.string.description_average_speed, "\n"); + assertEquals("Average speed: 3.96 km/h (2.5 mi/h)\n", builder.toString()); + } + + /** + * Tests {@link DescriptionGeneratorImpl#writeElevation(double, StringBuilder, + * int, String)}. + */ + public void testWriteElevation() { + StringBuilder builder = new StringBuilder(); + descriptionGenerator.writeElevation(4.2, builder, R.string.description_min_elevation, "
"); + assertEquals("Min elevation: 4 m (14 ft)
", builder.toString()); + } + + /** + * Tests {@link DescriptionGeneratorImpl#writePace(double, StringBuilder, int, + * String)}. + */ + public void testWritePace() { + StringBuilder builder = new StringBuilder(); + descriptionGenerator.writePace(1.1, builder, R.string.description_average_pace_in_minute, "\n"); + assertEquals("Average pace: 15:09 min/km (24:23 min/mi)\n", builder.toString()); + } + + /** + * Tests {@link DescriptionGeneratorImpl#writeGrade(double, StringBuilder, + * int, String)}. + */ + public void testWriteGrade() { + StringBuilder builder = new StringBuilder(); + descriptionGenerator.writeGrade(.042, builder, R.string.description_max_grade, "
"); + assertEquals("Max grade: 4 %
", builder.toString()); + } + + /** + * Tests {@link DescriptionGeneratorImpl#writeGrade(double, StringBuilder, + * int, String)} with a NaN. + */ + public void testWriteGrade_nan() { + StringBuilder builder = new StringBuilder(); + descriptionGenerator.writeGrade(Double.NaN, builder, R.string.description_max_grade, "
"); + assertEquals("Max grade: 0 %
", builder.toString()); + } + + /** + * Tests {@link DescriptionGeneratorImpl#writeGrade(double, StringBuilder, + * int, String)} with an infinite number. + */ + public void testWriteGrade_infinite() { + StringBuilder builder = new StringBuilder(); + descriptionGenerator.writeGrade( + Double.POSITIVE_INFINITY, builder, R.string.description_max_grade, "
"); + assertEquals("Max grade: 0 %
", builder.toString()); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/content/MyTracksProviderTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/content/MyTracksProviderTest.java new file mode 100644 index 000000000..75fb116ab --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/content/MyTracksProviderTest.java @@ -0,0 +1,263 @@ +/* + * Copyright 2012 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.android.apps.mytracks.content; + +import com.google.android.apps.mytracks.content.MyTracksProvider.DatabaseHelper; + +import android.database.sqlite.SQLiteDatabase; +import android.net.Uri; +import android.test.AndroidTestCase; + +/** + * Tests {@link MyTracksProvider}. + * + * @author Youtao Liu + */ +public class MyTracksProviderTest extends AndroidTestCase { + + private static final String DATABASE_NAME = "mytrackstest.db"; + + private SQLiteDatabase db; + private MyTracksProvider myTracksProvider; + + @Override + protected void setUp() throws Exception { + super.setUp(); + getContext().deleteDatabase(DATABASE_NAME); + db = (new DatabaseHelper(getContext(), DATABASE_NAME)).getWritableDatabase(); + myTracksProvider = new MyTracksProvider(); + } + + /** + * Tests {@link MyTracksProvider.DatabaseHelper#onCreate(SQLiteDatabase)}. + */ + public void testDatabaseHelper_OnCreate() { + assertTrue(hasTable(TracksColumns.TABLE_NAME)); + assertTrue(hasTable(TrackPointsColumns.TABLE_NAME)); + assertTrue(hasTable(WaypointsColumns.TABLE_NAME)); + } + + /** + * Tests {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int, + * int)} when version is less than 17. + */ + public void testDatabaseHelper_onUpgrade_Version16() { + dropTable(TracksColumns.TABLE_NAME); + dropTable(TrackPointsColumns.TABLE_NAME); + dropTable(WaypointsColumns.TABLE_NAME); + + int oldVersion = 16; + DatabaseHelper databaseHelper = new DatabaseHelper(getContext()); + databaseHelper.onUpgrade(db, oldVersion, MyTracksProvider.DATABASE_VERSION); + + assertTrue(hasTable(TracksColumns.TABLE_NAME)); + assertTrue(hasTable(TrackPointsColumns.TABLE_NAME)); + assertTrue(hasTable(WaypointsColumns.TABLE_NAME)); + } + + /** + * Tests {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int, + * int)} when version is 17. + */ + public void testDatabaseHelper_onUpgrade_Version17() { + setupUpgrade(17); + + assertTrue(hasColumn(TrackPointsColumns.TABLE_NAME, TrackPointsColumns.SENSOR)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.TABLEID)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.ICON)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.DRIVEID)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.MODIFIEDTIME)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDWITHME)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDOWNER)); + assertTrue(hasColumn(WaypointsColumns.TABLE_NAME, WaypointsColumns.PHOTOURL)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.CALORIE)); + } + + /** + * Tests {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int, + * int)} when version is 18. + */ + public void testDatabaseHelper_onUpgrade_Version18() { + setupUpgrade(18); + + assertFalse(hasColumn(TrackPointsColumns.TABLE_NAME, TrackPointsColumns.SENSOR)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.TABLEID)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.ICON)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.DRIVEID)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.MODIFIEDTIME)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDWITHME)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDOWNER)); + assertTrue(hasColumn(WaypointsColumns.TABLE_NAME, WaypointsColumns.PHOTOURL)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.CALORIE)); + } + + /** + * Tests {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int, + * int)} when version is 19. + */ + public void testDatabaseHelper_onUpgrade_Version19() { + setupUpgrade(19); + + assertFalse(hasColumn(TrackPointsColumns.TABLE_NAME, TrackPointsColumns.SENSOR)); + assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.TABLEID)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.ICON)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.DRIVEID)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.MODIFIEDTIME)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDWITHME)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDOWNER)); + assertTrue(hasColumn(WaypointsColumns.TABLE_NAME, WaypointsColumns.PHOTOURL)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.CALORIE)); + } + + /** + * Tests {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int, + * int)} when version is 20. + */ + public void testDatabaseHelper_onUpgrade_Version20() { + setupUpgrade(20); + + assertFalse(hasColumn(TrackPointsColumns.TABLE_NAME, TrackPointsColumns.SENSOR)); + assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.TABLEID)); + assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.ICON)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.DRIVEID)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.MODIFIEDTIME)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDWITHME)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDOWNER)); + assertTrue(hasColumn(WaypointsColumns.TABLE_NAME, WaypointsColumns.PHOTOURL)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.CALORIE)); + } + + /** + * Tests {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int, + * int)} when version is 21. + */ + public void testDatabaseHelper_onUpgrade_Version21() { + setupUpgrade(21); + + assertFalse(hasColumn(TrackPointsColumns.TABLE_NAME, TrackPointsColumns.SENSOR)); + assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.TABLEID)); + assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.ICON)); + assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.DRIVEID)); + assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.MODIFIEDTIME)); + assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDWITHME)); + assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDOWNER)); + assertTrue(hasColumn(WaypointsColumns.TABLE_NAME, WaypointsColumns.PHOTOURL)); + assertTrue(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.CALORIE)); + } + + /** + * Tests {@link MyTracksProvider.DatabaseHelper#onUpgrade(SQLiteDatabase, int, + * int)} when version is 22. + */ + public void testDatabaseHelper_onUpgrade_Version22() { + setupUpgrade(22); + + assertFalse(hasColumn(TrackPointsColumns.TABLE_NAME, TrackPointsColumns.SENSOR)); + assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.TABLEID)); + assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.ICON)); + assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.DRIVEID)); + assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.MODIFIEDTIME)); + assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDWITHME)); + assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.SHAREDOWNER)); + assertFalse(hasColumn(WaypointsColumns.TABLE_NAME, WaypointsColumns.PHOTOURL)); + assertFalse(hasColumn(TracksColumns.TABLE_NAME, TracksColumns.CALORIE)); + } + + /** + * Tests {@link MyTracksProvider#onCreate(android.content.Context)}. + */ + public void testOnCreate() { + assertTrue(myTracksProvider.onCreate(getContext())); + } + + /** + * Tests {@link MyTracksProvider#getType(Uri)}. + */ + public void testGetType() { + assertEquals(TracksColumns.CONTENT_TYPE, myTracksProvider.getType(TracksColumns.CONTENT_URI)); + assertEquals( + TrackPointsColumns.CONTENT_TYPE, myTracksProvider.getType(TrackPointsColumns.CONTENT_URI)); + assertEquals( + WaypointsColumns.CONTENT_TYPE, myTracksProvider.getType(WaypointsColumns.CONTENT_URI)); + } + + /** + * Creates a table, containing one column. + * + * @param table the table name + */ + private void createTable(String table) { + db.execSQL("CREATE TABLE " + table + " (test INTEGER)"); + } + + /** + * Drops a table in database. + * + * @param table the table name + */ + private void dropTable(String table) { + db.execSQL("Drop TABLE " + table); + } + + /** + * Returns true if the table exists. + * + * @param table the table name + */ + private boolean hasTable(String table) { + try { + db.rawQuery("select count(*) from " + table, null); + return true; + } catch (Exception e) { + return false; + } + } + + /** + * Returns true if the column in the table exists. + * + * @param table the table name + * @param column the column name + */ + private boolean hasColumn(String table, String column) { + try { + db.execSQL("SElECT count(*) from " + table + " order by " + column); + } catch (Exception e) { + if (e.getMessage().indexOf("no such column") > -1) { + return false; + } + } + return true; + } + + /** + * Sets up upgrade. + * + * @param oldVersion thd old database version + */ + private void setupUpgrade(int oldVersion) { + dropTable(TracksColumns.TABLE_NAME); + dropTable(TrackPointsColumns.TABLE_NAME); + dropTable(WaypointsColumns.TABLE_NAME); + createTable(TracksColumns.TABLE_NAME); + createTable(TrackPointsColumns.TABLE_NAME); + createTable(WaypointsColumns.TABLE_NAME); + + DatabaseHelper databaseHelper = new DatabaseHelper(getContext()); + databaseHelper.onUpgrade(db, oldVersion, MyTracksProvider.DATABASE_VERSION); + } +} \ No newline at end of file diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/content/MyTracksProviderUtilsImplTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/content/MyTracksProviderUtilsImplTest.java new file mode 100644 index 000000000..137e9aa38 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/content/MyTracksProviderUtilsImplTest.java @@ -0,0 +1,908 @@ +/* + * 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. + */ +package com.google.android.apps.mytracks.content; + +import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationFactory; +import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator; +import com.google.android.apps.mytracks.content.Waypoint.WaypointType; +import com.google.android.apps.mytracks.services.TrackRecordingServiceTest.MockContext; +import com.google.android.apps.mytracks.stats.TripStatistics; +import com.google.android.testing.mocking.AndroidMock; +import com.google.android.testing.mocking.UsesMocks; + +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.location.Location; +import android.test.AndroidTestCase; +import android.test.RenamingDelegatingContext; +import android.test.mock.MockContentResolver; + +import java.util.ArrayList; +import java.util.List; +import java.util.Vector; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * A unit test for {@link MyTracksProviderUtilsImpl}. + * + * @author Bartlomiej Niechwiej + * @author Youtao Liu + */ +public class MyTracksProviderUtilsImplTest extends AndroidTestCase { + private Context context; + private MyTracksProviderUtils providerUtils; + + private static final String NAME_PREFIX = "test name"; + private static final String MOCK_DESC = "Mock Next Waypoint Desc!"; + private static final String TEST_DESC = "Test Desc!"; + private static final String TEST_DESC_NEW = "Test Desc new!"; + private double INITIAL_LATITUDE = 37.0; + private double INITIAL_LONGITUDE = -57.0; + private double ALTITUDE_INTERVAL = 2.5; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + MockContentResolver mockContentResolver = new MockContentResolver(); + RenamingDelegatingContext targetContext = new RenamingDelegatingContext( + getContext(), getContext(), "test."); + context = new MockContext(mockContentResolver, targetContext); + MyTracksProvider provider = new MyTracksProvider(); + provider.attachInfo(context, null); + mockContentResolver.addProvider(MyTracksProviderUtils.AUTHORITY, provider); + setContext(context); + + providerUtils = MyTracksProviderUtils.Factory.get(context); + providerUtils.deleteAllTracks(context); + } + + public void testLocationIterator_noPoints() { + testIterator(1, 0, 1, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY); + } + + public void testLocationIterator_customFactory() { + final Location location = new Location("test_location"); + final AtomicInteger counter = new AtomicInteger(); + testIterator(1, 15, 4, false, new LocationFactory() { + @Override + public Location createLocation() { + counter.incrementAndGet(); + return location; + } + }); + // Make sure we were called exactly as many times as we had track points. + assertEquals(15, counter.get()); + } + + public void testLocationIterator_nullFactory() { + try { + testIterator(1, 15, 4, false, null); + fail("Expecting IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // Expected. + } + } + + public void testLocationIterator_noBatchAscending() { + testIterator(1, 50, 100, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY); + testIterator(2, 50, 50, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY); + } + + public void testLocationIterator_noBatchDescending() { + testIterator(1, 50, 100, true, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY); + testIterator(2, 50, 50, true, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY); + } + + public void testLocationIterator_batchAscending() { + testIterator(1, 50, 11, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY); + testIterator(2, 50, 25, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY); + } + + public void testLocationIterator_batchDescending() { + testIterator(1, 50, 11, true, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY); + testIterator(2, 50, 25, true, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY); + } + + public void testLocationIterator_largeTrack() { + testIterator(1, 20000, 2000, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY); + } + + private List testIterator(long trackId, int numPoints, int batchSize, + boolean descending, LocationFactory locationFactory) { + long lastPointId = initializeTrack(trackId, numPoints); + ((MyTracksProviderUtilsImpl) providerUtils).setDefaultCursorBatchSize(batchSize); + List locations = new ArrayList(numPoints); + LocationIterator it = providerUtils.getTrackPointLocationIterator( + trackId, -1L, descending, locationFactory); + try { + while (it.hasNext()) { + Location loc = it.next(); + assertNotNull(loc); + locations.add(loc); + // Make sure the IDs are returned in the right order. + assertEquals(descending ? lastPointId - locations.size() + 1 + : lastPointId - numPoints + locations.size(), it.getLocationId()); + } + assertEquals(numPoints, locations.size()); + } finally { + it.close(); + } + return locations; + } + + private long initializeTrack(long id, int numPoints) { + Track track = new Track(); + track.setId(id); + track.setName("Test: " + id); + track.setNumberOfPoints(numPoints); + providerUtils.insertTrack(track); + track = providerUtils.getTrack(id); + assertNotNull(track); + + Location[] locations = new Location[numPoints]; + for (int i = 0; i < numPoints; ++i) { + Location loc = new Location("test"); + loc.setLatitude(37.0 + (double) i / 10000.0); + loc.setLongitude(57.0 - (double) i / 10000.0); + loc.setAccuracy((float) i / 100.0f); + loc.setAltitude(i * 2.5); + locations[i] = loc; + } + providerUtils.bulkInsertTrackPoint(locations, numPoints, id); + + // Load all inserted locations. + long lastPointId = -1; + int counter = 0; + LocationIterator it = providerUtils.getTrackPointLocationIterator(id, -1L, false, + MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY); + try { + while (it.hasNext()) { + it.next(); + lastPointId = it.getLocationId(); + counter++; + } + } finally { + it.close(); + } + + assertTrue(numPoints == 0 || lastPointId > 0); + assertEquals(numPoints, track.getNumberOfPoints()); + assertEquals(numPoints, counter); + + return lastPointId; + } + + /** + * Tests the method {@link MyTracksProviderUtilsImpl#createTrack(Cursor)}. + */ + @UsesMocks(Cursor.class) + public void testCreateTrack() { + Cursor cursorMock = AndroidMock.createNiceMock(Cursor.class); + int startColumnIndex = 1; + int columnIndex = startColumnIndex; + AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TracksColumns._ID)) + .andReturn(columnIndex++); + AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TracksColumns.NAME)).andReturn( + columnIndex++); + columnIndex = startColumnIndex; + // Id + AndroidMock.expect(cursorMock.isNull(columnIndex++)).andReturn(false); + // Name + AndroidMock.expect(cursorMock.isNull(columnIndex++)).andReturn(false); + long trackId = System.currentTimeMillis(); + columnIndex = startColumnIndex; + // Id + AndroidMock.expect(cursorMock.getLong(columnIndex++)).andReturn(trackId); + // Name + String name = NAME_PREFIX + Long.toString(trackId); + AndroidMock.expect(cursorMock.getString(columnIndex++)).andReturn(name); + AndroidMock.replay(cursorMock); + Track track = providerUtils.createTrack(cursorMock); + assertEquals(trackId, track.getId()); + assertEquals(name, track.getName()); + AndroidMock.verify(cursorMock); + } + + /** + * Tests the method {@link MyTracksProviderUtilsImpl#deleteAllTracks(Context)} + */ + public void testDeleteAllTracks() { + // Insert track, points and waypoint at first. + long trackId = System.currentTimeMillis(); + Track track = getTrack(trackId, 10); + insertTrackWithLocations(track); + Waypoint waypoint = new Waypoint(); + providerUtils.insertWaypoint(waypoint); + ContentResolver contentResolver = context.getContentResolver(); + Cursor tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null, + TracksColumns._ID); + assertEquals(1, tracksCursor.getCount()); + Cursor tracksPointsCursor = contentResolver.query(TrackPointsColumns.CONTENT_URI, null, null, + null, TrackPointsColumns._ID); + assertEquals(10, tracksPointsCursor.getCount()); + Cursor waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null, + null, WaypointsColumns._ID); + assertEquals(1, waypointCursor.getCount()); + // Delete all. + providerUtils.deleteAllTracks(context); + // Check whether all have been deleted. + tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null, + TracksColumns._ID); + assertEquals(0, tracksCursor.getCount()); + tracksPointsCursor = contentResolver.query(TrackPointsColumns.CONTENT_URI, null, null, + null, TrackPointsColumns._ID); + assertEquals(0, tracksPointsCursor.getCount()); + waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null, + null, WaypointsColumns._ID); + assertEquals(0, waypointCursor.getCount()); + } + + /** + * Tests the method {@link MyTracksProviderUtilsImpl#deleteTrack(Context, long)}. + */ + public void testDeleteTrack() { + // Insert three tracks, points of two tracks and way point of one track. + long trackId = System.currentTimeMillis(); + Track track = getTrack(trackId, 10); + + providerUtils.insertTrack(track); + insertTrackWithLocations(getTrack(trackId + 1, 10)); + insertTrackWithLocations(getTrack(trackId + 2, 10)); + + Waypoint waypoint = new Waypoint(); + waypoint.setTrackId(trackId); + providerUtils.insertWaypoint(waypoint); + + ContentResolver contentResolver = context.getContentResolver(); + Cursor tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null, + TracksColumns._ID); + assertEquals(3, tracksCursor.getCount()); + Cursor tracksPointsCursor = contentResolver.query(TrackPointsColumns.CONTENT_URI, null, null, + null, TrackPointsColumns._ID); + assertEquals(20, tracksPointsCursor.getCount()); + Cursor waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null, + null, WaypointsColumns._ID); + assertEquals(1, waypointCursor.getCount()); + // Delete one track. + providerUtils.deleteTrack(context, trackId); + // Check whether all data of a track has been deleted. + tracksCursor = contentResolver.query(TracksColumns.CONTENT_URI, null, null, null, + TracksColumns._ID); + assertEquals(2, tracksCursor.getCount()); + tracksPointsCursor = contentResolver.query(TrackPointsColumns.CONTENT_URI, null, null, + null, TrackPointsColumns._ID); + assertEquals(20, tracksPointsCursor.getCount()); + waypointCursor = contentResolver.query(WaypointsColumns.CONTENT_URI, null, null, + null, WaypointsColumns._ID); + assertEquals(0, waypointCursor.getCount()); + } + + /** + * Tests the method {@link MyTracksProviderUtilsImpl#getAllTracks()} + */ + public void testGetAllTracks() { + int initialTrackNumber = providerUtils.getAllTracks().size(); + long trackId = System.currentTimeMillis(); + providerUtils.insertTrack(getTrack(trackId, 0)); + List allTracks = providerUtils.getAllTracks(); + assertEquals(initialTrackNumber + 1, allTracks.size()); + assertEquals(trackId, allTracks.get(allTracks.size() - 1).getId()); + } + + /** + * Tests the method {@link MyTracksProviderUtilsImpl#getLastTrack()} + */ + public void testGetLastTrack() { + long trackId = System.currentTimeMillis(); + providerUtils.insertTrack(getTrack(trackId, 0)); + assertEquals(trackId, providerUtils.getLastTrack().getId()); + } + + /** + * Tests the method {@link MyTracksProviderUtilsImpl#getTrack(long)} + */ + public void testGetTrack() { + long trackId = System.currentTimeMillis(); + providerUtils.insertTrack(getTrack(trackId, 0)); + assertNotNull(providerUtils.getTrack(trackId)); + } + + /** + * Tests the method {@link MyTracksProviderUtilsImpl#updateTrack(Track)} + */ + public void testUpdateTrack() { + long trackId = System.currentTimeMillis(); + Track track = getTrack(trackId, 0); + String nameOld = "name1"; + String nameNew = "name2"; + track.setName(nameOld); + providerUtils.insertTrack(track); + assertEquals(nameOld, providerUtils.getTrack(trackId).getName()); + track.setName(nameNew); + providerUtils.updateTrack(track); + assertEquals(nameNew, providerUtils.getTrack(trackId).getName()); + } + + /** + * Tests the method {@link MyTracksProviderUtilsImpl#createContentValues(Waypoint)}. + */ + public void testCreateContentValues_waypoint() { + long trackId = System.currentTimeMillis(); + Track track = getTrack(trackId, 10); + providerUtils.insertTrack(track); + // Bottom + long startTime = 1000L; + // AverageSpeed + double minGrade = -20.11; + TripStatistics statistics = new TripStatistics(); + statistics.setStartTime(startTime); + statistics.setStopTime(2500L); + statistics.setTotalTime(1500L); + statistics.setMovingTime(700L); + statistics.setTotalDistance(750.0); + statistics.setTotalElevationGain(50.0); + statistics.setMaxSpeed(60.0); + statistics.setMaxElevation(1250.0); + statistics.setMinElevation(1200.0); + statistics.setMaxGrade(15.0); + statistics.setMinGrade(minGrade); + statistics.setBounds(-10000, 20000, 30000, -40000); + // Insert at first. + Waypoint waypoint = new Waypoint(); + waypoint.setDescription(TEST_DESC); + waypoint.setType(WaypointType.STATISTICS); + waypoint.setTripStatistics(statistics); + + Location loc = new Location("test"); + loc.setLatitude(22); + loc.setLongitude(22); + loc.setAccuracy((float) 1 / 100.0f); + loc.setAltitude(2.5); + waypoint.setLocation(loc); + providerUtils.insertWaypoint(waypoint); + + MyTracksProviderUtilsImpl myTracksProviderUtilsImpl = new MyTracksProviderUtilsImpl( + new MockContentResolver()); + + long waypointId = System.currentTimeMillis(); + waypoint.setId(waypointId); + ContentValues contentValues = myTracksProviderUtilsImpl.createContentValues(waypoint); + assertEquals(waypointId, contentValues.get(WaypointsColumns._ID)); + assertEquals(22 * 1000000, contentValues.get(WaypointsColumns.LONGITUDE)); + assertEquals(TEST_DESC, contentValues.get(WaypointsColumns.DESCRIPTION)); + assertEquals(startTime, contentValues.get(WaypointsColumns.STARTTIME)); + assertEquals(minGrade, contentValues.get(WaypointsColumns.MINGRADE)); + } + + /** + * Tests the method {@link MyTracksProviderUtilsImpl#createWaypoint(Cursor)}. + */ + @UsesMocks(Cursor.class) + public void testCreateWaypoint() { + Cursor cursorMock = AndroidMock.createNiceMock(Cursor.class); + int startColumnIndex = 1; + int columnIndex = startColumnIndex; + AndroidMock.expect(cursorMock.getColumnIndexOrThrow(WaypointsColumns._ID)) + .andReturn(columnIndex++); + AndroidMock.expect(cursorMock.getColumnIndexOrThrow(WaypointsColumns.NAME)).andReturn( + columnIndex++); + AndroidMock.expect(cursorMock.getColumnIndexOrThrow(WaypointsColumns.TRACKID)).andReturn( + columnIndex++); + columnIndex = startColumnIndex; + // Id + AndroidMock.expect(cursorMock.isNull(columnIndex++)).andReturn(false); + // Name + AndroidMock.expect(cursorMock.isNull(columnIndex++)).andReturn(false); + // trackIdIndex + AndroidMock.expect(cursorMock.isNull(columnIndex++)).andReturn(false); + long id = System.currentTimeMillis(); + columnIndex = startColumnIndex; + // Id + AndroidMock.expect(cursorMock.getLong(columnIndex++)).andReturn(id); + // Name + String name = NAME_PREFIX + Long.toString(id); + AndroidMock.expect(cursorMock.getString(columnIndex++)).andReturn(name); + // trackIdIndex + long trackId = 11L; + AndroidMock.expect(cursorMock.getLong(columnIndex++)).andReturn(trackId); + AndroidMock.replay(cursorMock); + Waypoint waypoint = providerUtils.createWaypoint(cursorMock); + assertEquals(id, waypoint.getId()); + assertEquals(name, waypoint.getName()); + assertEquals(trackId, waypoint.getTrackId()); + AndroidMock.verify(cursorMock); + } + + /** + * Tests the method + * {@link MyTracksProviderUtilsImpl#deleteWaypoint(Context, long, DescriptionGenerator)} + * when there is only one waypoint in the track. + */ + public void testDeleteWaypoint_onlyOneWayPoint() { + long trackId = System.currentTimeMillis(); + Track track = getTrack(trackId, 10); + providerUtils.insertTrack(track); + + // Insert at first. + Waypoint waypoint1 = new Waypoint(); + waypoint1.setDescription(TEST_DESC); + waypoint1.setTrackId(trackId); + waypoint1.setType(WaypointType.STATISTICS); + providerUtils.insertWaypoint(waypoint1); + + // Delete + DescriptionGenerator descriptionGenerator = new DescriptionGenerator() { + + @Override + public String generateWaypointDescription(TripStatistics tripStatistics) { + return MyTracksProviderUtilsImplTest.MOCK_DESC; + } + + @Override + public String generateTrackDescription(Track aTrack, Vector distances, + Vector elevations, boolean html) { + return null; + } + }; + providerUtils.deleteWaypoint(context, 1, descriptionGenerator); + + assertNull(providerUtils.getWaypoint(1)); + } + + /** + * Tests the method + * {@link MyTracksProviderUtilsImpl#deleteWaypoint(Context, long, DescriptionGenerator)} + * when there is more than one waypoint in the track. + */ + public void testDeleteWaypoint_hasNextWayPoint() { + long trackId = System.currentTimeMillis(); + Track track = getTrack(trackId, 10); + providerUtils.insertTrack(track); + + TripStatistics statistics = new TripStatistics(); + statistics.setStartTime(1000L); + statistics.setStopTime(2500L); + statistics.setTotalTime(1500L); + statistics.setMovingTime(700L); + statistics.setTotalDistance(750.0); + statistics.setTotalElevationGain(50.0); + statistics.setMaxSpeed(60.0); + statistics.setMaxElevation(1250.0); + statistics.setMinElevation(1200.0); + statistics.setMaxGrade(15.0); + statistics.setMinGrade(-25.0); + statistics.setBounds(-10000, 20000, 30000, -40000); + // Insert at first. + Waypoint waypoint1 = new Waypoint(); + waypoint1.setDescription(Long.toString(trackId)); + waypoint1.setTrackId(trackId); + waypoint1.setType(WaypointType.STATISTICS); + waypoint1.setTripStatistics(statistics); + providerUtils.insertWaypoint(waypoint1); + Waypoint waypoint2 = new Waypoint(); + waypoint2.setDescription(Long.toString(trackId)); + waypoint2.setTrackId(trackId); + waypoint2.setType(WaypointType.STATISTICS); + waypoint2.setTripStatistics(statistics); + providerUtils.insertWaypoint(waypoint2); + + // Delete + DescriptionGenerator descriptionGenerator = new DescriptionGenerator() { + @Override + public String generateWaypointDescription(TripStatistics tripStatistics) { + return MyTracksProviderUtilsImplTest.MOCK_DESC; + } + + @Override + public String generateTrackDescription(Track aTrack, Vector distances, + Vector elevations, boolean html) { + return null; + } + }; + providerUtils.deleteWaypoint(context, 1, descriptionGenerator); + + assertNull(providerUtils.getWaypoint(1)); + assertEquals(MyTracksProviderUtilsImplTest.MOCK_DESC, providerUtils.getWaypoint(2) + .getDescription()); + } + + /** + * Tests the method {@link MyTracksProviderUtilsImpl#getFirstWaypointId(long)}. + */ + public void testGetFirstWaypointId() { + long trackId = System.currentTimeMillis(); + Track track = getTrack(trackId, 10); + providerUtils.insertTrack(track); + + Waypoint waypoint1 = new Waypoint(); + waypoint1.setTrackId(trackId); + Waypoint waypoint2 = new Waypoint(); + waypoint2.setTrackId(trackId); + providerUtils.insertWaypoint(waypoint1); + providerUtils.insertWaypoint(waypoint2); + + assertEquals(-1L, providerUtils.getFirstWaypointId(-1)); + assertEquals(1L, providerUtils.getFirstWaypointId(trackId)); + } + + /** + * Tests the method {@link MyTracksProviderUtilsImpl#getNextWaypointNumber(long, WaypointType)}. + */ + public void testGetNextWaypointNumber() { + long trackId = System.currentTimeMillis(); + Track track = getTrack(trackId, 10); + providerUtils.insertTrack(track); + + Waypoint waypoint1 = new Waypoint(); + waypoint1.setType(WaypointType.STATISTICS); + waypoint1.setTrackId(trackId); + Waypoint waypoint2 = new Waypoint(); + waypoint2.setType(WaypointType.WAYPOINT); + waypoint2.setTrackId(trackId); + Waypoint waypoint3 = new Waypoint(); + waypoint3.setType(WaypointType.STATISTICS); + waypoint3.setTrackId(trackId); + Waypoint waypoint4 = new Waypoint(); + waypoint4.setType(WaypointType.WAYPOINT); + waypoint4.setTrackId(trackId); + providerUtils.insertWaypoint(waypoint1); + providerUtils.insertWaypoint(waypoint2); + providerUtils.insertWaypoint(waypoint3); + providerUtils.insertWaypoint(waypoint4); + + assertEquals(2, providerUtils.getNextWaypointNumber(trackId, WaypointType.STATISTICS)); + assertEquals(3, providerUtils.getNextWaypointNumber(trackId, WaypointType.WAYPOINT)); + } + + /** + * Tests the method + * {@link MyTracksProviderUtils#getLastWaypoint(long, WaypointType)}. + */ + public void testGetLastStatisticsWaypoint() { + long trackId = System.currentTimeMillis(); + Track track = getTrack(trackId, 10); + providerUtils.insertTrack(track); + + Waypoint waypoint1 = new Waypoint(); + waypoint1.setTrackId(trackId); + waypoint1.setType(WaypointType.STATISTICS); + waypoint1.setDescription("Desc1"); + Waypoint waypoint2 = new Waypoint(); + waypoint2.setTrackId(trackId); + waypoint2.setType(WaypointType.STATISTICS); + waypoint2.setDescription("Desc2"); + Waypoint waypoint3 = new Waypoint(); + waypoint3.setTrackId(trackId); + waypoint3.setType(WaypointType.WAYPOINT); + waypoint3.setDescription("Desc3"); + providerUtils.insertWaypoint(waypoint1); + providerUtils.insertWaypoint(waypoint2); + providerUtils.insertWaypoint(waypoint3); + + assertEquals("Desc2", providerUtils.getLastWaypoint(trackId, WaypointType.STATISTICS).getDescription()); + } + + /** + * Tests the method {@link MyTracksProviderUtilsImpl#insertWaypoint(Waypoint)} and + * {@link MyTracksProviderUtilsImpl#getWaypoint(long)}. + */ + public void testInsertAndGetWaypoint() { + long trackId = System.currentTimeMillis(); + Track track = getTrack(trackId, 10); + providerUtils.insertTrack(track); + + Waypoint waypoint = new Waypoint(); + waypoint.setDescription(TEST_DESC); + waypoint.setTrackId(trackId); + providerUtils.insertWaypoint(waypoint); + + assertEquals(TEST_DESC, providerUtils.getWaypoint(1).getDescription()); + } + + /** + * Tests the method {@link MyTracksProviderUtilsImpl#updateWaypoint(Waypoint)}. + */ + public void testUpdateWaypoint() { + long trackId = System.currentTimeMillis(); + Track track = getTrack(trackId, 10); + providerUtils.insertTrack(track); + // Insert at first. + Waypoint waypoint = new Waypoint(); + waypoint.setDescription(TEST_DESC); + waypoint.setTrackId(trackId); + providerUtils.insertWaypoint(waypoint); + // Update + waypoint = providerUtils.getWaypoint(1); + waypoint.setDescription(TEST_DESC_NEW); + providerUtils.updateWaypoint(waypoint); + + assertEquals(TEST_DESC_NEW, providerUtils.getWaypoint(1).getDescription()); + } + + /** + * Tests the method {@link MyTracksProviderUtilsImpl#bulkInsertTrackPoint(Location[], + * int, long)}. + */ + public void testBulkInsertTrackPoint() { + // Insert track, point at first. + long trackId = System.currentTimeMillis(); + Track track = getTrack(trackId, 10); + insertTrackWithLocations(track); + + providerUtils.bulkInsertTrackPoint(track.getLocations().toArray(new Location[0]), -1, trackId); + assertEquals(20, providerUtils.getTrackPointCursor(trackId, -1L, 1000, false).getCount()); + providerUtils.bulkInsertTrackPoint(track.getLocations().toArray(new Location[0]), 8, trackId); + assertEquals(28, providerUtils.getTrackPointCursor(trackId, -1L, 1000, false).getCount()); + } + + /** + * Tests the method {@link MyTracksProviderUtilsImpl#createTrackPoint(Cursor)}. + */ + @UsesMocks(Cursor.class) + public void testCreateTrackPoint() { + Cursor cursorMock = AndroidMock.createNiceMock(Cursor.class); + + // Set index. + int index = 1; + // Id + AndroidMock.expect(cursorMock.getColumnIndex(TrackPointsColumns._ID)).andReturn(index++); + // Longitude + AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TrackPointsColumns.LONGITUDE)).andReturn( + index++); + // Latitude + AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TrackPointsColumns.LATITUDE)).andReturn( + index++); + // Time + AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TrackPointsColumns.TIME)) + .andReturn(index++); + // Speed + AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TrackPointsColumns.SPEED)).andReturn( + index++); + // Sensor + AndroidMock.expect(cursorMock.getColumnIndexOrThrow(TrackPointsColumns.SENSOR)).andReturn( + index++); + + // Set return value of isNull(). + index = 2; + // Longitude + AndroidMock.expect(cursorMock.isNull(index++)).andReturn(false); + // Latitude + AndroidMock.expect(cursorMock.isNull(index++)).andReturn(false); + // Time + AndroidMock.expect(cursorMock.isNull(index++)).andReturn(false); + // Speed + AndroidMock.expect(cursorMock.isNull(index++)).andReturn(false); + // Sensor + AndroidMock.expect(cursorMock.isNull(index++)).andReturn(false); + + // Set return value of isNull(). + index = 2; + // Longitude + int longitude = 11; + AndroidMock.expect(cursorMock.getInt(index++)).andReturn(longitude * 1000000); + // Latitude. + int latitude = 22; + AndroidMock.expect(cursorMock.getInt(index++)).andReturn(latitude * 1000000); + // Time + long time = System.currentTimeMillis(); + AndroidMock.expect(cursorMock.getLong(index++)).andReturn(time); + // Speed + float speed = 2.2f; + AndroidMock.expect(cursorMock.getFloat(index++)).andReturn(speed); + // Sensor + byte[] sensor = "Sensor state".getBytes(); + AndroidMock.expect(cursorMock.getBlob(index++)).andReturn(sensor); + + AndroidMock.replay(cursorMock); + Location location = providerUtils.createTrackPoint(cursorMock); + assertEquals((double) longitude, location.getLongitude()); + assertEquals((double) latitude, location.getLatitude()); + assertEquals(time, location.getTime()); + assertEquals(speed, location.getSpeed()); + AndroidMock.verify(cursorMock); + } + + /** + * Tests the method + * {@link MyTracksProviderUtilsImpl#insertTrackPoint(Location, long)}. + */ + public void testInsertTrackPoint() { + // Insert track, point at first. + long trackId = System.currentTimeMillis(); + Track track = getTrack(trackId, 10); + insertTrackWithLocations(track); + + providerUtils.insertTrackPoint(createLocation(22), trackId); + assertEquals(11, providerUtils.getTrackPointCursor(trackId, -1L, 1000, false).getCount()); + } + + /** + * Tests the method {@link MyTracksProviderUtilsImpl#getFirstTrackPointId(long)}. + */ + public void testGetFirstTrackPointId() { + // Insert track, point at first. + long trackId = System.currentTimeMillis(); + Track track = getTrack(trackId, 10); + insertTrackWithLocations(track); + + assertEquals(1, providerUtils.getFirstTrackPointId(trackId)); + } + + /** + * Tests the method {@link MyTracksProviderUtilsImpl#getLastTrackPointId(long)}. + */ + public void testGetLastTrackPointId() { + // Insert track, point at first. + long trackId = System.currentTimeMillis(); + Track track = getTrack(trackId, 10); + insertTrackWithLocations(track); + + assertEquals(10, providerUtils.getLastTrackPointId(trackId)); + } + + /** + * Tests the method {@link MyTracksProviderUtilsImpl#getLastValidTrackPoint(long)}. + */ + public void testGetLastValidTrackPoint() { + // Insert track, points at first. + long trackId = System.currentTimeMillis(); + Track track = getTrack(trackId, 10); + insertTrackWithLocations(track); + + Location lastLocation = providerUtils.getLastValidTrackPoint(trackId); + checkLocation(9, lastLocation); + } + + /** + * Tests the method + * {@link MyTracksProviderUtilsImpl#getTrackPointCursor(long, long, int, boolean)} + * in descending. + */ + public void testGetTrackPointCursor_desc() { + // Insert track, points at first. + long trackId = System.currentTimeMillis(); + Track track = getTrack(trackId, 10); + insertTrackWithLocations(track); + + Cursor cursor = providerUtils.getTrackPointCursor(trackId, 2L, 5, true); + assertEquals(2, cursor.getCount()); + } + + /** + * Tests the method + * {@link MyTracksProviderUtilsImpl#getTrackPointCursor(long, long, int, boolean)} + * in ascending. + */ + public void testGetTrackPointCursor_asc() { + // Insert track, points at first. + long trackId = System.currentTimeMillis(); + Track track = getTrack(trackId, 10); + insertTrackWithLocations(track); + + Cursor cursor = providerUtils.getTrackPointCursor(trackId, 2L, 5, false); + assertEquals(5, cursor.getCount()); + } + + /** + * Tests the method + * {@link MyTracksProviderUtilsImpl#getTrackPointLocationIterator(long, long, boolean, LocationFactory)} + * in descending. + */ + public void testGetTrackPointLocationIterator_desc() { + // Insert track, points at first. + long trackId = System.currentTimeMillis(); + Track track = getTrack(trackId, 10); + insertTrackWithLocations(track); + + long startTrackPointId = 2L; + + LocationIterator locationIterator = providerUtils.getTrackPointLocationIterator(trackId, + startTrackPointId, true, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY); + for (int i = 1; i >= 0; i--) { + assertTrue(locationIterator.hasNext()); + Location location = locationIterator.next(); + assertEquals(2 + (i - 1), locationIterator.getLocationId()); + checkLocation(i, location); + } + assertFalse(locationIterator.hasNext()); + } + + /** + * Tests the method + * {@link MyTracksProviderUtilsImpl#getTrackPointLocationIterator(long, long, boolean, LocationFactory)} + * in ascending. + */ + public void testGetTrackPointLocationIterator_asc() { + // Insert track, point at first. + long trackId = System.currentTimeMillis(); + Track track = getTrack(trackId, 10); + insertTrackWithLocations(track); + + long startTrackPointId = 2L; + + LocationIterator locationIterator = providerUtils.getTrackPointLocationIterator(trackId, + startTrackPointId, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY); + + for (int i = 1; i < 10; i++) { + assertTrue(locationIterator.hasNext()); + Location location = locationIterator.next(); + assertEquals(2 + (i - 1), locationIterator.getLocationId()); + checkLocation(i, location); + } + assertFalse(locationIterator.hasNext()); + } + + /** + * Simulates a track which is used for testing. + * + * @param id the id of the track + * @param numPoints the location number in the track + * @return the simulated track + */ + private Track getTrack(long id,int numPoints) { + Track track = new Track(); + track.setId(id); + track.setName("Test: " + id); + track.setNumberOfPoints(numPoints); + for(int i = 0; i < numPoints; i++) { + track.addLocation(createLocation(i)); + } + return track; + } + + /** + * Creates a location. + * @param i the index to set the value of location. + * @return created location + */ + private Location createLocation(int i) { + + Location loc = new Location("test"); + loc.setLatitude(INITIAL_LATITUDE + (double) i / 10000.0); + loc.setLongitude(INITIAL_LONGITUDE - (double) i / 10000.0); + loc.setAccuracy((float) i / 100.0f); + loc.setAltitude(i * ALTITUDE_INTERVAL); + return loc; + } + + /** + * Checks the value of a location. + * + * @param i the index of this location which created in the method + * {@link MyTracksProviderUtilsImplTest#getTrack(long, int)} + * @param location the location to be checked + */ + private void checkLocation(int i, Location location) { + assertEquals(INITIAL_LATITUDE + (double) i / 10000.0, location.getLatitude()); + assertEquals(INITIAL_LONGITUDE - (double) i / 10000.0, location.getLongitude()); + assertEquals((float) i / 100.0f, location.getAccuracy()); + assertEquals(i * ALTITUDE_INTERVAL, location.getAltitude()); + } + + /** + * Inserts a track with locations into the database. + * + * @param track track to be inserted + */ + private void insertTrackWithLocations(Track track) { + providerUtils.insertTrack(track); + providerUtils.bulkInsertTrackPoint(track.getLocations().toArray(new Location[0]), track + .getLocations().size(), track.getId()); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/content/SearchEngineTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/content/SearchEngineTest.java new file mode 100644 index 000000000..1c77c57f0 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/content/SearchEngineTest.java @@ -0,0 +1,326 @@ +/* + * Copyright 2012 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.android.apps.mytracks.content; + +import com.google.android.apps.mytracks.content.SearchEngine.ScoredResult; +import com.google.android.apps.mytracks.content.SearchEngine.SearchQuery; +import com.google.android.apps.mytracks.services.TrackRecordingServiceTest.MockContext; +import com.google.android.apps.mytracks.stats.TripStatistics; + +import android.content.ContentUris; +import android.location.Location; +import android.net.Uri; +import android.test.AndroidTestCase; +import android.test.RenamingDelegatingContext; +import android.test.mock.MockContentResolver; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Tests for {@link SearchEngine}. + * These are not meant to be quality tests, but instead feature-by-feature tests + * (in other words, they don't test the mixing of different score boostings, just + * each boosting separately) + * + * @author Rodrigo Damazio + */ +public class SearchEngineTest extends AndroidTestCase { + + private static final Location HERE = new Location("gps"); + private static final long NOW = 1234567890000L; // After OLDEST_ALLOWED_TIMESTAMP + private MyTracksProviderUtils providerUtils; + private SearchEngine engine; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + MockContentResolver mockContentResolver = new MockContentResolver(); + RenamingDelegatingContext targetContext = new RenamingDelegatingContext( + getContext(), getContext(), "test."); + MockContext context = new MockContext(mockContentResolver, targetContext); + MyTracksProvider provider = new MyTracksProvider(); + provider.attachInfo(context, null); + mockContentResolver.addProvider(MyTracksProviderUtils.AUTHORITY, provider); + setContext(context); + + providerUtils = MyTracksProviderUtils.Factory.get(context); + engine = new SearchEngine(providerUtils); + } + + @Override + protected void tearDown() throws Exception { + providerUtils.deleteAllTracks(getContext()); + + super.tearDown(); + } + + private long insertTrack(String title, String description, String category, double distance, long hoursAgo) { + Track track = new Track(); + track.setName(title); + track.setDescription(description); + track.setCategory(category); + + TripStatistics stats = track.getTripStatistics(); + if (hoursAgo > 0) { + // Started twice hoursAgo, so the average time is hoursAgo. + stats.setStartTime(NOW - hoursAgo * 1000L * 60L * 60L * 2); + stats.setStopTime(NOW); + } + + int latitude = (int) ((HERE.getLatitude() + distance) * 1E6); + int longitude = (int) ((HERE.getLongitude() + distance) * 1E6); + stats.setBounds(latitude, longitude, latitude, longitude); + + Uri uri = providerUtils.insertTrack(track); + return ContentUris.parseId(uri); + } + + private long insertTrack(String title, String description, String category) { + return insertTrack(title, description, category, 0, -1); + } + + private long insertTrack(String title, double distance) { + return insertTrack(title, "", "", distance, -1); + } + + private long insertTrack(String title, long hoursAgo) { + return insertTrack(title, "", "", 0.0, hoursAgo); + } + + private long insertWaypoint(String title, String description, String category, double distance, long hoursAgo, long trackId) { + Waypoint waypoint = new Waypoint(); + waypoint.setName(title); + waypoint.setDescription(description); + waypoint.setCategory(category); + waypoint.setTrackId(trackId); + + Location location = new Location(HERE); + location.setLatitude(location.getLatitude() + distance); + location.setLongitude(location.getLongitude() + distance); + if (hoursAgo >= 0) { + location.setTime(NOW - hoursAgo * 1000L * 60L * 60L); + } + waypoint.setLocation(location); + + Uri uri = providerUtils.insertWaypoint(waypoint); + return ContentUris.parseId(uri); + } + + private long insertWaypoint(String title, String description, String category) { + return insertWaypoint(title, description, category, 0.0, -1, -1); + } + + private long insertWaypoint(String title, double distance) { + return insertWaypoint(title, "", "", distance, -1, -1); + } + + private long insertWaypoint(String title, long hoursAgo) { + return insertWaypoint(title, "", "", 0.0, hoursAgo, -1); + } + + private long insertWaypoint(String title, long hoursAgo, long trackId) { + return insertWaypoint(title, "", "", 0.0, hoursAgo, trackId); + } + + public void testSearchText() { + // Insert 7 tracks (purposefully out of result order): + // - one which won't match + // - one which will match the description + // - one which will match the category + // - one which will match the title + // - one which will match in title and category + // - one which will match in title and description + // - one which will match in all fields + insertTrack("bb", "cc", "dd"); + long descriptionMatchId = insertTrack("bb", "aa", "cc"); + long categoryMatchId = insertTrack("bb", "cc", "aa"); + long titleMatchId = insertTrack("aa", "bb", "cc"); + long titleCategoryMatchId = insertTrack("aa", "bb", "ca"); + long titleDescriptionMatchId = insertTrack("aa", "ba", "cc"); + long allMatchId = insertTrack("aa", "ba", "ca"); + + SearchQuery query = new SearchQuery("a", null, -1, NOW); + ArrayList results = new ArrayList(engine.search(query)); + + // Title > Description > Category. + assertTrackResults(results, + allMatchId, titleDescriptionMatchId, titleCategoryMatchId, titleMatchId, descriptionMatchId, + categoryMatchId); + } + + public void testSearchWaypointText() { + // Insert 7 waypoints (purposefully out of result order): + // - one which won't match + // - one which will match the description + // - one which will match the category + // - one which will match the title + // - one which will match in title and category + // - one which will match in title and description + // - one which will match in all fields + insertWaypoint("bb", "cc", "dd"); + long descriptionMatchId = insertWaypoint("bb", "aa", "cc"); + long categoryMatchId = insertWaypoint("bb", "cc", "aa"); + long titleMatchId = insertWaypoint("aa", "bb", "cc"); + long titleCategoryMatchId = insertWaypoint("aa", "bb", "ca"); + long titleDescriptionMatchId = insertWaypoint("aa", "ba", "cc"); + long allMatchId = insertWaypoint("aa", "ba", "ca"); + + SearchQuery query = new SearchQuery("a", null, -1, NOW); + ArrayList results = new ArrayList(engine.search(query)); + + // Title > Description > Category. + assertWaypointResults(results, + allMatchId, titleDescriptionMatchId, titleCategoryMatchId, titleMatchId, descriptionMatchId, + categoryMatchId); + } + + public void testSearchMixedText() { + // Insert 5 entries (purposefully out of result order): + // - one waypoint which will match by description + // - one waypoint which won't match + // - one waypoint which will match by title + // - one track which won't match + // - one track which will match by title + long descriptionWaypointId = insertWaypoint("bb", "aa", "cc"); + insertWaypoint("bb", "cc", "dd"); + long titleWaypointId = insertWaypoint("aa", "bb", "cc"); + insertTrack("bb", "cc", "dd"); + long trackId = insertTrack("aa", "bb", "cc"); + + SearchQuery query = new SearchQuery("a", null, -1, NOW); + ArrayList results = new ArrayList(engine.search(query)); + + // Title > Description > Category. + assertEquals(results.toString(), 3, results.size()); + assertTrackResult(trackId, results.get(0)); + assertWaypointResult(titleWaypointId, results.get(1)); + assertWaypointResult(descriptionWaypointId, results.get(2)); + } + + public void testSearchTrackDistance() { + // All results match text, but they're at difference distances from the user. + long farFarAwayId = insertTrack("aa", 0.3); + long nearId = insertTrack("ab", 0.1); + long farId = insertTrack("ac", 0.2); + + SearchQuery query = new SearchQuery("a", HERE, -1, NOW); + ArrayList results = new ArrayList(engine.search(query)); + + // Distance order. + assertTrackResults(results, nearId, farId, farFarAwayId); + } + + public void testSearchWaypointDistance() { + // All results match text, but they're at difference distances from the user. + long farFarAwayId = insertWaypoint("aa", 0.3); + long nearId = insertWaypoint("ab", 0.1); + long farId = insertWaypoint("ac", 0.2); + + SearchQuery query = new SearchQuery("a", HERE, -1, NOW); + ArrayList results = new ArrayList(engine.search(query)); + + // Distance order. + assertWaypointResults(results, nearId, farId, farFarAwayId); + } + + public void testSearchTrackRecent() { + // All results match text, but they're were recorded at different times. + long oldestId = insertTrack("aa", 3); + long recentId = insertTrack("ab", 1); + long oldId = insertTrack("ac", 2); + + SearchQuery query = new SearchQuery("a", null, -1, NOW); + ArrayList results = new ArrayList(engine.search(query)); + + // Reverse time order. + assertTrackResults(results, recentId, oldId, oldestId); + } + + public void testSearchWaypointRecent() { + // All results match text, but they're were recorded at different times. + long oldestId = insertWaypoint("aa", 2); + long recentId = insertWaypoint("ab", 0); + long oldId = insertWaypoint("ac", 1); + + SearchQuery query = new SearchQuery("a", null, -1, NOW); + ArrayList results = new ArrayList(engine.search(query)); + + // Reverse time order. + assertWaypointResults(results, recentId, oldId, oldestId); + } + + public void testSearchCurrentTrack() { + // All results match text, but one of them is the current track. + long currentId = insertTrack("ab", 1); + long otherId = insertTrack("aa", 1); + + SearchQuery query = new SearchQuery("a", null, currentId, NOW); + ArrayList results = new ArrayList(engine.search(query)); + + // Current track should be demoted. + assertTrackResults(results, otherId, currentId); + } + + public void testSearchCurrentTrackWaypoint() { + // All results match text, but one of them is in the current track. + long otherId = insertWaypoint("aa", 1, 456); + long currentId = insertWaypoint("ab", 1, 123); + + SearchQuery query = new SearchQuery("a", null, 123, NOW); + ArrayList results = new ArrayList(engine.search(query)); + + // Waypoint in current track should be promoted. + assertWaypointResults(results, currentId, otherId); + } + + private void assertTrackResult(long trackId, ScoredResult result) { + assertNotNull("Not a track", result.track); + assertNull("Ambiguous result", result.waypoint); + assertEquals(trackId, result.track.getId()); + } + + private void assertTrackResults(List results, long... trackIds) { + String errMsg = "Expected IDs=" + Arrays.toString(trackIds) + "; results=" + results; + assertEquals(results.size(), trackIds.length); + for (int i = 0; i < results.size(); i++) { + ScoredResult result = results.get(i); + assertNotNull(errMsg, result.track); + assertNull(errMsg, result.waypoint); + assertEquals(errMsg, trackIds[i], result.track.getId()); + } + } + + private void assertWaypointResult(long waypointId, ScoredResult result) { + assertNotNull("Not a waypoint", result.waypoint); + assertNull("Ambiguous result", result.track); + assertEquals(waypointId, result.waypoint.getId()); + } + + private void assertWaypointResults(List results, long... waypointIds) { + String errMsg = "Expected IDs=" + Arrays.toString(waypointIds) + "; results=" + results; + assertEquals(results.size(), waypointIds.length); + for (int i = 0; i < results.size(); i++) { + ScoredResult result = results.get(i); + assertNotNull(errMsg, result.waypoint); + assertNull(errMsg, result.track); + assertEquals(errMsg, waypointIds[i], result.waypoint.getId()); + } + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/content/TrackDataHubTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/content/TrackDataHubTest.java new file mode 100644 index 000000000..dfa74c587 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/content/TrackDataHubTest.java @@ -0,0 +1,805 @@ +/* + * Copyright 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.android.apps.mytracks.content; + +import static com.google.android.testing.mocking.AndroidMock.capture; +import static com.google.android.testing.mocking.AndroidMock.eq; +import static com.google.android.testing.mocking.AndroidMock.expect; +import static com.google.android.testing.mocking.AndroidMock.isA; + +import com.google.android.apps.mytracks.Constants; +import com.google.android.apps.mytracks.TrackStubUtils; +import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationFactory; +import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator; +import com.google.android.apps.mytracks.services.TrackRecordingServiceTest.MockContext; +import com.google.android.apps.mytracks.util.PreferencesUtils; +import com.google.android.maps.mytracks.R; +import com.google.android.testing.mocking.AndroidMock; +import com.google.android.testing.mocking.UsesMocks; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.database.ContentObserver; +import android.database.Cursor; +import android.database.MatrixCursor; +import android.location.Location; +import android.provider.BaseColumns; +import android.test.AndroidTestCase; +import android.test.RenamingDelegatingContext; +import android.test.mock.MockContentResolver; + +import java.util.EnumSet; +import java.util.HashSet; +import java.util.Set; + +import org.easymock.Capture; +import org.easymock.IAnswer; + +/** + * Tests for {@link TrackDataHub}. + * + * @author Rodrigo Damazio + */ +public class TrackDataHubTest extends AndroidTestCase { + + private static final long TRACK_ID = 42L; + private static final int TARGET_POINTS = 50; + + private MockContext context; + private SharedPreferences sharedPreferences; + private MyTracksProviderUtils myTracksProviderUtils; + private DataSource dataSource; + private TrackDataManager trackDataManager; + private TrackDataHub trackDataHub; + private TrackDataListener trackDataListener1; + private TrackDataListener trackDataListener2; + private Capture preferenceChangeListenerCapture = new Capture< + SharedPreferences.OnSharedPreferenceChangeListener>(); + + @UsesMocks({ MyTracksProviderUtils.class, DataSource.class, TrackDataListener.class }) + @Override + protected void setUp() throws Exception { + super.setUp(); + context = new MockContext(new MockContentResolver(), new RenamingDelegatingContext( + getContext(), getContext(), "test.")); + sharedPreferences = context.getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE); + myTracksProviderUtils = AndroidMock.createMock(MyTracksProviderUtils.class); + dataSource = AndroidMock.createMock(DataSource.class, context); + trackDataManager = new TrackDataManager(); + trackDataHub = new TrackDataHub( + context, trackDataManager, myTracksProviderUtils, TARGET_POINTS) { + @Override + protected DataSource newDataSource() { + return dataSource; + } + + @Override + protected void runInHanderThread(Runnable runnable) { + // Run everything in the same thread + runnable.run(); + } + }; + + trackDataListener1 = AndroidMock.createStrictMock( + "trackDataListener1", TrackDataListener.class); + trackDataListener2 = AndroidMock.createStrictMock( + "trackDataListener2", TrackDataListener.class); + PreferencesUtils.setLong(context, R.string.recording_track_id_key, TRACK_ID); + } + + @Override + protected void tearDown() throws Exception { + AndroidMock.reset(dataSource); + + // Expect everything to be unregistered. + dataSource.unregisterContentObserver(isA(ContentObserver.class)); + AndroidMock.expectLastCall().times(3); + dataSource.unregisterOnSharedPreferenceChangeListener( + isA(OnSharedPreferenceChangeListener.class)); + AndroidMock.replay(dataSource); + + trackDataHub.stop(); + trackDataHub = null; + super.tearDown(); + } + + /** + * Tests registering for tracks table update. + */ + public void testTracksTableUpdate() { + + // Register two listeners + Capture contentObserverCapture = new Capture(); + Track track = new Track(); + expect(myTracksProviderUtils.getTrack(TRACK_ID)).andStubReturn(track); + dataSource.registerContentObserver( + eq(TracksColumns.CONTENT_URI), capture(contentObserverCapture)); + trackDataListener1.onTrackUpdated(track); + trackDataListener2.onTrackUpdated(track); + replay(); + + trackDataHub.start(); + trackDataHub.loadTrack(TRACK_ID); + trackDataHub.registerTrackDataListener( + trackDataListener1, EnumSet.of(TrackDataType.TRACKS_TABLE)); + trackDataHub.registerTrackDataListener( + trackDataListener2, EnumSet.of(TrackDataType.TRACKS_TABLE)); + verifyAndReset(); + + // Causes tracks table update + ContentObserver contentObserver = contentObserverCapture.getValue(); + expect(myTracksProviderUtils.getTrack(TRACK_ID)).andStubReturn(track); + trackDataListener1.onTrackUpdated(track); + trackDataListener2.onTrackUpdated(track); + replay(); + + contentObserver.onChange(false); + verifyAndReset(); + + // Unregister one listener + expect(myTracksProviderUtils.getTrack(TRACK_ID)).andStubReturn(track); + trackDataListener2.onTrackUpdated(track); + replay(); + + trackDataHub.unregisterTrackDataListener(trackDataListener1); + contentObserver.onChange(false); + verifyAndReset(); + + // Unregister the second listener + dataSource.unregisterContentObserver(contentObserver); + replay(); + + trackDataHub.unregisterTrackDataListener(trackDataListener2); + contentObserver.onChange(false); + verifyAndReset(); + } + + /** + * Tests registering for waypoints table update. + */ + public void testWaypointsTableUpdate() { + Waypoint waypoint1 = new Waypoint(); + Waypoint waypoint2 = new Waypoint(); + Waypoint waypoint3 = new Waypoint(); + Waypoint waypoint4 = new Waypoint(); + Location location = new Location("gps"); + location.setLatitude(10.0); + location.setLongitude(8.0); + waypoint1.setLocation(location); + waypoint2.setLocation(location); + waypoint3.setLocation(location); + waypoint4.setLocation(location); + + // Register two listeners + Capture contentObserverCapture = new Capture(); + expect(myTracksProviderUtils.getWaypointCursor( + eq(TRACK_ID), AndroidMock.leq(-1L), eq(TrackDataHub.MAX_DISPLAYED_WAYPOINTS))) + .andStubAnswer(new FixedSizeCursorAnswer(2)); + expect(myTracksProviderUtils.createWaypoint(isA(Cursor.class))) + .andReturn(waypoint1).andReturn(waypoint2).andReturn(waypoint1).andReturn(waypoint2); + dataSource.registerContentObserver( + eq(WaypointsColumns.CONTENT_URI), capture(contentObserverCapture)); + trackDataListener1.clearWaypoints(); + trackDataListener2.clearWaypoints(); + trackDataListener1.onNewWaypoint(waypoint1); + trackDataListener2.onNewWaypoint(waypoint1); + trackDataListener1.onNewWaypoint(waypoint2); + trackDataListener2.onNewWaypoint(waypoint2); + trackDataListener1.onNewWaypointsDone(); + trackDataListener2.onNewWaypointsDone(); + replay(); + + trackDataHub.start(); + trackDataHub.loadTrack(TRACK_ID); + trackDataHub.registerTrackDataListener( + trackDataListener1, EnumSet.of(TrackDataType.WAYPOINTS_TABLE)); + trackDataHub.registerTrackDataListener( + trackDataListener2, EnumSet.of(TrackDataType.WAYPOINTS_TABLE)); + verifyAndReset(); + + // Cause waypoints table update + ContentObserver contentObserver = contentObserverCapture.getValue(); + expect(myTracksProviderUtils.getWaypointCursor( + eq(TRACK_ID), AndroidMock.leq(-1L), eq(TrackDataHub.MAX_DISPLAYED_WAYPOINTS))) + .andStubAnswer(new FixedSizeCursorAnswer(3)); + expect(myTracksProviderUtils.createWaypoint(isA(Cursor.class))) + .andReturn(waypoint1).andReturn(waypoint2).andReturn(waypoint3); + trackDataListener1.clearWaypoints(); + trackDataListener2.clearWaypoints(); + trackDataListener1.onNewWaypoint(waypoint1); + trackDataListener2.onNewWaypoint(waypoint1); + trackDataListener1.onNewWaypoint(waypoint2); + trackDataListener2.onNewWaypoint(waypoint2); + trackDataListener1.onNewWaypoint(waypoint3); + trackDataListener2.onNewWaypoint(waypoint3); + trackDataListener1.onNewWaypointsDone(); + trackDataListener2.onNewWaypointsDone(); + replay(); + + contentObserver.onChange(false); + verifyAndReset(); + + // Unregister one listener + expect(myTracksProviderUtils.getWaypointCursor( + eq(TRACK_ID), AndroidMock.leq(-1L), eq(TrackDataHub.MAX_DISPLAYED_WAYPOINTS))) + .andStubAnswer(new FixedSizeCursorAnswer(4)); + expect(myTracksProviderUtils.createWaypoint(isA(Cursor.class))) + .andReturn(waypoint1).andReturn(waypoint2).andReturn(waypoint3).andReturn(waypoint4); + trackDataListener2.clearWaypoints(); + trackDataListener2.onNewWaypoint(waypoint1); + trackDataListener2.onNewWaypoint(waypoint2); + trackDataListener2.onNewWaypoint(waypoint3); + trackDataListener2.onNewWaypoint(waypoint4); + trackDataListener2.onNewWaypointsDone(); + replay(); + + trackDataHub.unregisterTrackDataListener(trackDataListener1); + contentObserver.onChange(false); + verifyAndReset(); + + // Unregister the second listener + dataSource.unregisterContentObserver(contentObserver); + replay(); + + trackDataHub.unregisterTrackDataListener(trackDataListener2); + contentObserver.onChange(false); + verifyAndReset(); + } + + /** + * Tests track points table update. + */ + public void testTrackPointsTableUpdate() { + // Register one listener + Capture contentObserverCapture = new Capture(); + dataSource.registerContentObserver( + eq(TrackPointsColumns.CONTENT_URI), capture(contentObserverCapture)); + + FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5); + expect(myTracksProviderUtils.getTrackPointLocationIterator( + eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator); + expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(10L); + trackDataListener1.clearTrackPoints(); + locationIterator.expectLocationsDelivered(trackDataListener1); + trackDataListener1.onNewTrackPointsDone(); + replay(); + + trackDataHub.start(); + trackDataHub.loadTrack(TRACK_ID); + trackDataHub.registerTrackDataListener( + trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE)); + verifyAndReset(); + + // Register a second listener + locationIterator = new FixedSizeLocationIterator(1, 10, 5); + expect(myTracksProviderUtils.getTrackPointLocationIterator( + eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator); + expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(10L); + trackDataListener2.clearTrackPoints(); + locationIterator.expectLocationsDelivered(trackDataListener2); + trackDataListener2.onNewTrackPointsDone(); + replay(); + + trackDataHub.registerTrackDataListener( + trackDataListener2, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE)); + verifyAndReset(); + + // Deliver more points - should go to both listeners without clearing + ContentObserver contentObserver = contentObserverCapture.getValue(); + locationIterator = new FixedSizeLocationIterator(11, 10, 1); + expect(myTracksProviderUtils.getTrackPointLocationIterator( + eq(TRACK_ID), eq(11L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator); + expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(20L); + locationIterator.expectLocationsDelivered(trackDataListener1); + locationIterator.expectLocationsDelivered(trackDataListener2); + trackDataListener1.onNewTrackPointsDone(); + trackDataListener2.onNewTrackPointsDone(); + replay(); + + contentObserver.onChange(false); + verifyAndReset(); + + // Unregister one listener and change track + locationIterator = new FixedSizeLocationIterator(101, 10); + expect(myTracksProviderUtils.getTrackPointLocationIterator( + eq(TRACK_ID + 1), eq(0L), eq(false), isA(LocationFactory.class))) + .andReturn(locationIterator); + expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID + 1)).andReturn(110L); + trackDataListener2.clearTrackPoints(); + locationIterator.expectLocationsDelivered(trackDataListener2); + trackDataListener2.onNewTrackPointsDone(); + replay(); + + trackDataHub.unregisterTrackDataListener(trackDataListener1); + trackDataHub.loadTrack(TRACK_ID + 1); + verifyAndReset(); + } + + /** + * Tests track points table update with registering the same listener. + */ + public void testTrackPointsTableUpdate_reRegister() { + + // Register one listener + Capture contentObserverCapture = new Capture(); + dataSource.registerContentObserver( + eq(TrackPointsColumns.CONTENT_URI), capture(contentObserverCapture)); + + FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5); + expect(myTracksProviderUtils.getTrackPointLocationIterator( + eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator); + expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(10L); + + trackDataListener1.clearTrackPoints(); + locationIterator.expectLocationsDelivered(trackDataListener1); + trackDataListener1.onNewTrackPointsDone(); + replay(); + + trackDataHub.start(); + trackDataHub.loadTrack(TRACK_ID); + trackDataHub.registerTrackDataListener( + trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE)); + verifyAndReset(); + + // Unregister the listener + ContentObserver observer = contentObserverCapture.getValue(); + dataSource.unregisterContentObserver(observer); + replay(); + + trackDataHub.unregisterTrackDataListener(trackDataListener1); + verifyAndReset(); + + // Register again + dataSource.registerContentObserver( + eq(TrackPointsColumns.CONTENT_URI), capture(contentObserverCapture)); + locationIterator = new FixedSizeLocationIterator(1, 10, 5); + expect(myTracksProviderUtils.getTrackPointLocationIterator( + eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator); + expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(10L); + trackDataListener1.clearTrackPoints(); + locationIterator.expectLocationsDelivered(trackDataListener1); + trackDataListener1.onNewTrackPointsDone(); + replay(); + + trackDataHub.registerTrackDataListener( + trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE)); + verifyAndReset(); + } + + /** + * Tests tracks point able change. Register a listener after a track change. + */ + public void testTrackPointsTableUpdate_reRegisterAfterTrackChange() { + + // Register one listener + Capture observerCapture = new Capture(); + dataSource.registerContentObserver( + eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture)); + + FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 10, 5); + expect(myTracksProviderUtils.getTrackPointLocationIterator( + eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator); + expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(10L); + trackDataListener1.clearTrackPoints(); + locationIterator.expectLocationsDelivered(trackDataListener1); + trackDataListener1.onNewTrackPointsDone(); + replay(); + + trackDataHub.start(); + trackDataHub.loadTrack(TRACK_ID); + trackDataHub.registerTrackDataListener( + trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE)); + verifyAndReset(); + + // Unregister the listener + ContentObserver observer = observerCapture.getValue(); + dataSource.unregisterContentObserver(observer); + replay(); + + trackDataHub.unregisterTrackDataListener(trackDataListener1); + verifyAndReset(); + + // Register the listener after a new track + dataSource.registerContentObserver( + eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture)); + locationIterator = new FixedSizeLocationIterator(1, 10); + expect(myTracksProviderUtils.getTrackPointLocationIterator( + eq(TRACK_ID + 1), eq(0L), eq(false), isA(LocationFactory.class))) + .andReturn(locationIterator); + expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID + 1)).andReturn(10L); + trackDataListener1.clearTrackPoints(); + locationIterator.expectLocationsDelivered(trackDataListener1); + trackDataListener1.onNewTrackPointsDone(); + replay(); + + trackDataHub.loadTrack(TRACK_ID + 1); + trackDataHub.registerTrackDataListener( + trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE)); + verifyAndReset(); + } + + /** + * Tests track points table update with large track sampling. + */ + public void testTrackPointsTableUpdate_largeTrackSampling() { + Capture contentObserverCapture = new Capture(); + dataSource.registerContentObserver( + eq(TrackPointsColumns.CONTENT_URI), capture(contentObserverCapture)); + + expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(200L); + AndroidMock.expectLastCall().anyTimes(); + FixedSizeLocationIterator locationIterator1 = new FixedSizeLocationIterator( + 1, 200, 4, 25, 71, 120); + expect(myTracksProviderUtils.getTrackPointLocationIterator( + eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator1); + FixedSizeLocationIterator locationIterator2 = new FixedSizeLocationIterator( + 1, 200, 4, 25, 71, 120); + expect(myTracksProviderUtils.getTrackPointLocationIterator( + eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator2); + + trackDataListener1.clearTrackPoints(); + locationIterator1.expectSampledLocationsDelivered(trackDataListener1, 4, false); + trackDataListener1.onNewTrackPointsDone(); + trackDataListener2.clearTrackPoints(); + locationIterator2.expectSampledLocationsDelivered(trackDataListener2, 4, true); + trackDataListener2.onNewTrackPointsDone(); + replay(); + + trackDataHub.start(); + trackDataHub.loadTrack(TRACK_ID); + trackDataHub.registerTrackDataListener( + trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE)); + trackDataHub.registerTrackDataListener(trackDataListener2, EnumSet.of( + TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE, TrackDataType.SAMPLED_OUT_TRACK_POINTS_TABLE)); + verifyAndReset(); + } + + /** + * Tests track points table update with resampling. + */ + public void testTrackPointsTableUpdate_resampling() { + Capture observerCapture = new Capture(); + dataSource.registerContentObserver( + eq(TrackPointsColumns.CONTENT_URI), capture(observerCapture)); + + // Deliver 30 points (no sampling happens) + FixedSizeLocationIterator locationIterator = new FixedSizeLocationIterator(1, 30, 5); + expect(myTracksProviderUtils.getTrackPointLocationIterator( + eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator); + expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(30L); + + trackDataListener1.clearTrackPoints(); + locationIterator.expectLocationsDelivered(trackDataListener1); + trackDataListener1.onNewTrackPointsDone(); + replay(); + + trackDataHub.start(); + trackDataHub.loadTrack(TRACK_ID); + trackDataHub.registerTrackDataListener( + trackDataListener1, EnumSet.of(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE)); + verifyAndReset(); + + // Now deliver 30 more (incrementally sampled) + ContentObserver observer = observerCapture.getValue(); + locationIterator = new FixedSizeLocationIterator(31, 30); + expect(myTracksProviderUtils.getTrackPointLocationIterator( + eq(TRACK_ID), eq(31L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator); + expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(60L); + locationIterator.expectSampledLocationsDelivered(trackDataListener1, 2, false); + trackDataListener1.onNewTrackPointsDone(); + replay(); + + observer.onChange(false); + verifyAndReset(); + + // Now another 30 (triggers resampling) + locationIterator = new FixedSizeLocationIterator(1, 90); + expect(myTracksProviderUtils.getTrackPointLocationIterator( + eq(TRACK_ID), eq(0L), eq(false), isA(LocationFactory.class))).andReturn(locationIterator); + expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID)).andReturn(90L); + trackDataListener1.clearTrackPoints(); + locationIterator.expectSampledLocationsDelivered(trackDataListener1, 2, false); + trackDataListener1.onNewTrackPointsDone(); + replay(); + + observer.onChange(false); + verifyAndReset(); + } + + /** + * Tests preferences change. + */ + public void testPreferencesChange() throws Exception { + + // Register two listeners + PreferencesUtils.setString( + context, R.string.stats_rate_key, PreferencesUtils.STATS_RATE_DEFAULT); + PreferencesUtils.setString( + context, R.string.stats_units_key, PreferencesUtils.STATS_UNITS_DEFAULT); + PreferencesUtils.setInt(context, R.string.recording_gps_accuracy_key, + PreferencesUtils.RECORDING_GPS_ACCURACY_DEFAULT); + PreferencesUtils.setInt(context, R.string.recording_distance_interval_key, + PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT); + + dataSource.registerOnSharedPreferenceChangeListener(capture(preferenceChangeListenerCapture)); + expect(trackDataListener1.onMetricUnitsChanged(true)).andReturn(false); + expect(trackDataListener1.onReportSpeedChanged(true)).andReturn(false); + expect( + trackDataListener1.onRecordingGpsAccuracy(PreferencesUtils.RECORDING_GPS_ACCURACY_DEFAULT)) + .andReturn(false); + expect(trackDataListener1.onRecordingDistanceIntervalChanged( + PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT)).andReturn(false); + expect(trackDataListener1.onMapTypeChanged(PreferencesUtils.MAP_TYPE_DEFAUlT)).andReturn(false); + + expect(trackDataListener2.onMetricUnitsChanged(true)).andReturn(false); + expect(trackDataListener2.onReportSpeedChanged(true)).andReturn(false); + expect( + trackDataListener2.onRecordingGpsAccuracy(PreferencesUtils.RECORDING_GPS_ACCURACY_DEFAULT)) + .andReturn(false); + expect(trackDataListener2.onRecordingDistanceIntervalChanged( + PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT)).andReturn(false); + expect(trackDataListener2.onMapTypeChanged(PreferencesUtils.MAP_TYPE_DEFAUlT)).andReturn(false); + replay(); + + trackDataHub.start(); + trackDataHub.registerTrackDataListener( + trackDataListener1, EnumSet.of(TrackDataType.PREFERENCE)); + trackDataHub.registerTrackDataListener( + trackDataListener2, EnumSet.of(TrackDataType.PREFERENCE)); + verifyAndReset(); + + // Change report speed to false + expect(trackDataListener1.onReportSpeedChanged(false)).andReturn(false); + expect(trackDataListener2.onReportSpeedChanged(false)).andReturn(false); + replay(); + + PreferencesUtils.setString( + context, R.string.stats_rate_key, context.getString(R.string.stats_rate_pace)); + OnSharedPreferenceChangeListener listener = preferenceChangeListenerCapture.getValue(); + listener.onSharedPreferenceChanged( + sharedPreferences, PreferencesUtils.getKey(context, R.string.stats_rate_key)); + verifyAndReset(); + + // Change metric units to false + expect(trackDataListener1.onMetricUnitsChanged(false)).andReturn(false); + expect(trackDataListener2.onMetricUnitsChanged(false)).andReturn(false); + replay(); + + String imperialUnits = context.getString(R.string.stats_units_imperial); + PreferencesUtils.setString(context, R.string.stats_units_key, imperialUnits); + listener.onSharedPreferenceChanged( + sharedPreferences, PreferencesUtils.getKey(context, R.string.stats_units_key)); + verifyAndReset(); + } + + /** + * Replays mocks. + */ + private void replay() { + AndroidMock.replay(myTracksProviderUtils, dataSource, trackDataListener1, trackDataListener2); + } + + /** + * Verifies and resets mocks. + */ + private void verifyAndReset() { + AndroidMock.verify(myTracksProviderUtils, dataSource, trackDataListener1, trackDataListener2); + AndroidMock.reset(myTracksProviderUtils, dataSource, trackDataListener1, trackDataListener2); + } + + /** + * Fixed size cursor answer. + * + * @author Jimmy Shih + */ + private static class FixedSizeCursorAnswer implements IAnswer { + private final int size; + + public FixedSizeCursorAnswer(int size) { + this.size = size; + } + + @Override + public Cursor answer() throws Throwable { + MatrixCursor cursor = new MatrixCursor(new String[] { BaseColumns._ID }); + for (long i = 0; i < size; i++) { + cursor.addRow(new Object[] { i }); + } + return cursor; + } + } + + /** + * Fixed size location iterator. + * + * @author Jimmy Shih + */ + private static class FixedSizeLocationIterator implements LocationIterator { + private final long startId; + private final Location[] locations; + private final Set splitIndexSet = new HashSet(); + private int currentIndex = -1; + + public FixedSizeLocationIterator(long startId, int size) { + this(startId, size, null); + } + + public FixedSizeLocationIterator(long startId, int size, int... splitIndexes) { + this.startId = startId; + this.locations = new Location[size]; + + for (int i = 0; i < size; i++) { + Location location = new Location("gps"); + location.setLatitude(-15.0 + i / 1000.0); + location.setLongitude(37 + i / 1000.0); + location.setAltitude(i); + locations[i] = location; + } + + if (splitIndexes != null) { + for (int splitIndex : splitIndexes) { + splitIndexSet.add(splitIndex); + + Location splitLocation = locations[splitIndex]; + splitLocation.setLatitude(100.0); + splitLocation.setLongitude(200.0); + } + } + } + + public void expectLocationsDelivered(TrackDataListener listener) { + for (int i = 0; i < locations.length; i++) { + if (splitIndexSet.contains(i)) { + listener.onSegmentSplit(locations[i]); + } else { + listener.onSampledInTrackPoint(locations[i]); + } + } + } + + public void expectSampledLocationsDelivered( + TrackDataListener listener, int sampleFrequency, boolean includeSampledOut) { + boolean includeNext = false; + for (int i = 0; i < locations.length; i++) { + if (splitIndexSet.contains(i)) { + listener.onSegmentSplit(locations[i]); + includeNext = true; + } else if (includeNext || (i % sampleFrequency == 0)) { + listener.onSampledInTrackPoint(locations[i]); + includeNext = false; + } else if (includeSampledOut) { + listener.onSampledOutTrackPoint(locations[i]); + } + } + } + + @Override + public boolean hasNext() { + return currentIndex < locations.length - 1; + } + + @Override + public Location next() { + currentIndex++; + return locations[currentIndex]; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + @Override + public long getLocationId() { + return startId + currentIndex; + } + + @Override + public void close() { + // Do nothing + } + } + + /** + * Tests the method {@link TrackDataHub#start()}. + */ + public void testRegisterTracksTableListener() { + Capture observerCapture = new Capture(); + dataSource.registerContentObserver(eq(TracksColumns.CONTENT_URI), capture(observerCapture)); + Track track = TrackStubUtils.createTrack(1); + expect(myTracksProviderUtils.getTrack(capture(new Capture()))).andReturn(track); + // Make the track id is unique. + PreferencesUtils.setLong(context, R.string.recording_track_id_key, System.currentTimeMillis()); + trackDataListener1.onTrackUpdated(track); + replay(); + trackDataHub.start(); + trackDataHub.registerTrackDataListener( + trackDataListener1, EnumSet.of(TrackDataType.TRACKS_TABLE)); + verifyAndReset(); + } + + /** + * Tests the method {@link TrackDataHub#start()}. + */ + public void testRegisterWaypointsTableListener() { + Capture observerCapture = new Capture(); + dataSource.registerContentObserver(eq(WaypointsColumns.CONTENT_URI), capture(observerCapture)); + expect(myTracksProviderUtils.getWaypointCursor( + capture(new Capture()), capture(new Capture()), + capture(new Capture()))).andReturn(null); + trackDataListener1.clearWaypoints(); + trackDataListener1.onNewWaypointsDone(); + replay(); + trackDataHub.start(); + trackDataHub.registerTrackDataListener( + trackDataListener1, EnumSet.of(TrackDataType.WAYPOINTS_TABLE)); + verifyAndReset(); + } + + /** + * Tests the method {@link TrackDataHub#notifyPreferenceChanged(String)} when + * the key is R.string.min_required_accuracy_key. + */ + public void testNotifyPreferenceChanged_minRequiredAccuracy() { + int value = 1; + PreferencesUtils.setInt(context, R.string.recording_gps_accuracy_key, value); + trackDataHub.notifyPreferenceChanged(PreferencesUtils + .getKey(context, R.string.recording_gps_accuracy_key)); + assertEquals(value, trackDataHub.getRecordingGpsAccuracy()); + PreferencesUtils.setInt(context, R.string.recording_gps_accuracy_key, value + 1); + trackDataHub.notifyPreferenceChanged(PreferencesUtils + .getKey(context, R.string.recording_gps_accuracy_key)); + assertEquals(value + 1, trackDataHub.getRecordingGpsAccuracy()); + } + + /** + * Tests the method {@link TrackDataHub#notifyPreferenceChanged(String)} when + * the key is R.string.metric_units_key. + */ + public void testNotifyPreferenceChanged_metricUnitsNoNotify() { + String imperialUnits = context.getString(R.string.stats_units_imperial); + + PreferencesUtils.setString(context, R.string.stats_units_key, imperialUnits); + trackDataHub.notifyPreferenceChanged( + PreferencesUtils.getKey(context, R.string.stats_units_key)); + assertEquals(false, trackDataHub.isMetricUnits()); + PreferencesUtils.setString( + context, R.string.stats_units_key, PreferencesUtils.STATS_UNITS_DEFAULT); + trackDataHub.notifyPreferenceChanged( + PreferencesUtils.getKey(context, R.string.stats_units_key)); + assertEquals(true, trackDataHub.isMetricUnits()); + } + + + /** + * Tests the method {@link TrackDataHub#notifyPreferenceChanged(String)} when + * the key is R.string.metric_units_key. + */ + public void testNotifyPreferenceChanged_reportSpeedNoNotify() { + String value = context.getString(R.string.stats_rate_pace); + PreferencesUtils.setString(context, R.string.stats_rate_key, value); + trackDataHub.notifyPreferenceChanged(PreferencesUtils + .getKey(context, R.string.stats_rate_key)); + assertEquals(false, trackDataHub.isReportSpeed()); + + value = context.getString(R.string.stats_rate_speed); + PreferencesUtils.setString(context, R.string.stats_rate_key, value); + trackDataHub.notifyPreferenceChanged(PreferencesUtils + .getKey(context, R.string.stats_rate_key)); + assertEquals(true, trackDataHub.isReportSpeed()); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/content/WaypointCreationRequestTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/content/WaypointCreationRequestTest.java new file mode 100644 index 000000000..9bf8e8a67 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/content/WaypointCreationRequestTest.java @@ -0,0 +1,58 @@ +/* + * 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. + */ +package com.google.android.apps.mytracks.content; + +import com.google.android.apps.mytracks.content.Waypoint.WaypointType; + +import android.os.Parcel; +import android.test.AndroidTestCase; + +/** + * Tests for the WaypointCreationRequest class. + * {@link WaypointCreationRequest} + * + * @author Sandor Dornbush + */ +public class WaypointCreationRequestTest extends AndroidTestCase { + + public void testTypeParceling() { + WaypointCreationRequest original = WaypointCreationRequest.DEFAULT_WAYPOINT; + Parcel p = Parcel.obtain(); + original.writeToParcel(p, 0); + p.setDataPosition(0); + WaypointCreationRequest copy = WaypointCreationRequest.CREATOR.createFromParcel(p); + assertEquals(original.getType(), copy.getType()); + assertFalse(copy.isTrackStatistics()); + assertNull(copy.getName()); + assertNull(copy.getDescription()); + assertNull(copy.getIconUrl()); + } + + public void testAllAttributesParceling() { + WaypointCreationRequest original = new WaypointCreationRequest( + WaypointType.WAYPOINT, false, "name", "category", "description", "img.png", null); + Parcel p = Parcel.obtain(); + original.writeToParcel(p, 0); + p.setDataPosition(0); + WaypointCreationRequest copy = WaypointCreationRequest.CREATOR.createFromParcel(p); + assertEquals(original.getType(), copy.getType()); + assertFalse(copy.isTrackStatistics()); + assertEquals("name", copy.getName()); + assertEquals("category", copy.getCategory()); + assertEquals("description", copy.getDescription()); + assertEquals("img.png", copy.getIconUrl()); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/fragments/ChartFragmentTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/fragments/ChartFragmentTest.java new file mode 100644 index 000000000..7c0d781a1 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/fragments/ChartFragmentTest.java @@ -0,0 +1,352 @@ +/* + * Copyright 2012 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.fragments; + +import com.google.android.apps.mytracks.ChartView; +import com.google.android.apps.mytracks.TrackStubUtils; +import com.google.android.apps.mytracks.content.MyTracksLocation; +import com.google.android.apps.mytracks.content.Sensor; +import com.google.android.apps.mytracks.content.Sensor.SensorDataSet; +import com.google.android.apps.mytracks.util.UnitConversions; + +import android.location.Location; +import android.test.AndroidTestCase; + +/** + * Tests {@link ChartFragment}. + * + * @author Youtao Liu + */ +public class ChartFragmentTest extends AndroidTestCase { + + private static final double HOURS_PER_UNIT = 60.0; + + private ChartFragment chartFragment; + + @Override + protected void setUp() throws Exception { + chartFragment = new ChartFragment(); + chartFragment.setChartView(new ChartView(getContext())); + chartFragment.setTripStatisticsUpdater(TrackStubUtils.INITIAL_TIME); + } + + /** + * Tests the logic to get the incorrect values of sensor in {@link ChartFragment#fillDataPoint(Location, + * double[])} + */ + public void testFillDataPoint_sensorIncorrect() { + MyTracksLocation myTracksLocation = TrackStubUtils.createMyTracksLocation(); + + // No input. + double[] point = fillDataPointTestHelper(myTracksLocation); + assertEquals(Double.NaN, point[ChartView.HEART_RATE_SERIES + 1]); + assertEquals(Double.NaN, point[ChartView.CADENCE_SERIES + 1]); + assertEquals(Double.NaN, point[ChartView.POWER_SERIES + 1]); + + // Input incorrect state. + // Creates SensorData. + Sensor.SensorData.Builder heartRateData = Sensor.SensorData.newBuilder() + .setValue(100).setState(Sensor.SensorState.NONE); + Sensor.SensorData.Builder cadenceData = Sensor.SensorData.newBuilder() + .setValue(101).setState(Sensor.SensorState.NONE); + Sensor.SensorData.Builder powerData = Sensor.SensorData.newBuilder() + .setValue(102).setState(Sensor.SensorState.NONE); + + // Creates SensorDataSet. + SensorDataSet sensorDataSet = myTracksLocation.getSensorDataSet(); + sensorDataSet = sensorDataSet.toBuilder() + .setHeartRate(heartRateData).setCadence(cadenceData).setPower(powerData).build(); + myTracksLocation.setSensorDataSet(sensorDataSet); + // Test. + point = fillDataPointTestHelper(myTracksLocation); + assertEquals(Double.NaN, point[ChartView.HEART_RATE_SERIES + 1]); + assertEquals(Double.NaN, point[ChartView.CADENCE_SERIES + 1]); + assertEquals(Double.NaN, point[ChartView.POWER_SERIES + 1]); + } + + /** + * Tests the logic to get the correct values of sensor in {@link ChartFragment#fillDataPoint(Location, + * double[])}. + */ + public void testFillDataPoint_sensorCorrect() { + MyTracksLocation myTracksLocation = TrackStubUtils.createMyTracksLocation(); + // No input. + double[] point = fillDataPointTestHelper(myTracksLocation); + assertEquals(Double.NaN, point[ChartView.HEART_RATE_SERIES + 1]); + assertEquals(Double.NaN, point[ChartView.CADENCE_SERIES + 1]); + assertEquals(Double.NaN, point[ChartView.POWER_SERIES + 1]); + + // Creates SensorData. + Sensor.SensorData.Builder heartRateData = Sensor.SensorData.newBuilder() + .setValue(100).setState(Sensor.SensorState.SENDING); + Sensor.SensorData.Builder cadenceData = Sensor.SensorData.newBuilder() + .setValue(101).setState(Sensor.SensorState.SENDING); + Sensor.SensorData.Builder powerData = Sensor.SensorData.newBuilder() + .setValue(102).setState(Sensor.SensorState.SENDING); + + // Creates SensorDataSet. + SensorDataSet sensorDataSet = myTracksLocation.getSensorDataSet(); + sensorDataSet = sensorDataSet.toBuilder() + .setHeartRate(heartRateData).setCadence(cadenceData).setPower(powerData).build(); + myTracksLocation.setSensorDataSet(sensorDataSet); + // Test. + point = fillDataPointTestHelper(myTracksLocation); + assertEquals(100.0, point[ChartView.HEART_RATE_SERIES + 1]); + assertEquals(101.0, point[ChartView.CADENCE_SERIES + 1]); + assertEquals(102.0, point[ChartView.POWER_SERIES + 1]); + } + + /** + * Tests the logic to get the value of metric Distance in {@link ChartFragment#fillDataPoint(Location, + * double[])}. + */ + public void testFillDataPoint_distanceMetric() { + // By distance. + chartFragment.setChartByDistance(true); + // Resets last location and writes first location. + MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation(); + double[] point = fillDataPointTestHelper(myTracksLocation1); + assertEquals(0.0, point[0]); + + // The second is a same location, just different time. + MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation(); + point = fillDataPointTestHelper(myTracksLocation2); + assertEquals(0.0, point[0]); + + // The third location is a new location, and use metric. + MyTracksLocation myTracksLocation3 = TrackStubUtils.createMyTracksLocation(); + myTracksLocation3.setLatitude(23); + point = fillDataPointTestHelper(myTracksLocation3); + + // Computes the distance between Latitude 22 and 23. + float[] results = new float[4]; + Location.distanceBetween(myTracksLocation2.getLatitude(), myTracksLocation2.getLongitude(), + myTracksLocation3.getLatitude(), myTracksLocation3.getLongitude(), results); + double distance1 = results[0] * UnitConversions.M_TO_KM; + assertEquals(distance1, point[0]); + + // The fourth location is a new location, and use metric. + MyTracksLocation myTracksLocation4 = TrackStubUtils.createMyTracksLocation(); + myTracksLocation4.setLatitude(24); + point = fillDataPointTestHelper(myTracksLocation4); + + // Computes the distance between Latitude 23 and 24. + Location.distanceBetween(myTracksLocation3.getLatitude(), myTracksLocation3.getLongitude(), + myTracksLocation4.getLatitude(), myTracksLocation4.getLongitude(), results); + double distance2 = results[0] * UnitConversions.M_TO_KM; + assertEquals((distance1 + distance2), point[0]); + } + + /** + * Tests the logic to get the value of imperial Distance in {@link ChartFragment#fillDataPoint(Location, + * double[])}. + */ + public void testFillDataPoint_distanceImperial() { + // By distance. + chartFragment.setChartByDistance(true); + // Setups to use imperial. + chartFragment.setMetricUnits(false); + + // The first is a same location, just different time. + MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation(); + double[] point = fillDataPointTestHelper(myTracksLocation1); + assertEquals(0.0, point[0]); + + // The second location is a new location, and use imperial. + MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation(); + myTracksLocation2.setLatitude(23); + point = fillDataPointTestHelper(myTracksLocation2); + + /* + * Computes the distance between Latitude 22 and 23. And for we set using + * imperial, the distance should be multiplied by UnitConversions.KM_TO_MI. + */ + float[] results = new float[4]; + Location.distanceBetween(myTracksLocation1.getLatitude(), myTracksLocation1.getLongitude(), + myTracksLocation2.getLatitude(), myTracksLocation2.getLongitude(), results); + double distance1 = results[0] * UnitConversions.M_TO_KM * UnitConversions.KM_TO_MI; + assertEquals(distance1, point[0]); + + // The third location is a new location, and use imperial. + MyTracksLocation myTracksLocation3 = TrackStubUtils.createMyTracksLocation(); + myTracksLocation3.setLatitude(24); + point = fillDataPointTestHelper(myTracksLocation3); + + /* + * Computes the distance between Latitude 23 and 24. And for we set using + * imperial, the distance should be multiplied by UnitConversions.KM_TO_MI. + */ + Location.distanceBetween(myTracksLocation2.getLatitude(), myTracksLocation2.getLongitude(), + myTracksLocation3.getLatitude(), myTracksLocation3.getLongitude(), results); + double distance2 = results[0] * UnitConversions.M_TO_KM * UnitConversions.KM_TO_MI; + assertEquals(distance1 + distance2, point[0]); + } + + /** + * Tests the logic to get the values of time in {@link ChartFragment#fillDataPoint(Location, + * double[])}. + */ + public void testFillDataPoint_time() { + // By time + chartFragment.setChartByDistance(false); + MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation(); + double[] point = fillDataPointTestHelper(myTracksLocation1); + assertEquals(0.0, point[0]); + long timeSpan = 222; + MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation(); + myTracksLocation2.setTime(myTracksLocation1.getTime() + timeSpan); + point = fillDataPointTestHelper(myTracksLocation2); + assertEquals((double) timeSpan, point[0]); + } + + /** + * Tests the logic to get the value of elevation in {@link ChartFragment#fillDataPoint(Location, + * double[])} by one and two points. + */ + public void testFillDataPoint_elevation() { + MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation(); + + /* + * At first, clear old points of elevation, so give true to the second + * parameter. Then only one value INITIALLONGTITUDE in buffer. + */ + double[] point = fillDataPointTestHelper(myTracksLocation1); + assertEquals(TrackStubUtils.INITIAL_ALTITUDE, point[ChartView.ELEVATION_SERIES + 1]); + + /* + * Send another value to buffer, now there are two values, INITIALALTITUDE + * and INITIALALTITUDE * 2. + */ + MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation(); + myTracksLocation2.setAltitude(TrackStubUtils.INITIAL_ALTITUDE * 2); + point = fillDataPointTestHelper(myTracksLocation2); + assertEquals((TrackStubUtils.INITIAL_ALTITUDE + TrackStubUtils.INITIAL_ALTITUDE * 2) / 2.0, + point[ChartView.ELEVATION_SERIES + 1]); + } + + /** + * Tests the logic to get the value of speed in {@link ChartFragment#fillDataPoint(Location, + * double[])}. In this test, firstly remove all + * points in memory, and then fill in two points one by one. The speed values + * of these points are 129, 130. + */ + public void testFillDataPoint_speed() { + /* + * At first, clear old points of speed, so give true to the second + * parameter. It will not be filled in to the speed buffer. + */ + MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation(); + myTracksLocation1.setSpeed(128.5f); + double[] point = fillDataPointTestHelper(myTracksLocation1); + assertEquals(0.0, point[ChartView.SPEED_SERIES + 1]); + + /* + * Tests the logic when both metricUnits and reportSpeed are true.This + * location will be filled into speed buffer. + */ + MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation(); + + /* + * Add a time span here to make sure the second point is valid, the value + * 222 here is doesn't matter. + */ + myTracksLocation2.setTime(myTracksLocation1.getTime() + 222); + myTracksLocation2.setSpeed(130); + point = fillDataPointTestHelper(myTracksLocation2); + assertEquals(130.0 * UnitConversions.MS_TO_KMH, point[ChartView.SPEED_SERIES + 1]); + } + + /** + * Tests the logic to compute speed when use Imperial. + */ + public void testFillDataPoint_speedImperial() { + // Setups to use imperial. + chartFragment.setMetricUnits(false); + + // First data point is not added to the speed buffer + MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation(); + myTracksLocation1.setSpeed(100.0f); + double[] point = fillDataPointTestHelper(myTracksLocation1); + assertEquals(0.0, point[ChartView.SPEED_SERIES + 1]); + + MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation(); + + /* + * Add a time span here to make sure the second point is valid and the speed + * is valid. Speed is valid if: speedDifference > Constants.MAX_ACCELERATION + * * timeDifference speedDifference = 102 -100 timeDifference = 222 + */ + myTracksLocation2.setTime(myTracksLocation2.getTime() + 222); + myTracksLocation2.setSpeed(102); + point = fillDataPointTestHelper(myTracksLocation2); + assertEquals(102.0 * UnitConversions.MS_TO_KMH * UnitConversions.KM_TO_MI, + point[ChartView.SPEED_SERIES + 1]); + } + + /** + * Tests the logic to get pace value when reportSpeed is false. + */ + public void testFillDataPoint_pace_nonZeroSpeed() { + // Setups reportSpeed to false. + chartFragment.setReportSpeed(false); + + // First data point is not added to the speed buffer + MyTracksLocation myTracksLocation1 = TrackStubUtils.createMyTracksLocation(); + myTracksLocation1.setSpeed(100.0f); + double[] point = fillDataPointTestHelper(myTracksLocation1); + assertEquals(0.0, point[ChartView.SPEED_SERIES + 1]); + + MyTracksLocation myTracksLocation2 = TrackStubUtils.createMyTracksLocation(); + + /* + * Add a time span here to make sure the second point is valid and the speed + * is valid. Speed is valid if: speedDifference > Constants.MAX_ACCELERATION + * * timeDifference speedDifference = 102 -100 timeDifference = 222 + */ + myTracksLocation2.setTime(myTracksLocation2.getTime() + 222); + myTracksLocation2.setSpeed(102); + point = fillDataPointTestHelper(myTracksLocation2); + assertEquals( + HOURS_PER_UNIT / (102.0 * UnitConversions.MS_TO_KMH), point[ChartView.PACE_SERIES + 1]); + } + + /** + * Tests the logic to get pace value when reportSpeed is false and average + * speed is zero. + */ + public void testFillDataPoint_pace_zeroSpeed() { + // Setups reportSpeed to false. + chartFragment.setReportSpeed(false); + MyTracksLocation myTracksLocation = TrackStubUtils.createMyTracksLocation(); + myTracksLocation.setSpeed(0); + double[] point = fillDataPointTestHelper(myTracksLocation); + assertEquals(0.0, point[ChartView.PACE_SERIES + 1]); + } + + /** + * Helper method to test fillDataPoint. + * + * @param location location to fill + * @return data of this location + */ + private double[] fillDataPointTestHelper(Location location) { + double[] point = new double[ChartView.NUM_SERIES + 1]; + chartFragment.fillDataPoint(location, point); + return point; + } + +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/backup/PreferenceBackupHelperTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/backup/PreferenceBackupHelperTest.java new file mode 100644 index 000000000..c610fd651 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/backup/PreferenceBackupHelperTest.java @@ -0,0 +1,212 @@ +/* + * 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. + */ +package com.google.android.apps.mytracks.io.backup; + +import com.google.android.apps.mytracks.util.ApiAdapterFactory; + +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.test.AndroidTestCase; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * Tests for {@link PreferenceBackupHelper}. + * + * @author Rodrigo Damazio + */ +public class PreferenceBackupHelperTest extends AndroidTestCase { + private Map preferenceValues; + private SharedPreferences preferences; + private PreferenceBackupHelper preferenceBackupHelper; + + /** + * Mock shared preferences editor which does not persist state. + */ + private class MockPreferenceEditor implements SharedPreferences.Editor { + private Map newPreferences = new HashMap(preferenceValues); + + @Override + public Editor clear() { + newPreferences.clear(); + return this; + } + + @Override + public boolean commit() { + apply(); + return true; + } + + @Override + public void apply() { + preferenceValues = newPreferences; + } + + @Override + public Editor putBoolean(String key, boolean value) { + return put(key, value); + } + + @Override + public Editor putFloat(String key, float value) { + return put(key, value); + } + + @Override + public Editor putInt(String key, int value) { + return put(key, value); + } + + @Override + public Editor putLong(String key, long value) { + return put(key, value); + } + + @Override + public Editor putString(String key, String value) { + return put(key, value); + } + + public Editor putStringSet(String key, Set value) { + return put(key, value); + } + + private Editor put(String key, T value) { + newPreferences.put(key, value); + return this; + } + + @Override + public Editor remove(String key) { + newPreferences.remove(key); + return this; + } + } + + /** + * Mock shared preferences which does not persist state. + */ + private class MockPreferences implements SharedPreferences { + @Override + public boolean contains(String key) { + return preferenceValues.containsKey(key); + } + + @Override + public Editor edit() { + return new MockPreferenceEditor(); + } + + @Override + public Map getAll() { + return preferenceValues; + } + + @Override + public boolean getBoolean(String key, boolean defValue) { + return get(key, defValue); + } + + @Override + public float getFloat(String key, float defValue) { + return get(key, defValue); + } + + @Override + public int getInt(String key, int defValue) { + return get(key, defValue); + } + + @Override + public long getLong(String key, long defValue) { + return get(key, defValue); + } + + @Override + public String getString(String key, String defValue) { + return get(key, defValue); + } + + public Set getStringSet(String key, Set defValue) { + return get(key, defValue); + } + + @Override + public void registerOnSharedPreferenceChangeListener( + OnSharedPreferenceChangeListener listener) { + throw new UnsupportedOperationException(); + } + + @Override + public void unregisterOnSharedPreferenceChangeListener( + OnSharedPreferenceChangeListener listener) { + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("unchecked") + private T get(String key, T defValue) { + Object value = preferenceValues.get(key); + if (value == null) return defValue; + return (T) value; + } + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + + preferenceValues = new HashMap(); + preferences = new MockPreferences(); + preferenceBackupHelper = new PreferenceBackupHelper(getContext()); + } + + public void testExportImportPreferences() throws Exception { + // Populate with some initial values + Editor editor = preferences.edit(); + editor.clear(); + editor.putBoolean("bool1", true); + editor.putBoolean("bool2", false); + editor.putFloat("flt1", 3.14f); + editor.putInt("int1", 42); + editor.putLong("long1", 123456789L); + editor.putString("str1", "lolcat"); + ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(editor); + + // Export it + byte[] exported = preferenceBackupHelper.exportPreferences(preferences); + + // Mess with the previous values + editor = preferences.edit(); + editor.clear(); + editor.putString("str2", "Shouldn't be there after restore"); + editor.putBoolean("bool2", true); + ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(editor); + + // Import it back + preferenceBackupHelper.importPreferences(exported, preferences); + + assertFalse(preferences.contains("str2")); + assertTrue(preferences.getBoolean("bool1", false)); + assertFalse(preferences.getBoolean("bool2", true)); + assertEquals(3.14f, preferences.getFloat("flt1", 0.0f)); + assertEquals(42, preferences.getInt("int1", 0)); + assertEquals(123456789L, preferences.getLong("long1", 0)); + assertEquals("lolcat", preferences.getString("str1", "")); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/exporter/CsvTrackWriterTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/exporter/CsvTrackWriterTest.java new file mode 100644 index 000000000..e05e8caba --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/exporter/CsvTrackWriterTest.java @@ -0,0 +1,90 @@ +/* + * Copyright 2012 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.io.file.exporter; + +import com.google.android.apps.mytracks.io.file.exporter.CsvTrackWriter; + + +/** + * Tests for {@link CsvTrackWriter}. + * + * @author Rodrigo Damazio + */ +public class CsvTrackWriterTest extends TrackWriterTest { + + private static final String BEGIN_TAG = "\""; + private static final String END_TAG = "\"\n"; + private static final String SEPARATOR = "\",\""; + + public void testCsvOutput() throws Exception { + String expectedTrackHeader = getExpectedLine( + "Name", "Activity type", "Description"); + String expectedTrack = getExpectedLine(TRACK_NAME, TRACK_CATEGORY, TRACK_DESCRIPTION); + String expectedMarkerHeader = getExpectedLine("Name", + "Marker type", + "Description", + "Latitude (deg)", + "Longitude (deg)", + "Altitude (m)", + "Bearing (deg)", + "Accuracy (m)", + "Speed (m/s)", + "Time"); + String expectedMarker1 = getExpectedLine(WAYPOINT1_NAME, WAYPOINT1_CATEGORY, + WAYPOINT1_DESCRIPTION, "1.0", "-1.0", "10.0", "100.0", "1,000", "10,000", + "1970-01-01T00:01:40.000Z"); + String expectedMarker2 = getExpectedLine(WAYPOINT2_NAME, WAYPOINT2_CATEGORY, + WAYPOINT2_DESCRIPTION, "2.0", "-2.0", "20.0", "200.0", "2,000", "20,000", + "1970-01-01T00:03:20.000Z"); + String expectedPointHeader = getExpectedLine("Segment", "Point", "Latitude (deg)", + "Longitude (deg)", "Altitude (m)", "Bearing (deg)", "Accuracy (m)", "Speed (m/s)", "Time", + "Power (W)", "Cadence (rpm)", "Heart rate (bpm)"); + String expectedPoint1 = getExpectedLine("1", "1", "0.0", "0.0", "0.0", "0.0", "0", "0", + "1970-01-01T00:00:00.000Z", "100.0", "200.0", "300.0"); + String expectedPoint2 = getExpectedLine("1", "2", "1.0", "-1.0", "10.0", "100.0", "1,000", + "10,000", "1970-01-01T00:01:40.000Z", "101.0", "201.0", "301.0"); + String expectedPoint3 = getExpectedLine("2", "1", "2.0", "-2.0", "20.0", "200.0", "2,000", + "20,000", "1970-01-01T00:03:20.000Z", "102.0", "202.0", "302.0"); + String expectedPoint4 = getExpectedLine("2", "2", "3.0", "-3.0", "30.0", "300.0", "3,000", + "30,000", "1970-01-01T00:05:00.000Z", "103.0", "203.0", "303.0"); + String expected = expectedTrackHeader + expectedTrack + "\n" + + expectedMarkerHeader + expectedMarker1 + expectedMarker2 + "\n" + + expectedPointHeader + expectedPoint1 + expectedPoint2 + expectedPoint3 + expectedPoint4; + + CsvTrackWriter csvTrackWriter = new CsvTrackWriter(getContext()); + assertEquals(expected, writeTrack(csvTrackWriter)); + } + + /** + * Gets the expected CSV line from a list of expected values. + * + * @param values expected values + */ + private String getExpectedLine(String... values) { + StringBuilder builder = new StringBuilder(); + builder.append(BEGIN_TAG); + boolean first = true; + for (String value : values) { + if (!first) { + builder.append(SEPARATOR); + } + first = false; + builder.append(value); + } + builder.append(END_TAG); + return builder.toString(); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/exporter/FileTrackExporterTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/exporter/FileTrackExporterTest.java new file mode 100644 index 000000000..5c524bc2c --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/exporter/FileTrackExporterTest.java @@ -0,0 +1,314 @@ +// Copyright 2010 Google Inc. All Rights Reserved. + +package com.google.android.apps.mytracks.io.file.exporter; + +import com.google.android.apps.mytracks.content.MyTracksProvider; +import com.google.android.apps.mytracks.content.MyTracksProviderUtils; +import com.google.android.apps.mytracks.content.MyTracksProviderUtils.Factory; +import com.google.android.apps.mytracks.content.Track; +import com.google.android.apps.mytracks.content.Waypoint; +import com.google.android.apps.mytracks.services.TrackRecordingServiceTest.MockContext; +import com.google.android.apps.mytracks.testing.TestingProviderUtilsFactory; + +import android.content.Context; +import android.location.Location; +import android.test.AndroidTestCase; +import android.test.RenamingDelegatingContext; +import android.test.mock.MockContentResolver; + +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; + +import org.easymock.EasyMock; +import org.easymock.IArgumentMatcher; +import org.easymock.IMocksControl; + +/** + * Tests for {@link FileTrackExporter}. + * + * @author Rodrigo Damazio + */ +public class FileTrackExporterTest extends AndroidTestCase { + + private static final long TRACK_ID = 1234567L; + private static final String TRACK_NAME = "Swimming across the pacific"; + + private MyTracksProviderUtils myTracksProviderUtils; + private Factory oldProviderUtilsFactory; + + private IMocksControl mocksControl; + + private TrackWriter trackWriter; + private Track[] tracks; + private OutputStream outputStream; + private FileTrackExporter fileTrackExporter; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + MockContentResolver mockContentResolver = new MockContentResolver(); + RenamingDelegatingContext targetContext = new RenamingDelegatingContext( + getContext(), getContext(), "test."); + Context context = new MockContext(mockContentResolver, targetContext); + MyTracksProvider myTracksProvider = new MyTracksProvider(); + myTracksProvider.attachInfo(context, null); + mockContentResolver.addProvider(MyTracksProviderUtils.AUTHORITY, myTracksProvider); + setContext(context); + myTracksProviderUtils = MyTracksProviderUtils.Factory.get(context); + oldProviderUtilsFactory = TestingProviderUtilsFactory.installWithInstance( + myTracksProviderUtils); + + mocksControl = EasyMock.createStrictControl(); + trackWriter = mocksControl.createMock(TrackWriter.class); + + Track track = new Track(); + track.setName(TRACK_NAME); + track.setId(TRACK_ID); + + tracks = new Track[] {track}; + + outputStream = new ByteArrayOutputStream(); + TrackExporterListener trackExporterListener = new TrackExporterListener() { + + @Override + public void onProgressUpdate(int number, int max) { + // Safe to ignore + + } + }; + fileTrackExporter = new FileTrackExporter( + myTracksProviderUtils, tracks, trackWriter, trackExporterListener); + } + + @Override + protected void tearDown() throws Exception { + TestingProviderUtilsFactory.restoreOldFactory(oldProviderUtilsFactory); + super.tearDown(); + } + + /** + * Tests write track with an empty track. + */ + public void testWriteTrack_emptyTrack() throws Exception { + + // Set expected mock behavior + trackWriter.prepare(outputStream); + trackWriter.writeHeader(tracks); + trackWriter.writeBeginTracks(); + trackWriter.writeBeginTrack(tracks[0], null); + trackWriter.writeEndTrack(tracks[0], null); + trackWriter.writeEndTracks(); + trackWriter.writeFooter(); + trackWriter.close(); + + mocksControl.replay(); + assertTrue(fileTrackExporter.writeTrack(outputStream)); + mocksControl.verify(); + } + + /** + * Tests write track with invalid locations. Make sure an empty track is + * written. + */ + public void testWriteTrack_oneInvalidLocation() throws Exception { + + // Add two locations + Location[] locations = { new Location("fake0"), new Location("fake1") }; + fillLocations(locations); + + // Make locations invalid + locations[0].setLatitude(100.0); + locations[1].setLatitude(100.0); + + assertEquals(locations.length, + myTracksProviderUtils.bulkInsertTrackPoint(locations, locations.length, TRACK_ID)); + + // Set expected mock behavior + trackWriter.prepare(outputStream); + trackWriter.writeHeader(tracks); + trackWriter.writeBeginTracks(); + trackWriter.writeBeginTrack(tracks[0], null); + trackWriter.writeEndTrack(tracks[0], null); + trackWriter.writeEndTracks(); + trackWriter.writeFooter(); + trackWriter.close(); + + mocksControl.replay(); + + assertTrue(fileTrackExporter.writeTrack(outputStream)); + mocksControl.verify(); + } + + /** + * Tests write track. + */ + public void testWriteTrack() throws Exception { + + // Add six locations + Location[] locations = { new Location("fake0"), new Location("fake1"), new Location("fake2"), + new Location("fake3"), new Location("fake4"), new Location("fake5") }; + fillLocations(locations); + + // Make location 3 invalid + locations[2].setLatitude(100.0); + + assertEquals(locations.length, + myTracksProviderUtils.bulkInsertTrackPoint(locations, locations.length, TRACK_ID)); + + Waypoint[] waypoints = { new Waypoint(), new Waypoint(), new Waypoint() }; + + for (int i = 0; i < waypoints.length; i++) { + Waypoint waypoint = waypoints[i]; + waypoint.setTrackId(TRACK_ID); + assertNotNull(myTracksProviderUtils.insertWaypoint(waypoint)); + waypoint.setId(i + 1); + } + + trackWriter.prepare(outputStream); + trackWriter.writeHeader(tracks); + + // Expect reading/writing of the waypoints (except the first) + trackWriter.writeBeginWaypoints(tracks[0]); + trackWriter.writeWaypoint(waypointEq(waypoints[1])); + trackWriter.writeWaypoint(waypointEq(waypoints[2])); + trackWriter.writeEndWaypoints(); + + // Begin the track + trackWriter.writeBeginTracks(); + trackWriter.writeBeginTrack(trackEq(tracks[0]), locationEq(locations[0])); + + // Write locations 1-2 + trackWriter.writeOpenSegment(); + trackWriter.writeLocation(locationEq(locations[0])); + trackWriter.writeLocation(locationEq(locations[1])); + trackWriter.writeCloseSegment(); + + // Location 3 is not written - it's invalid + + // Write locations 4-6 + trackWriter.writeOpenSegment(); + trackWriter.writeLocation(locationEq(locations[3])); + trackWriter.writeLocation(locationEq(locations[4])); + trackWriter.writeLocation(locationEq(locations[5])); + trackWriter.writeCloseSegment(); + + // End the track + trackWriter.writeEndTrack(trackEq(tracks[0]), locationEq(locations[5])); + trackWriter.writeEndTracks(); + + trackWriter.writeFooter(); + trackWriter.close(); + + mocksControl.replay(); + + assertTrue(fileTrackExporter.writeTrack(outputStream)); + mocksControl.verify(); + } + + /** + * Waypoint equals. + * + * @param waypoint the waypoint + */ + private Waypoint waypointEq(final Waypoint waypoint) { + EasyMock.reportMatcher(new IArgumentMatcher() { + @Override + public boolean matches(Object object) { + if (object == null || waypoint == null) { + return waypoint == object; + } + Waypoint waypoint2 = (Waypoint) object; + + return waypoint.getId() == waypoint2.getId(); + } + + @Override + public void appendTo(StringBuffer buffer) { + buffer.append("waypointEq("); + buffer.append(waypoint); + buffer.append(")"); + } + }); + return null; + } + + /** + * Location equals. + * + * @param location the location + */ + private Location locationEq(final Location location) { + EasyMock.reportMatcher(new IArgumentMatcher() { + @Override + public boolean matches(Object object) { + if (object == null || location == null) { + return location == object; + } + Location location2 = (Location) object; + + return location.hasAccuracy() == location2.hasAccuracy() + && (!location.hasAccuracy() || location.getAccuracy() == location2.getAccuracy()) + && location.hasAltitude() == location2.hasAltitude() + && (!location.hasAltitude() || location.getAltitude() == location2.getAltitude()) + && location.hasBearing() == location2.hasBearing() + && (!location.hasBearing() || location.getBearing() == location2.getBearing()) + && location.hasSpeed() == location2.hasSpeed() + && (!location.hasSpeed() || location.getSpeed() == location2.getSpeed()) + && location.getLatitude() == location2.getLatitude() + && location.getLongitude() == location2.getLongitude() + && location.getTime() == location2.getTime(); + } + + @Override + public void appendTo(StringBuffer buffer) { + buffer.append("locationEq("); + buffer.append(location); + buffer.append(")"); + } + }); + return null; + } + + /** + * Track equals. + * + * @param track1 the track + */ + private Track trackEq(final Track track1) { + EasyMock.reportMatcher(new IArgumentMatcher() { + @Override + public boolean matches(Object object) { + if (object == null || track1 == null) { + return track1 == object; + } + Track track2 = (Track) object; + + return track1.getName().equals(track2.getName()); + } + + @Override + public void appendTo(StringBuffer buffer) { + buffer.append("trackEq("); + buffer.append(track1); + buffer.append(")"); + } + }); + return null; + } + + /** + * Fills the locations. + * + * @param locations the locations + */ + private void fillLocations(Location... locations) { + assertTrue(locations.length < 90); + for (int i = 0; i < locations.length; i++) { + Location location = locations[i]; + location.setLatitude(i + 1); + location.setLongitude(i + 1); + location.setTime(i + 1000); + } + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/exporter/GpxTrackWriterTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/exporter/GpxTrackWriterTest.java new file mode 100644 index 000000000..35e9f6a14 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/exporter/GpxTrackWriterTest.java @@ -0,0 +1,78 @@ +/* + * 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. + */ +package com.google.android.apps.mytracks.io.file.exporter; + +import com.google.android.apps.mytracks.io.file.exporter.GpxTrackWriter; + +import java.util.List; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * Tests for {@link GpxTrackWriter}. + * + * @author Rodrigo Damazio + */ +public class GpxTrackWriterTest extends TrackWriterTest { + + public void testXmlOutput() throws Exception { + GpxTrackWriter gpxTrackWriter = new GpxTrackWriter(getContext()); + String result = writeTrack(gpxTrackWriter); + Document doc = parseXmlDocument(result); + + Element gpxTag = getChildElement(doc, "gpx"); + Element trackTag = getChildElement(gpxTag, "trk"); + assertEquals(TRACK_NAME, getChildTextValue(trackTag, "name")); + assertEquals(TRACK_DESCRIPTION, getChildTextValue(trackTag, "desc")); + List segmentTags = getChildElements(trackTag, "trkseg", 2); + List segPointTags = getChildElements(segmentTags.get(0), "trkpt", 2); + assertTagMatchesLocation(segPointTags.get(0), "0", "0", "1970-01-01T00:00:00.000Z", "0"); + assertTagMatchesLocation(segPointTags.get(1), "1", "-1", "1970-01-01T00:01:40.000Z", "10"); + + segPointTags = getChildElements(segmentTags.get(1), "trkpt", 2); + assertTagMatchesLocation(segPointTags.get(0), "2", "-2", "1970-01-01T00:03:20.000Z", "20"); + assertTagMatchesLocation(segPointTags.get(1), "3", "-3", "1970-01-01T00:05:00.000Z", "30"); + + List waypointTags = getChildElements(gpxTag, "wpt", 2); + Element wptTag = waypointTags.get(0); + assertEquals(WAYPOINT1_NAME, getChildTextValue(wptTag, "name")); + assertEquals(WAYPOINT1_DESCRIPTION, getChildTextValue(wptTag, "desc")); + assertTagMatchesLocation(wptTag, "1", "-1", "1970-01-01T00:01:40.000Z", "10"); + + wptTag = waypointTags.get(1); + assertEquals(WAYPOINT2_NAME, getChildTextValue(wptTag, "name")); + assertEquals(WAYPOINT2_DESCRIPTION, getChildTextValue(wptTag, "desc")); + assertTagMatchesLocation(wptTag, "2", "-2", "1970-01-01T00:03:20.000Z", "20"); + } + + /** + * Asserts that the given tag describes a location. + * + * @param tag the tag + * @param latitude the location's latitude + * @param longitude the location's longitude + * @param time the location's time + * @param elevation the location's elevation + */ + private void assertTagMatchesLocation( + Element tag, String latitude, String longitude, String time, String elevation) { + assertEquals(latitude, tag.getAttribute("lat")); + assertEquals(longitude, tag.getAttribute("lon")); + assertEquals(time, getChildTextValue(tag, "time")); + assertEquals(elevation, getChildTextValue(tag, "ele")); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/exporter/KmlTrackWriterTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/exporter/KmlTrackWriterTest.java new file mode 100644 index 000000000..bf0ffd9b8 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/exporter/KmlTrackWriterTest.java @@ -0,0 +1,127 @@ +/* + * 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. + */ +package com.google.android.apps.mytracks.io.file.exporter; + +import com.google.android.apps.mytracks.content.DescriptionGenerator; +import com.google.android.apps.mytracks.content.Track; +import com.google.android.apps.mytracks.stats.TripStatistics; + +import android.location.Location; + +import java.util.List; +import java.util.Vector; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * Tests for {@link KmlTrackWriter}. + * + * @author Rodrigo Damazio + */ +public class KmlTrackWriterTest extends TrackWriterTest { + + private static final String FULL_TRACK_DESCRIPTION = "full track description"; + + /** + * A fake version of {@link DescriptionGenerator} which returns a fixed track + * description, thus not depending on the context. + */ + private class FakeDescriptionGenerator implements DescriptionGenerator { + @Override + public String generateTrackDescription( + Track aTrack, Vector distances, Vector elevations, boolean html) { + return FULL_TRACK_DESCRIPTION; + } + + @Override + public String generateWaypointDescription(TripStatistics tripStatistics) { + return null; + } + } + + public void testXmlOutput() throws Exception { + KmlTrackWriter kmlTrackWriter = new KmlTrackWriter( + getContext(), false, false, new FakeDescriptionGenerator()); + String result = writeTrack(kmlTrackWriter); + Document doc = parseXmlDocument(result); + + Element kmlTag = getChildElement(doc, "kml"); + Element docTag = getChildElement(kmlTag, "Document"); + assertEquals(TRACK_NAME, getChildTextValue(docTag, "name")); + + // There are 3 placemarks - start, track, and end + List placemarkTags = getChildElements(docTag, "Placemark", 3); + assertTagIsPlacemark( + placemarkTags.get(0), TRACK_NAME + " (Start)", "", location1); + assertTagIsPlacemark( + placemarkTags.get(2), TRACK_NAME + " (End)", FULL_TRACK_DESCRIPTION, location4); + + List folderTag = getChildElements(docTag, "Folder", 1); + List folderPlacemarkTags = getChildElements(folderTag.get(0), "Placemark", 2); + assertTagIsPlacemark( + folderPlacemarkTags.get(0), WAYPOINT1_NAME, WAYPOINT1_DESCRIPTION, location2); + assertTagIsPlacemark( + folderPlacemarkTags.get(1), WAYPOINT2_NAME, WAYPOINT2_DESCRIPTION, location3); + + Element trackPlacemarkTag = placemarkTags.get(1); + assertEquals(TRACK_NAME, getChildTextValue(trackPlacemarkTag, "name")); + assertEquals(TRACK_DESCRIPTION, getChildTextValue(trackPlacemarkTag, "description")); + Element multiTrackTag = getChildElement(trackPlacemarkTag, "gx:MultiTrack"); + List trackTags = getChildElements(multiTrackTag, "gx:Track", 2); + assertTagHasPoints(trackTags.get(0), location1, location2); + assertTagHasPoints(trackTags.get(1), location3, location4); + } + + /** + * Asserts that the given tag is a placemark with the given properties. + * + * @param tag the tag + * @param name the expected placemark name + * @param description the expected placemark description + * @param location the expected placemark location + */ + private void assertTagIsPlacemark( + Element tag, String name, String description, Location location) { + assertEquals(name, getChildTextValue(tag, "name")); + if (description != null && !description.equals("")) { + assertEquals(description, getChildTextValue(tag, "description")); + } + Element pointTag = getChildElement(tag, "Point"); + String expected = location.getLongitude() + "," + location.getLatitude() + "," + + location.getAltitude(); + String actual = getChildTextValue(pointTag, "coordinates"); + assertEquals(expected, actual); + } + + /** + * Asserts that the given tag has a list of "gx:coord" subtags matching the + * expected locations. + * + * @param tag the parent tag + * @param locations list of expected locations + */ + private void assertTagHasPoints(Element tag, Location... locations) { + List coordTags = getChildElements(tag, "gx:coord", locations.length); + for (int i = 0; i < locations.length; i++) { + Location location = locations[i]; + String expected = location.getLongitude() + " " + location.getLatitude() + " " + + location.getAltitude(); + String actual = coordTags.get(i).getFirstChild().getTextContent(); + assertEquals(expected, actual); + } + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/exporter/TcxTrackWriterTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/exporter/TcxTrackWriterTest.java new file mode 100644 index 000000000..576b2c73c --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/exporter/TcxTrackWriterTest.java @@ -0,0 +1,97 @@ +/* + * 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. + */ +package com.google.android.apps.mytracks.io.file.exporter; + +import com.google.android.apps.mytracks.content.MyTracksLocation; +import com.google.android.apps.mytracks.content.Sensor; +import com.google.android.apps.mytracks.io.file.exporter.TcxTrackWriter; +import com.google.android.apps.mytracks.util.StringUtils; + +import java.util.List; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * Tests for {@link TcxTrackWriter}. + * + * @author Sandor Dornbush + */ +public class TcxTrackWriterTest extends TrackWriterTest { + + public void testXmlOutput() throws Exception { + TcxTrackWriter tcxTrackWriter = new TcxTrackWriter(getContext()); + String result = writeTrack(tcxTrackWriter); + Document doc = parseXmlDocument(result); + + Element root = getChildElement(doc, "TrainingCenterDatabase"); + Element activitiesTag = getChildElement(root, "Activities"); + Element activityTag = getChildElement(activitiesTag, "Activity"); + Element lapTag = getChildElement(activityTag, "Lap"); + + List segmentTags = getChildElements(lapTag, "Track", 2); + Element segment1Tag = segmentTags.get(0); + Element segment2Tag = segmentTags.get(1); + List seg1PointTags = getChildElements(segment1Tag, "Trackpoint", 2); + List seg2PointTags = getChildElements(segment2Tag, "Trackpoint", 2); + assertTagsMatchPoints(seg1PointTags, location1, location2); + assertTagsMatchPoints(seg2PointTags, location3, location4); + } + + /** + * Asserts that the given tags describe the given locations in the same order. + * + * @param tags list of tags + * @param locations list of locations + */ + private void assertTagsMatchPoints(List tags, MyTracksLocation... locations) { + assertEquals(locations.length, tags.size()); + for (int i = 0; i < locations.length; i++) { + assertTagMatchesLocation(tags.get(i), locations[i]); + } + } + + /** + * Asserts that the given tag describes the given location. + * + * @param tag the tag + * @param location the location + */ + private void assertTagMatchesLocation(Element tag, MyTracksLocation location) { + assertEquals(StringUtils.formatDateTimeIso8601(location.getTime()), getChildTextValue(tag, "Time")); + + Element positionTag = getChildElement(tag, "Position"); + assertEquals( + Double.toString(location.getLatitude()), getChildTextValue(positionTag, "LatitudeDegrees")); + assertEquals(Double.toString(location.getLongitude()), + getChildTextValue(positionTag, "LongitudeDegrees")); + + assertEquals(Double.toString(location.getAltitude()), getChildTextValue(tag, "AltitudeMeters")); + assertTrue(location.getSensorDataSet() != null); + Sensor.SensorDataSet sds = location.getSensorDataSet(); + + List heartRate = getChildElements(tag, "HeartRateBpm", 1); + assertEquals(Integer.toString(sds.getHeartRate().getValue()), + getChildTextValue(heartRate.get(0), "Value")); + + List extensions = getChildElements(tag, "Extensions", 1); + List tpx = getChildElements(extensions.get(0), "TPX", 1); + assertEquals( + Integer.toString(sds.getCadence().getValue()), getChildTextValue(tpx.get(0), "RunCadence")); + assertEquals( + Integer.toString(sds.getPower().getValue()), getChildTextValue(tpx.get(0), "Watts")); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/exporter/TrackWriterTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/exporter/TrackWriterTest.java new file mode 100644 index 000000000..cd8e3f622 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/exporter/TrackWriterTest.java @@ -0,0 +1,219 @@ +// Copyright 2010 Google Inc. All Rights Reserved. +package com.google.android.apps.mytracks.io.file.exporter; + +import com.google.android.apps.mytracks.content.MyTracksLocation; +import com.google.android.apps.mytracks.content.Sensor; +import com.google.android.apps.mytracks.content.Track; +import com.google.android.apps.mytracks.content.Waypoint; + +import android.test.AndroidTestCase; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.FactoryConfigurationError; +import javax.xml.parsers.ParserConfigurationException; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +/** + * Base class for track format writer tests, which sets up a fake track and + * gives auxiliary methods for verifying XML output. + * + * @author Rodrigo Damazio + */ +public abstract class TrackWriterTest extends AndroidTestCase { + + // All the user-provided strings have "]]>" to ensure that proper escaping is + // being done. + protected static final String TRACK_NAME = "Home]]>"; + protected static final String TRACK_CATEGORY = "Hiking"; + protected static final String TRACK_DESCRIPTION = "The long ]]> journey home"; + protected static final String WAYPOINT1_NAME = "point]]>1"; + protected static final String WAYPOINT1_CATEGORY = "Statistics"; + protected static final String WAYPOINT1_DESCRIPTION = "point 1]]>description"; + protected static final String WAYPOINT2_NAME = "point]]>2"; + protected static final String WAYPOINT2_CATEGORY = "Waypoint"; + protected static final String WAYPOINT2_DESCRIPTION = "point 2]]>description"; + private static final int BUFFER_SIZE = 10240; + protected Track track; + protected MyTracksLocation location1, location2, location3, location4; + protected Waypoint wp1, wp2; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + track = new Track(); + track.setName(TRACK_NAME); + track.setCategory(TRACK_CATEGORY); + track.setDescription(TRACK_DESCRIPTION); + + location1 = new MyTracksLocation("mock"); + location2 = new MyTracksLocation("mock"); + location3 = new MyTracksLocation("mock"); + location4 = new MyTracksLocation("mock"); + populateLocations(location1, location2, location3, location4); + + wp1 = new Waypoint(); + wp2 = new Waypoint(); + wp1.setLocation(location2); + wp1.setName(WAYPOINT1_NAME); + wp1.setCategory(WAYPOINT1_CATEGORY); + wp1.setDescription(WAYPOINT1_DESCRIPTION); + wp2.setLocation(location3); + wp2.setName(WAYPOINT2_NAME); + wp2.setCategory(WAYPOINT2_CATEGORY); + wp2.setDescription(WAYPOINT2_DESCRIPTION); + } + + /** + * Populates a list of locations with values. + * + * @param locations a list of locations + */ + private void populateLocations(MyTracksLocation... locations) { + for (int i = 0; i < locations.length; i++) { + MyTracksLocation location = locations[i]; + location.setLatitude(i); + location.setLongitude(-i); + location.setAltitude(i * 10); + location.setBearing(i * 100); + location.setAccuracy(i * 1000); + location.setSpeed(i * 10000); + location.setTime(i * 100000); + Sensor.SensorData.Builder power = Sensor.SensorData.newBuilder().setValue(100 + i) + .setState(Sensor.SensorState.SENDING); + Sensor.SensorData.Builder cadence = Sensor.SensorData.newBuilder().setValue(200 + i) + .setState(Sensor.SensorState.SENDING); + Sensor.SensorData.Builder heartRate = Sensor.SensorData.newBuilder().setValue(300 + i) + .setState(Sensor.SensorState.SENDING); + Sensor.SensorDataSet sensorDataSet = Sensor.SensorDataSet.newBuilder().setPower(power) + .setCadence(cadence).setHeartRate(heartRate).build(); + location.setSensorDataSet(sensorDataSet); + } + } + + /** + * Makes the right sequence of calls to the writer in order to write the fake + * track in {@link #track}. + * + * @param trackWriter the track writer + * @return the written contents + */ + protected String writeTrack(TrackWriter trackWriter) throws Exception { + OutputStream output = new ByteArrayOutputStream(BUFFER_SIZE); + trackWriter.prepare(output); + trackWriter.writeHeader(new Track[] {track}); + trackWriter.writeBeginWaypoints(track); + trackWriter.writeWaypoint(wp1); + trackWriter.writeWaypoint(wp2); + trackWriter.writeEndWaypoints(); + trackWriter.writeBeginTracks(); + trackWriter.writeBeginTrack(track, location1); + trackWriter.writeOpenSegment(); + trackWriter.writeLocation(location1); + trackWriter.writeLocation(location2); + trackWriter.writeCloseSegment(); + trackWriter.writeOpenSegment(); + trackWriter.writeLocation(location3); + trackWriter.writeLocation(location4); + trackWriter.writeCloseSegment(); + trackWriter.writeEndTrack(track, location4); + trackWriter.writeEndTracks(); + trackWriter.writeFooter(); + trackWriter.close(); + return output.toString(); + } + + /** + * Gets the text data contained inside a tag. + * + * @param parent the parent of the tag containing the text + * @param elementName the name of the tag containing the text + * @return the text contents + */ + protected String getChildTextValue(Element parent, String elementName) { + Element child = getChildElement(parent, elementName); + assertTrue(child.hasChildNodes()); + NodeList children = child.getChildNodes(); + int length = children.getLength(); + assertTrue(length > 0); + + // The children may be a sucession of text elements, just concatenate them + String result = ""; + for (int i = 0; i < length; i++) { + Text textNode = (Text) children.item(i); + result += textNode.getNodeValue(); + } + return result; + } + + /** + * Returns all child elements of a given parent which have the given name. + * + * @param parent the parent to get children from + * @param elementName the element name to look for + * @param expectedChildren the number of children we're expected to find + * @return a list of the found elements + */ + protected List getChildElements(Node parent, String elementName, + int expectedChildren) { + assertTrue(parent.hasChildNodes()); + NodeList children = parent.getChildNodes(); + int length = children.getLength(); + List result = new ArrayList(); + for (int i = 0; i < length; i++) { + Node childNode = children.item(i); + if (childNode.getNodeType() == Node.ELEMENT_NODE + && childNode.getNodeName().equalsIgnoreCase(elementName)) { + result.add((Element) childNode); + } + } + assertTrue(children.toString(), result.size() == expectedChildren); + return result; + } + + /** + * Returns the single child element of the given parent with the given type. + * + * @param parent the parent to get a child from + * @param elementName the name of the child to look for + * @return the child element + */ + protected Element getChildElement(Node parent, String elementName) { + return getChildElements(parent, elementName, 1).get(0); + } + + /** + * Parses the given XML contents and returns a DOM {@link Document} for it. + */ + protected Document parseXmlDocument(String contents) + throws FactoryConfigurationError, ParserConfigurationException, + SAXException, IOException { + DocumentBuilderFactory builderFactory = + DocumentBuilderFactory.newInstance(); + builderFactory.setCoalescing(true); + // TODO: Somehow do XML validation on Android + // builderFactory.setValidating(true); + builderFactory.setNamespaceAware(true); + builderFactory.setIgnoringComments(true); + builderFactory.setIgnoringElementContentWhitespace(true); + DocumentBuilder documentBuilder = builderFactory.newDocumentBuilder(); + Document doc = documentBuilder.parse( + new InputSource(new StringReader(contents))); + return doc; + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/importer/AbstractTestFileTrackImporter.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/importer/AbstractTestFileTrackImporter.java new file mode 100644 index 000000000..50dbdfd98 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/importer/AbstractTestFileTrackImporter.java @@ -0,0 +1,164 @@ +/* + * Copyright 2012 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.io.file.importer; + +import static com.google.android.testing.mocking.AndroidMock.eq; +import static com.google.android.testing.mocking.AndroidMock.expect; + +import com.google.android.apps.mytracks.content.MyTracksProviderUtils; +import com.google.android.apps.mytracks.content.MyTracksProviderUtils.Factory; +import com.google.android.apps.mytracks.content.Track; +import com.google.android.apps.mytracks.content.TracksColumns; +import com.google.android.apps.mytracks.content.Waypoint; +import com.google.android.apps.mytracks.content.WaypointsColumns; +import com.google.android.apps.mytracks.testing.TestingProviderUtilsFactory; +import com.google.android.testing.mocking.AndroidMock; +import com.google.android.testing.mocking.UsesMocks; + +import android.content.ContentUris; +import android.location.Location; +import android.location.LocationManager; +import android.net.Uri; +import android.test.AndroidTestCase; + +import java.text.SimpleDateFormat; +import java.util.Locale; +import java.util.SimpleTimeZone; + +import org.easymock.Capture; + +/** + * Abstract class for testing file track importers. + * + * @author Jimmy Shih. + */ +public class AbstractTestFileTrackImporter extends AndroidTestCase { + + protected static final String TRACK_NAME_0 = "blablub"; + protected static final String TRACK_DESCRIPTION_0 = "s'Laebe isch koi Schlotzer"; + + protected static final String TRACK_NAME_1 = "another track"; + protected static final String TRACK_DESCRIPTION_1 = "another description"; + + protected static final double TRACK_LATITUDE = 48.768364; + protected static final double TRACK_LONGITUDE = 9.177886; + protected static final double TRACK_ELEVATION = 324.0; + + protected static final String TRACK_TIME_0 = "2010-04-22T18:21:00Z"; + protected static final String TRACK_TIME_1 = "2010-04-22T18:21:50.123"; + protected static final String TRACK_TIME_2 = "2010-04-22T18:23:00.123"; + protected static final String TRACK_TIME_3 = "2010-04-22T18:24:50.123"; + + protected static final SimpleDateFormat DATE_FORMAT_0 = new SimpleDateFormat( + "yyyy-MM-dd'T'hh:mm:ss'Z'", Locale.US); + protected static final SimpleDateFormat DATE_FORMAT_1 = new SimpleDateFormat( + "yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US); + + static { + /* + * We can't omit the timezones in the test, otherwise it'll use the local + * timezone and fail depending on where the test runner is. + */ + SimpleTimeZone utc = new SimpleTimeZone(0, "UTC"); + DATE_FORMAT_0.setTimeZone(utc); + DATE_FORMAT_1.setTimeZone(utc); + } + + protected static final long TRACK_ID_0 = 1; + protected static final long TRACK_ID_1 = 2; + protected static final long TRACK_POINT_ID_0 = 1; + protected static final long TRACK_POINT_ID_1 = 2; + protected static final long TRACK_POINT_ID_3 = 4; + protected static final long WAYPOINT_ID_0 = 1; + + protected static final Uri TRACK_ID_0_URI = ContentUris.appendId( + TracksColumns.CONTENT_URI.buildUpon(), TRACK_ID_0).build(); + protected static final Uri TRACK_ID_1_URI = ContentUris.appendId( + TracksColumns.CONTENT_URI.buildUpon(), TRACK_ID_1).build(); + protected static final Uri WAYPOINT_ID_O_URI = ContentUris.appendId( + WaypointsColumns.CONTENT_URI.buildUpon(), WAYPOINT_ID_0).build(); + + protected MyTracksProviderUtils myTracksProviderUtils; + + private Factory oldMyTracksProviderUtilsFactory; + + @UsesMocks(MyTracksProviderUtils.class) + @Override + protected void setUp() throws Exception { + super.setUp(); + myTracksProviderUtils = AndroidMock.createMock(MyTracksProviderUtils.class); + oldMyTracksProviderUtilsFactory = TestingProviderUtilsFactory.installWithInstance( + myTracksProviderUtils); + } + + @Override + protected void tearDown() throws Exception { + TestingProviderUtilsFactory.restoreOldFactory(oldMyTracksProviderUtilsFactory); + super.tearDown(); + } + + protected Location createLocation(int index, long time) { + Location location = new Location(LocationManager.GPS_PROVIDER); + location.setLatitude(TRACK_LATITUDE + index); + location.setLongitude(TRACK_LONGITUDE + index); + location.setAltitude(TRACK_ELEVATION + index); + location.setTime(time); + return location; + } + + /** + * Expects the first track point to be added. + * + * @param location the location + * @param trackId the track id + * @param trackPointId the track point id + */ + protected void expectFirstTrackPoint(Location location, long trackId, long trackPointId) { + expect(myTracksProviderUtils.bulkInsertTrackPoint( + location != null ? LocationsMatcher.eqLoc(location) : (Location[]) AndroidMock.anyObject(), + eq(1), eq(trackId))).andReturn(1); + expect(myTracksProviderUtils.getFirstTrackPointId(trackId)).andReturn(trackPointId); + expect(myTracksProviderUtils.getLastTrackPointId(trackId)).andReturn(trackPointId); + } + + /** + * Expects the track to be updated. + * + * @param track the track + * @param lastTrack true if it is the last track in the gpx + * @param trackId the track id + */ + protected void expectUpdateTrack(Capture track, boolean lastTrack, long trackId) { + myTracksProviderUtils.updateTrack(AndroidMock.capture(track)); + expect(myTracksProviderUtils.insertWaypoint((Waypoint) AndroidMock.anyObject())) + .andReturn(WAYPOINT_ID_O_URI); + if (lastTrack) { + // Return null to not add waypoints + expect(myTracksProviderUtils.getTrack(trackId)).andReturn(null); + } + } + + protected void verifyTrack(Track track, String name, String description, long time) { + assertEquals(name, track.getName()); + assertEquals(description, track.getDescription()); + if (time != -1L) { + assertEquals(time, track.getTripStatistics().getStartTime()); + } + assertNotSame(-1, track.getStartId()); + assertNotSame(-1, track.getStopId()); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/importer/GpxFileTrackImporterTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/importer/GpxFileTrackImporterTest.java new file mode 100644 index 000000000..3b7769112 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/importer/GpxFileTrackImporterTest.java @@ -0,0 +1,257 @@ +/* + * 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. + */ + +package com.google.android.apps.mytracks.io.file.importer; + +import static com.google.android.testing.mocking.AndroidMock.eq; +import static com.google.android.testing.mocking.AndroidMock.expect; + +import com.google.android.apps.mytracks.content.Track; +import com.google.android.apps.mytracks.util.PreferencesUtils; +import com.google.android.maps.mytracks.R; +import com.google.android.testing.mocking.AndroidMock; + +import android.location.Location; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import org.easymock.Capture; + +/** + * Tests for {@link GpxFileTrackImporter}. + * + * @author Steffen Horlacher + */ +public class GpxFileTrackImporterTest extends AbstractTestFileTrackImporter { + + private static String getNameAndDescription(String name, String description) { + return "" + ""; + } + + private static String getTrackPoint(int index, String time) { + String latitude = Double.toString(TRACK_LATITUDE + index); + String longitude = Double.toString(TRACK_LONGITUDE + index); + String elevation = Double.toString(TRACK_ELEVATION + index); + StringBuffer buffer = new StringBuffer(); + buffer.append( + "" + elevation + ""); + if (time != null) { + buffer.append(""); + } + buffer.append(""); + return buffer.toString(); + } + + private static final String VALID_ONE_TRACK_ONE_SEGMENT_GPX = "" + + getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "" + + getTrackPoint(0, TRACK_TIME_0) + getTrackPoint(1, TRACK_TIME_1) + ""; + private static final String VALID_ONE_TRACK_TWO_SEGMENTS_GPX = "" + + getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "" + + getTrackPoint(0, TRACK_TIME_0) + getTrackPoint(1, TRACK_TIME_1) + "" + + getTrackPoint(2, TRACK_TIME_2) + getTrackPoint(3, TRACK_TIME_3) + ""; + private static final String VALID_ONE_TRACK_TWO_SEGMENTS_NO_TIME_GPX = "" + + getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "" + + getTrackPoint(0, null) + getTrackPoint(1, null) + "" + + getTrackPoint(2, null) + getTrackPoint(3, null) + ""; + + private static final String INVALID_XML_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.substring( + 0, VALID_ONE_TRACK_ONE_SEGMENT_GPX.length() - 50); + private static final String INVALID_LOCATION_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll( + Double.toString(TRACK_LATITUDE), "1000.0"); + private static final String INVALID_TIME_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll( + TRACK_TIME_0, "invalid"); + private static final String INVALID_ALTITUDE_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll( + Double.toString(TRACK_ELEVATION), "invalid"); + private static final String INVALID_LATITUDE_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll( + Double.toString(TRACK_LATITUDE), "invalid"); + private static final String INVALID_LONGITUDE_GPX = VALID_ONE_TRACK_ONE_SEGMENT_GPX.replaceAll( + Double.toString(TRACK_LONGITUDE), "invalid"); + + /** + * Tests one track with one segment. + */ + public void testOneTrackOneSegment() throws Exception { + Capture track = new Capture(); + + Location location0 = createLocation(0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime()); + Location location1 = createLocation(1, DATE_FORMAT_1.parse(TRACK_TIME_1).getTime()); + + expect(myTracksProviderUtils.insertTrack((Track) AndroidMock.anyObject())) + .andReturn(TRACK_ID_0_URI); + expectFirstTrackPoint(location0, TRACK_ID_0, TRACK_POINT_ID_0); + + // A flush happens at the end + expect(myTracksProviderUtils.bulkInsertTrackPoint( + LocationsMatcher.eqLoc(location1), eq(1), eq(TRACK_ID_0))).andReturn(1); + expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID_0)).andReturn(TRACK_POINT_ID_1); + expect( + myTracksProviderUtils.getTrack(PreferencesUtils.getLong(getContext(), + R.string.recording_track_id_key))).andStubReturn(null); + expectUpdateTrack(track, true, TRACK_ID_0); + AndroidMock.replay(myTracksProviderUtils); + + InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_ONE_SEGMENT_GPX.getBytes()); + GpxFileTrackImporter gpxFileTrackImporter = new GpxFileTrackImporter( + getContext(), myTracksProviderUtils); + long trackId = gpxFileTrackImporter.importFile(inputStream); + assertEquals(TRACK_ID_0, trackId); + + long time0 = DATE_FORMAT_0.parse(TRACK_TIME_0).getTime(); + long time1 = DATE_FORMAT_1.parse(TRACK_TIME_1).getTime(); + assertEquals(time1 - time0, track.getValue().getTripStatistics().getTotalTime()); + AndroidMock.verify(myTracksProviderUtils); + verifyTrack(track.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, time0); + } + + /** + * Tests one track with two segments. + */ + public void testOneTrackTwoSegments() throws Exception { + Capture track = new Capture(); + + Location location0 = createLocation(0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime()); + + expect(myTracksProviderUtils.insertTrack((Track) AndroidMock.anyObject())) + .andReturn(TRACK_ID_0_URI); + expectFirstTrackPoint(location0, TRACK_ID_0, TRACK_POINT_ID_0); + // A flush happens at the end + expect(myTracksProviderUtils.bulkInsertTrackPoint( + (Location[]) AndroidMock.anyObject(), eq(5), eq(TRACK_ID_0))).andStubReturn(5); + expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID_0)).andReturn(TRACK_POINT_ID_3); + expect( + myTracksProviderUtils.getTrack(PreferencesUtils.getLong(getContext(), + R.string.recording_track_id_key))).andStubReturn(null); + expectUpdateTrack(track, true, TRACK_ID_0); + AndroidMock.replay(myTracksProviderUtils); + + InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_TWO_SEGMENTS_GPX.getBytes()); + GpxFileTrackImporter gpxFileTrackImporter = new GpxFileTrackImporter( + getContext(), myTracksProviderUtils); + long trackId = gpxFileTrackImporter.importFile(inputStream); + assertEquals(TRACK_ID_0, trackId); + + long time0 = DATE_FORMAT_0.parse(TRACK_TIME_0).getTime(); + long time1 = DATE_FORMAT_1.parse(TRACK_TIME_1).getTime(); + long time2 = DATE_FORMAT_1.parse(TRACK_TIME_2).getTime(); + long time3 = DATE_FORMAT_1.parse(TRACK_TIME_3).getTime(); + assertEquals( + time1 - time0 + time3 - time2, track.getValue().getTripStatistics().getTotalTime()); + + AndroidMock.verify(myTracksProviderUtils); + verifyTrack(track.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, + DATE_FORMAT_0.parse(TRACK_TIME_0).getTime()); + } + + /** + * Tests one track with two segments, but no time in the track points. + */ + public void testOneTrackTwoSegmentsNoTime() throws Exception { + Capture track = new Capture(); + + expect(myTracksProviderUtils.insertTrack((Track) AndroidMock.anyObject())) + .andReturn(TRACK_ID_0_URI); + expectFirstTrackPoint(null, TRACK_ID_0, TRACK_POINT_ID_0); + + // A flush happens at the end + expect(myTracksProviderUtils.bulkInsertTrackPoint( + (Location[]) AndroidMock.anyObject(), eq(5), eq(TRACK_ID_0))).andStubReturn(5); + expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID_0)).andReturn(TRACK_POINT_ID_3); + expect( + myTracksProviderUtils.getTrack(PreferencesUtils.getLong(getContext(), + R.string.recording_track_id_key))).andStubReturn(null); + expectUpdateTrack(track, true, TRACK_ID_0); + AndroidMock.replay(myTracksProviderUtils); + + InputStream inputStream = new ByteArrayInputStream( + VALID_ONE_TRACK_TWO_SEGMENTS_NO_TIME_GPX.getBytes()); + GpxFileTrackImporter gpxFileTrackImporter = new GpxFileTrackImporter( + getContext(), myTracksProviderUtils); + long trackId = gpxFileTrackImporter.importFile(inputStream); + assertEquals(TRACK_ID_0, trackId); + assertEquals(0, track.getValue().getTripStatistics().getTotalTime()); + + AndroidMock.verify(myTracksProviderUtils); + verifyTrack(track.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, -1L); + } + + /** + * Test an invalid xml input. + */ + public void testInvalidXml() throws Exception { + testInvalidGpx(INVALID_XML_GPX); + } + + /** + * Test an invalid location. + */ + public void testInvalidLocation() throws Exception { + testInvalidGpx(INVALID_LOCATION_GPX); + } + + /** + * Test an invalid time. + */ + public void testInvalidTime() throws Exception { + testInvalidGpx(INVALID_TIME_GPX); + } + + /** + * Test an invalid altitude. + */ + public void testInvalidAltitude() throws Exception { + testInvalidGpx(INVALID_ALTITUDE_GPX); + } + + /** + * Test an invalid latitude. + */ + public void testInvalidLatitude() throws Exception { + testInvalidGpx(INVALID_LATITUDE_GPX); + } + + /** + * Test an invalid longitude. + */ + public void testInvalidLongitude() throws Exception { + testInvalidGpx(INVALID_LONGITUDE_GPX); + } + + private void testInvalidGpx(String xml) throws Exception { + expect(myTracksProviderUtils.insertTrack((Track) AndroidMock.anyObject())) + .andReturn(TRACK_ID_0_URI); + + // For the following, use StubReturn since we don't care whether they are + // invoked or not. + expect(myTracksProviderUtils.bulkInsertTrackPoint( + (Location[]) AndroidMock.anyObject(), AndroidMock.anyInt(), AndroidMock.anyLong())) + .andStubReturn(1); + expect(myTracksProviderUtils.getFirstTrackPointId(TRACK_ID_0)).andStubReturn(TRACK_POINT_ID_0); + expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID_0)).andStubReturn(TRACK_POINT_ID_0); + expect( + myTracksProviderUtils.getTrack(PreferencesUtils.getLong(getContext(), + R.string.recording_track_id_key))).andStubReturn(null); + myTracksProviderUtils.deleteTrack(getContext(), TRACK_ID_0); + AndroidMock.replay(myTracksProviderUtils); + + InputStream inputStream = new ByteArrayInputStream(xml.getBytes()); + GpxFileTrackImporter gpxFileTrackImporter = new GpxFileTrackImporter( + getContext(), myTracksProviderUtils); + long trackId = gpxFileTrackImporter.importFile(inputStream); + assertEquals(-1L, trackId); + AndroidMock.verify(myTracksProviderUtils); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/importer/KmlFileTrackImporterTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/importer/KmlFileTrackImporterTest.java new file mode 100644 index 000000000..3b669cd51 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/importer/KmlFileTrackImporterTest.java @@ -0,0 +1,141 @@ +/* + * Copyright 2012 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.io.file.importer; + +import static com.google.android.testing.mocking.AndroidMock.eq; +import static com.google.android.testing.mocking.AndroidMock.expect; + +import com.google.android.apps.mytracks.content.Track; +import com.google.android.apps.mytracks.util.PreferencesUtils; +import com.google.android.maps.mytracks.R; +import com.google.android.testing.mocking.AndroidMock; + +import android.location.Location; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import org.easymock.Capture; + +/** + * Tests for {@link KmlFileTrackImporter}. + * + * @author Jimmy Shih + */ +public class KmlFileTrackImporterTest extends AbstractTestFileTrackImporter { + + private static String getNameAndDescription(String name, String description) { + return ""; + } + + private static String getTrackPoint(int index, String time) { + String latitude = Double.toString(TRACK_LATITUDE + index); + String longitude = Double.toString(TRACK_LONGITUDE + index); + String altitude = Double.toString(TRACK_ELEVATION + index); + StringBuffer buffer = new StringBuffer(); + buffer.append("" + time + "" + "" + longitude + " " + latitude + " " + + altitude + ""); + return buffer.toString(); + } + + private static final String VALID_ONE_TRACK_ONE_SEGMENT_GPX = + "" + + getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "" + + getTrackPoint(0, TRACK_TIME_0) + getTrackPoint(1, TRACK_TIME_1) + + ""; + private static final String VALID_ONE_TRACK_TWO_SEGMENTS_GPX = + "" + + getNameAndDescription(TRACK_NAME_0, TRACK_DESCRIPTION_0) + "" + + getTrackPoint(0, TRACK_TIME_0) + getTrackPoint(1, TRACK_TIME_1) + "" + + getTrackPoint(2, TRACK_TIME_2) + getTrackPoint(3, TRACK_TIME_3) + + ""; + + /** + * Tests one track with one segment. + */ + public void testOneTrackOneSegment() throws Exception { + Capture track = new Capture(); + + Location location0 = createLocation(0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime()); + Location location1 = createLocation(1, DATE_FORMAT_1.parse(TRACK_TIME_1).getTime()); + + myTracksProviderUtils.clearTrack(getContext(), TRACK_ID_0); + expectFirstTrackPoint(location0, TRACK_ID_0, TRACK_POINT_ID_0); + + // A flush happens at the end + expect(myTracksProviderUtils.bulkInsertTrackPoint( + LocationsMatcher.eqLoc(location1), eq(1), eq(TRACK_ID_0))).andReturn(1); + expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID_0)).andReturn(TRACK_POINT_ID_1); + expect( + myTracksProviderUtils.getTrack(PreferencesUtils.getLong(getContext(), + R.string.recording_track_id_key))).andStubReturn(null); + expectUpdateTrack(track, true, TRACK_ID_0); + AndroidMock.replay(myTracksProviderUtils); + + InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_ONE_SEGMENT_GPX.getBytes()); + KmlFileTrackImporter kmlFileTrackImporter = new KmlFileTrackImporter( + getContext(), TRACK_ID_0, myTracksProviderUtils); + long trackId = kmlFileTrackImporter.importFile(inputStream); + assertEquals(TRACK_ID_0, trackId); + + long time0 = DATE_FORMAT_0.parse(TRACK_TIME_0).getTime(); + long time1 = DATE_FORMAT_1.parse(TRACK_TIME_1).getTime(); + assertEquals(time1 - time0, track.getValue().getTripStatistics().getTotalTime()); + AndroidMock.verify(myTracksProviderUtils); + verifyTrack(track.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, time0); + } + + /** + * Tests one track with two segments. + */ + public void testOneTrackTwoSegments() throws Exception { + Capture track = new Capture(); + + Location location0 = createLocation(0, DATE_FORMAT_0.parse(TRACK_TIME_0).getTime()); + + myTracksProviderUtils.clearTrack(getContext(), TRACK_ID_0); + expectFirstTrackPoint(location0, TRACK_ID_0, TRACK_POINT_ID_0); + + // A flush happens at the end + expect(myTracksProviderUtils.bulkInsertTrackPoint( + (Location[]) AndroidMock.anyObject(), eq(5), eq(TRACK_ID_0))).andStubReturn(5); + expect(myTracksProviderUtils.getLastTrackPointId(TRACK_ID_0)).andReturn(TRACK_POINT_ID_3); + expect( + myTracksProviderUtils.getTrack(PreferencesUtils.getLong(getContext(), + R.string.recording_track_id_key))).andStubReturn(null); + expectUpdateTrack(track, true, TRACK_ID_0); + AndroidMock.replay(myTracksProviderUtils); + + InputStream inputStream = new ByteArrayInputStream(VALID_ONE_TRACK_TWO_SEGMENTS_GPX.getBytes()); + KmlFileTrackImporter kmlFileTrackImporter = new KmlFileTrackImporter( + getContext(), TRACK_ID_0, myTracksProviderUtils); + long trackId = kmlFileTrackImporter.importFile(inputStream); + assertEquals(TRACK_ID_0, trackId); + + long time0 = DATE_FORMAT_0.parse(TRACK_TIME_0).getTime(); + long time1 = DATE_FORMAT_1.parse(TRACK_TIME_1).getTime(); + long time2 = DATE_FORMAT_1.parse(TRACK_TIME_2).getTime(); + long time3 = DATE_FORMAT_1.parse(TRACK_TIME_3).getTime(); + assertEquals( + time1 - time0 + time3 - time2, track.getValue().getTripStatistics().getTotalTime()); + + AndroidMock.verify(myTracksProviderUtils); + verifyTrack(track.getValue(), TRACK_NAME_0, TRACK_DESCRIPTION_0, + DATE_FORMAT_0.parse(TRACK_TIME_0).getTime()); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/importer/LocationsMatcher.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/importer/LocationsMatcher.java new file mode 100644 index 000000000..b54979259 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/file/importer/LocationsMatcher.java @@ -0,0 +1,81 @@ +/* + * Copyright 2012 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.io.file.importer; + +import com.google.android.testing.mocking.AndroidMock; + +import android.location.Location; + +import java.util.Arrays; + +import org.easymock.IArgumentMatcher; + +/** + * Locations matcher. Workaround because of capture bug 2617107 in easymock: + * http://sourceforge.net/tracker/?func=detail&aid=2617107&group_id=82958&atid=567837 + * + * @author Jimmy Shih + */ +public class LocationsMatcher implements IArgumentMatcher { + + public static Location[] eqLoc(Location expected) { + return eqLoc(new Location[] { expected }); + } + + public static Location[] eqLoc(Location[] expected) { + IArgumentMatcher matcher = new LocationsMatcher(expected); + AndroidMock.reportMatcher(matcher); + return null; + } + + private final Location[] expectedLocations; + + private LocationsMatcher(Location[] expected) { + this.expectedLocations = expected; + } + + @Override + public void appendTo(StringBuffer buf) { + buf.append("eqLoc(").append(Arrays.toString(expectedLocations)).append(")"); + } + + @Override + public boolean matches(Object obj) { + if (!(obj instanceof Location[])) { + return false; + } + Location[] locations = (Location[]) obj; + if (locations.length < expectedLocations.length) { + return false; + } + + // Only check the first elements (those that will be taken into account) + for (int i = 0; i < expectedLocations.length; i++) { + if (!matchLocation(locations[i], expectedLocations[i])) { + return false; + } + } + return true; + } + + private boolean matchLocation(Location location1, Location location2) { + return (location1.getTime() == location2.getTime()) + && (location1.getLatitude() == location2.getLatitude()) + && (location1.getLongitude() == location2.getLongitude()) + && (location1.getAltitude() == location2.getAltitude()); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesActivityTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesActivityTest.java new file mode 100644 index 000000000..9e2db29d6 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesActivityTest.java @@ -0,0 +1,85 @@ +/* + * Copyright 2012 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.io.fusiontables; + +import com.google.android.apps.mytracks.io.sendtogoogle.SendRequest; +import com.google.android.apps.mytracks.io.sendtogoogle.UploadResultActivity; +import com.google.android.apps.mytracks.io.spreadsheets.SendSpreadsheetsActivity; + +import android.test.AndroidTestCase; + +/** + * Tests the {@link SendFusionTablesActivity}. + * + * @author Youtao Liu + */ +public class SendFusionTablesActivityTest extends AndroidTestCase { + + private SendFusionTablesActivity sendFusionTablesActivity; + private SendRequest sendRequest; + + @Override + protected void setUp() throws Exception { + super.setUp(); + sendRequest = new SendRequest(1L); + sendFusionTablesActivity = new SendFusionTablesActivity(); + } + + /** + * Tests the method + * {@link SendFusionTablesActivity#getNextClass(SendRequest, boolean)}. Sets + * the flags of "sendSpreadsheets" and "cancel" to false and false. + */ + public void testGetNextClass_notCancelNotSendSpreadsheets() { + sendRequest.setSendSpreadsheets(false); + Class next = sendFusionTablesActivity.getNextClass(sendRequest, false); + assertEquals(UploadResultActivity.class, next); + } + + /** + * Tests the method + * {@link SendFusionTablesActivity#getNextClass(SendRequest, boolean)}. Sets + * the flags of "sendSpreadsheets" and "cancel" to true and false. + */ + public void testGetNextClass_notCancelSendSpreadsheets() { + sendRequest.setSendSpreadsheets(true); + Class next = sendFusionTablesActivity.getNextClass(sendRequest, false); + assertEquals(SendSpreadsheetsActivity.class, next); + } + + /** + * Tests the method + * {@link SendFusionTablesActivity#getNextClass(SendRequest,boolean)}. Sets + * the flags of "sendSpreadsheets" and "cancel" to true and true. + */ + public void testGetNextClass_cancelSendSpreadsheets() { + sendRequest.setSendSpreadsheets(true); + Class next = sendFusionTablesActivity.getNextClass(sendRequest, true); + assertEquals(UploadResultActivity.class, next); + } + + /** + * Tests the method + * {@link SendFusionTablesActivity#getNextClass(SendRequest,boolean)}. Sets + * the flags of "sendSpreadsheets" and "cancel" to false and true. + */ + public void testGetNextClass_cancelNotSendSpreadsheets() { + sendRequest.setSendSpreadsheets(false); + Class next = sendFusionTablesActivity.getNextClass(sendRequest, true); + assertEquals(UploadResultActivity.class, next); + } + +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesUtilsTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesUtilsTest.java new file mode 100644 index 000000000..a25c37b2b --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/fusiontables/SendFusionTablesUtilsTest.java @@ -0,0 +1,212 @@ +/* + * Copyright 2012 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.io.fusiontables; + +import com.google.android.apps.mytracks.content.Track; +import com.google.android.apps.mytracks.stats.TripStatistics; + +import android.location.Location; + +import java.util.ArrayList; + +import junit.framework.TestCase; + +/** + * Tests {@link SendFusionTablesUtils}. + * + * @author Jimmy Shih + */ +public class SendFusionTablesUtilsTest extends TestCase { + + /** + * Tests {@link SendFusionTablesUtils#getMapUrl(Track, String)} with null track. + */ + public void testGetMapUrl_null_track() { + assertEquals(null, SendFusionTablesUtils.getMapUrl(null, "123")); + } + + /** + * Tests {@link SendFusionTablesUtils#getMapUrl(Track, String)} with null stats. + */ + public void testGetMapUrl_null_stats() { + Track track = new Track(); + track.setTripStatistics(null); + assertEquals(null, SendFusionTablesUtils.getMapUrl(track, "123")); + } + + /** + * Tests {@link SendFusionTablesUtils#getMapUrl(Track, String)} with a valid track. + */ + public void testGetMapUrl_valid_track() { + Track track = new Track(); + track.setNumberOfPoints(2); + TripStatistics stats = new TripStatistics(); + stats.setBounds((int) 100.E6, (int) 10.E6, (int) 50.E6, (int) 5.E6); + track.setTripStatistics(stats); + assertEquals( + "https://www.google.com/fusiontables/embedviz?" + + "viz=MAP&q=select+col0,+col1,+col2,+col3+from+123+&h=false&lat=7.500000&lng=75.000000" + + "&z=15&t=1&l=col2", SendFusionTablesUtils.getMapUrl(track, "123")); + } + + /** + * Tests (@link {@link SendFusionTablesUtils#formatSqlValues(String...)} with + * no value. + */ + public void testFormatSqlValues_no_value() { + assertEquals("()", SendFusionTablesUtils.formatSqlValues()); + } + + /** + * Tests (@link {@link SendFusionTablesUtils#formatSqlValues(String...)} with + * an empty string. + */ + public void testFormatSqlValues_empty_string() { + assertEquals("(\'\')", SendFusionTablesUtils.formatSqlValues("")); + } + + /** + * Tests (@link {@link SendFusionTablesUtils#formatSqlValues(String...)} with + * one value. + */ + public void testFormatSqlValues_one_value() { + assertEquals("(\'first\')", SendFusionTablesUtils.formatSqlValues("first")); + } + + /** + * Tests (@link {@link SendFusionTablesUtils#formatSqlValues(String...)} with + * two values. + */ + public void testFormatSqlValues_two_values() { + assertEquals( + "(\'first\',\'second\')", SendFusionTablesUtils.formatSqlValues("first", "second")); + } + + /** + * Tests {@link SendFusionTablesUtils#escapeSqlString(String)} with a value + * containing several single quotes. + */ + public void testEscapeSqValuel() { + String value = "let's'"; + assertEquals("let''s''", SendFusionTablesUtils.escapeSqlString(value)); + } + + /** + * Tests {@link SendFusionTablesUtils#getKmlPoint(Location)} with a null + * point. + */ + public void testGetKmlPoint_null_point() { + assertEquals( + "", SendFusionTablesUtils.getKmlPoint(null)); + } + + /** + * Tests {@link SendFusionTablesUtils#getKmlPoint(Location)} with a valid + * point. + */ + public void testGetKmlPoint_valid_point() { + Location location = new Location("test"); + location.setLongitude(10.1); + location.setLatitude(20.2); + location.setAltitude(30.3); + assertEquals("10.1,20.2,30.3", + SendFusionTablesUtils.getKmlPoint(location)); + } + + /** + * Tests {@link SendFusionTablesUtils#getKmlLineString(ArrayList)} with a null + * locations. + */ + public void testKmlLineString_null_locations() { + assertEquals("", + SendFusionTablesUtils.getKmlLineString(null)); + } + + /** + * Tests {@link SendFusionTablesUtils#getKmlLineString(ArrayList)} with no + * location. + */ + public void testKmlLineString_no_location() { + ArrayList locations = new ArrayList(); + assertEquals("", + SendFusionTablesUtils.getKmlLineString(locations)); + } + + /** + * Tests {@link SendFusionTablesUtils#getKmlLineString(ArrayList)} with one + * location. + */ + public void testKmlLineString_one_location() { + ArrayList locations = new ArrayList(); + Location location = new Location("test"); + location.setLongitude(10.1); + location.setLatitude(20.2); + location.setAltitude(30.3); + locations.add(location); + assertEquals("10.1,20.2,30.3", + SendFusionTablesUtils.getKmlLineString(locations)); + } + + /** + * Tests {@link SendFusionTablesUtils#getKmlLineString(ArrayList)} with two + * locations. + */ + public void testKmlLineString_two_locations() { + ArrayList locations = new ArrayList(); + Location location1 = new Location("test"); + location1.setLongitude(10.1); + location1.setLatitude(20.2); + location1.setAltitude(30.3); + locations.add(location1); + + Location location2 = new Location("test"); + location2.setLongitude(1.1); + location2.setLatitude(2.2); + location2.removeAltitude(); + locations.add(location2); + + assertEquals("10.1,20.2,30.3 1.1,2.2", + SendFusionTablesUtils.getKmlLineString(locations)); + } + + /** + * Tests {@link SendFusionTablesUtils#appendLocation(Location, StringBuilder)} + * with no altitude. + */ + public void testAppendLocation_no_altitude() { + StringBuilder builder = new StringBuilder(); + Location location = new Location("test"); + location.setLongitude(10.1); + location.setLatitude(20.2); + location.removeAltitude(); + SendFusionTablesUtils.appendLocation(location, builder); + assertEquals("10.1,20.2", builder.toString()); + } + + /** + * Tests {@link SendFusionTablesUtils#appendLocation(Location, StringBuilder)} + * with altitude. + */ + public void testAppendLocation_has_altitude() { + StringBuilder builder = new StringBuilder(); + Location location = new Location("test"); + location.setLongitude(10.1); + location.setLatitude(20.2); + location.setAltitude(30.3); + SendFusionTablesUtils.appendLocation(location, builder); + assertEquals("10.1,20.2,30.3", builder.toString()); + } +} \ No newline at end of file diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/maps/SendMapsActivityTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/maps/SendMapsActivityTest.java new file mode 100644 index 000000000..d9af47112 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/maps/SendMapsActivityTest.java @@ -0,0 +1,90 @@ +/* + * Copyright 2012 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.io.maps; + +import com.google.android.apps.mytracks.io.fusiontables.SendFusionTablesActivity; +import com.google.android.apps.mytracks.io.sendtogoogle.SendRequest; +import com.google.android.apps.mytracks.io.sendtogoogle.UploadResultActivity; +import com.google.android.apps.mytracks.io.spreadsheets.SendSpreadsheetsActivity; + +import android.test.AndroidTestCase; + +/** + * Tests the {@link SendMapsActivity}. + * + * @author Youtao Liu + */ +public class SendMapsActivityTest extends AndroidTestCase { + + private SendMapsActivity sendMapsActivity; + private SendRequest sendRequest; + + @Override + protected void setUp() throws Exception { + super.setUp(); + sendRequest = new SendRequest(1L); + sendMapsActivity = new SendMapsActivity(); + } + + /** + * Tests the method + * {@link SendMapsActivity#getNextClass(SendRequest, boolean)}. Sets the flags + * of "sendFusionTables","sendSpreadsheets" and "cancel" to true, true and false. + */ + public void testGetNextClass_notCancelSendFusionTables() { + sendRequest.setSendFusionTables(true); + sendRequest.setSendSpreadsheets(true); + Class next = sendMapsActivity.getNextClass(sendRequest, false); + assertEquals(SendFusionTablesActivity.class, next); + } + + /** + * Tests the method + * {@link SendMapsActivity#getNextClass(SendRequest, boolean)}. Sets the flags + * of "sendFusionTables","sendSpreadsheets" and "cancel" to false, true and false. + */ + public void testGetNextClass_notCancelSendSpreadsheets() { + sendRequest.setSendFusionTables(false); + sendRequest.setSendSpreadsheets(true); + Class next = sendMapsActivity.getNextClass(sendRequest, false); + assertEquals(SendSpreadsheetsActivity.class, next); + } + + /** + * Tests the method + * {@link SendMapsActivity#getNextClass(SendRequest, boolean)}. Sets the flags + * of "sendFusionTables","sendSpreadsheets" and "cancel" to false, false and false. + */ + public void testGetNextClass_notCancelNotSend() { + sendRequest.setSendFusionTables(false); + sendRequest.setSendSpreadsheets(false); + Class next = sendMapsActivity.getNextClass(sendRequest, false); + assertEquals(UploadResultActivity.class, next); + } + + /** + * Tests the method + * {@link SendMapsActivity#getNextClass(SendRequest, boolean)}. Sets the flags + * of "sendFusionTables","sendSpreadsheets" and "cancel" to true, true and true. + */ + public void testGetNextClass_cancelSendSpreadsheets() { + sendRequest.setSendFusionTables(true); + sendRequest.setSendSpreadsheets(true); + Class next = sendMapsActivity.getNextClass(sendRequest, true); + assertEquals(UploadResultActivity.class, next); + } + +} \ No newline at end of file diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/maps/SendMapsAsyncTaskTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/maps/SendMapsAsyncTaskTest.java new file mode 100644 index 000000000..a83da4073 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/maps/SendMapsAsyncTaskTest.java @@ -0,0 +1,327 @@ +/* + * Copyright 2012 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.io.maps; + +import com.google.android.apps.mytracks.Constants; +import com.google.android.apps.mytracks.TrackStubUtils; +import com.google.android.apps.mytracks.content.MyTracksProviderUtils; +import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator; +import com.google.android.apps.mytracks.content.Track; +import com.google.android.apps.mytracks.content.Waypoint; +import com.google.android.apps.mytracks.io.gdata.maps.MapsGDataConverter; +import com.google.android.apps.mytracks.io.sendtogoogle.SendRequest; +import com.google.android.testing.mocking.AndroidMock; +import com.google.android.testing.mocking.UsesMocks; + +import android.accounts.Account; +import android.database.Cursor; +import android.location.Location; +import android.test.AndroidTestCase; + +import java.util.List; + +import org.xmlpull.v1.XmlPullParserException; + +/** + * Tests {@link SendMapsAsyncTask}. + * + * @author Youtao Liu + */ +public class SendMapsAsyncTaskTest extends AndroidTestCase { + + private static final long TRACK_ID = 1; + // Records the run times of {@link SendMapsAsyncTaskMock#uploadMarker(String, + // String, String, Location)} + private int uploadMarkerCounter = 0; + // Records the run times of {@link + // SendMapsAsyncTaskMock#prepareAndUploadPoints(Track, List, + // boolean)} + private int prepareAndUploadPointsCounter = 0; + + private SendMapsActivity sendMapsActivityMock; + private MyTracksProviderUtils myTracksProviderUtilsMock; + private SendRequest sendRequest; + + private class SendMapsAsyncTaskMock extends SendMapsAsyncTask { + + private boolean[] uploadMarkerResult = { false, false }; + private boolean prepareAndUploadPointsResult = false; + + private SendMapsAsyncTaskMock(SendMapsActivity activity, long trackId, Account account, + MyTracksProviderUtils myTracksProviderUtils) { + super(activity, trackId, account, myTracksProviderUtils); + } + + @Override + boolean uploadMarker(String title, String description, String iconUrl, Location location) { + int runTimes = uploadMarkerCounter++; + return uploadMarkerResult[runTimes]; + } + + @Override + boolean prepareAndUploadPoints(Track track, List locations, boolean lastBatch) { + prepareAndUploadPointsCounter++; + return prepareAndUploadPointsResult; + } + } + + @Override + @UsesMocks({ SendMapsActivity.class, MyTracksProviderUtils.class }) + protected void setUp() throws Exception { + super.setUp(); + uploadMarkerCounter = 0; + prepareAndUploadPointsCounter = 0; + sendMapsActivityMock = AndroidMock.createMock(SendMapsActivity.class); + myTracksProviderUtilsMock = AndroidMock.createMock(MyTracksProviderUtils.class); + sendRequest = new SendRequest(TRACK_ID); + AndroidMock.expect(sendMapsActivityMock.getApplicationContext()).andReturn(getContext()); + } + + /** + * Tests {@link SendMapsAsyncTask#fetchSendMapId(Track)} when chooseMapId is + * null and makes sure it returns false. + */ + public void testFetchSendMapId_nullMapID() { + Track track = TrackStubUtils.createTrack(1); + AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock); + // Makes chooseMapId to null. + SendMapsAsyncTask sendMapsAsyncTask = new SendMapsAsyncTask(sendMapsActivityMock, + sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock); + // Returns false for an exception would be thrown. + assertFalse(sendMapsAsyncTask.fetchSendMapId(track)); + AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock); + } + + /** + * Tests the method {@link SendMapsAsyncTask#uploadAllTrackPoints(Track)} when + * the location iterator has no item. And makes sure it returns true. + */ + public void testUploadAllTrackPoints_empptyLocationIterator() { + LocationIterator locationIterator = AndroidMock.createMock(LocationIterator.class); + AndroidMock.expect(locationIterator.hasNext()).andReturn(false); + locationIterator.close(); + + Track track = TrackStubUtils.createTrack(1); + AndroidMock.expect(myTracksProviderUtilsMock.getTrackPointLocationIterator( + TRACK_ID, -1L, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY)) + .andReturn(locationIterator); + AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator); + SendMapsAsyncTask sendMapsAsyncTask = new SendMapsAsyncTask(sendMapsActivityMock, + sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock); + assertTrue(sendMapsAsyncTask.uploadAllTrackPoints(track)); + AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator); + } + + /** + * Tests the method {@link SendMapsAsyncTask#uploadAllTrackPoints(Track)} when + * uploads the first marker is failed. + */ + @UsesMocks(Cursor.class) + public void testUploadAllTrackPoints_uploadFirstMarkerFailed() { + Track track = TrackStubUtils.createTrack(1); + + LocationIterator locationIterator = AndroidMock.createMock(LocationIterator.class); + AndroidMock.expect(locationIterator.hasNext()).andReturn(true); + AndroidMock.expect(locationIterator.next()).andReturn(new Location("1")); + locationIterator.close(); + + AndroidMock.expect(myTracksProviderUtilsMock.getTrackPointLocationIterator( + TRACK_ID, -1L, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY)) + .andReturn(locationIterator); + + AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator); + SendMapsAsyncTaskMock sendMapsAsyncTask = new SendMapsAsyncTaskMock(sendMapsActivityMock, + sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock); + sendMapsAsyncTask.uploadMarkerResult[0] = false; + assertFalse(sendMapsAsyncTask.uploadAllTrackPoints(track)); + assertEquals(1, uploadMarkerCounter); + AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator); + } + + /** + * Tests the method {@link SendMapsAsyncTask#uploadAllTrackPoints(Track)} when + * uploads the two markers is successful but failed when + * prepareAndUploadPoints. + */ + @UsesMocks(Cursor.class) + public void testUploadAllTrackPoints_prepareAndUploadPointsFailed() { + Track track = TrackStubUtils.createTrack(1); + + LocationIterator locationIterator = AndroidMock.createMock(LocationIterator.class); + AndroidMock.expect(locationIterator.hasNext()).andReturn(true).times(2); + AndroidMock.expect(locationIterator.hasNext()).andReturn(false); + AndroidMock.expect(locationIterator.next()).andReturn(new Location("1")).times(2); + locationIterator.close(); + + AndroidMock.expect(myTracksProviderUtilsMock.getTrackPointLocationIterator( + TRACK_ID, -1L, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY)) + .andReturn(locationIterator); + + AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator); + SendMapsAsyncTaskMock sendMapsAsyncTask = new SendMapsAsyncTaskMock(sendMapsActivityMock, + sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock); + // For will be failed when run prepareAndUploadPoints, it no require to + // set uploadMarkerResult[1]. + sendMapsAsyncTask.uploadMarkerResult[0] = true; + sendMapsAsyncTask.prepareAndUploadPointsResult = false; + assertFalse(sendMapsAsyncTask.uploadAllTrackPoints(track)); + assertEquals(1, uploadMarkerCounter); + assertEquals(1, prepareAndUploadPointsCounter); + AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator); + } + + /** + * Tests the method {@link SendMapsAsyncTask#uploadAllTrackPoints(Track)} when + * uploads the last marker is failed. + */ + @UsesMocks(Cursor.class) + public void testUploadAllTrackPoints_uploadLastMarkerFailed() { + Track track = TrackStubUtils.createTrack(1); + + LocationIterator locationIterator = AndroidMock.createMock(LocationIterator.class); + AndroidMock.expect(locationIterator.hasNext()).andReturn(true).times(2); + AndroidMock.expect(locationIterator.hasNext()).andReturn(false); + AndroidMock.expect(locationIterator.next()).andReturn(new Location("1")).times(2); + locationIterator.close(); + + AndroidMock.expect(myTracksProviderUtilsMock.getTrackPointLocationIterator( + TRACK_ID, -1L, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY)) + .andReturn(locationIterator); + + AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator); + SendMapsAsyncTaskMock sendMapsAsyncTask = new SendMapsAsyncTaskMock(sendMapsActivityMock, + sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock); + sendMapsAsyncTask.uploadMarkerResult[0] = true; + sendMapsAsyncTask.uploadMarkerResult[1] = false; + sendMapsAsyncTask.prepareAndUploadPointsResult = true; + assertFalse(sendMapsAsyncTask.uploadAllTrackPoints(track)); + assertEquals(2, uploadMarkerCounter); + assertEquals(1, prepareAndUploadPointsCounter); + AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator); + } + + /** + * Tests the method {@link SendMapsAsyncTask#uploadAllTrackPoints(Track)} when + * return true.a + */ + @UsesMocks(Cursor.class) + public void testUploadAllTrackPoints_success() { + Track track = TrackStubUtils.createTrack(1); + + LocationIterator locationIterator = AndroidMock.createMock(LocationIterator.class); + AndroidMock.expect(locationIterator.hasNext()).andReturn(true).times(2); + AndroidMock.expect(locationIterator.hasNext()).andReturn(false); + AndroidMock.expect(locationIterator.next()).andReturn(new Location("1")).times(2); + locationIterator.close(); + + AndroidMock.expect(myTracksProviderUtilsMock.getTrackPointLocationIterator( + TRACK_ID, -1L, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY)) + .andReturn(locationIterator); + + AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator); + SendMapsAsyncTaskMock sendMapsAsyncTask = new SendMapsAsyncTaskMock(sendMapsActivityMock, + sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock); + sendMapsAsyncTask.uploadMarkerResult[0] = true; + sendMapsAsyncTask.uploadMarkerResult[1] = true; + sendMapsAsyncTask.prepareAndUploadPointsResult = true; + assertTrue(sendMapsAsyncTask.uploadAllTrackPoints(track)); + assertEquals(2, uploadMarkerCounter); + assertEquals(1, prepareAndUploadPointsCounter); + AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock, locationIterator); + } + + /** + * Tests the method {@link SendMapsAsyncTask#uploadWaypoints()} when cursor is + * null. + */ + @UsesMocks(Cursor.class) + public void testUploadWaypoints_nullCursor() { + AndroidMock.expect(myTracksProviderUtilsMock.getWaypointCursor( + TRACK_ID, -1L, Constants.MAX_LOADED_WAYPOINTS_POINTS)).andReturn(null); + AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock); + SendMapsAsyncTask sendMapsAsyncTask = new SendMapsAsyncTask(sendMapsActivityMock, + sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock); + assertTrue(sendMapsAsyncTask.uploadWaypoints()); + AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock); + } + + /** + * Tests the method {@link SendMapsAsyncTask#uploadWaypoints()} when there is + * only one point. + */ + @UsesMocks(Cursor.class) + public void testUploadWaypoints_onePoint() { + Cursor cursorMock = AndroidMock.createMock(Cursor.class); + AndroidMock.expect(cursorMock.moveToFirst()).andReturn(true); + // Only one point, so next is null. + AndroidMock.expect(cursorMock.moveToNext()).andReturn(false); + cursorMock.close(); + + AndroidMock.expect(myTracksProviderUtilsMock.getWaypointCursor( + TRACK_ID, -1L, Constants.MAX_LOADED_WAYPOINTS_POINTS)).andReturn(cursorMock); + + AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, cursorMock); + SendMapsAsyncTask sendMapsAsyncTask = new SendMapsAsyncTask(sendMapsActivityMock, + sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock); + + assertTrue(sendMapsAsyncTask.uploadWaypoints()); + AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock, cursorMock); + } + + /** + * Tests the method {@link SendMapsAsyncTask#uploadWaypoints()}. Makes sure a + * cursor is created and a way point is created with such cursor. + * + * @throws XmlPullParserException + */ + @UsesMocks(Cursor.class) + public void testUploadWaypoints() throws XmlPullParserException { + Cursor cursorMock = AndroidMock.createMock(Cursor.class); + MapsGDataConverter mapsGDataConverterMock = new MapsGDataConverter(); + + AndroidMock.expect(cursorMock.moveToFirst()).andReturn(true); + AndroidMock.expect(cursorMock.moveToNext()).andReturn(true); + cursorMock.close(); + + AndroidMock.expect(myTracksProviderUtilsMock.getWaypointCursor( + TRACK_ID, -1L, Constants.MAX_LOADED_WAYPOINTS_POINTS)).andReturn(cursorMock); + Waypoint waypoint = new Waypoint(); + waypoint.setLocation(TrackStubUtils.createMyTracksLocation()); + AndroidMock.expect(myTracksProviderUtilsMock.createWaypoint(cursorMock)) + .andReturn(waypoint).times(1); + + AndroidMock.replay(sendMapsActivityMock, myTracksProviderUtilsMock, cursorMock); + SendMapsAsyncTask sendMapsAsyncTask = new SendMapsAsyncTask(sendMapsActivityMock, + sendRequest.getTrackId(), sendRequest.getAccount(), myTracksProviderUtilsMock); + sendMapsAsyncTask.setMapsGDataConverter(mapsGDataConverterMock); + // Would be failed for there is no source for uploading. + assertFalse(sendMapsAsyncTask.uploadWaypoints()); + AndroidMock.verify(sendMapsActivityMock, myTracksProviderUtilsMock, cursorMock); + } + + /** + * Tests the method {@link SendMapsAsyncTask#getPercentage(int, int)}. + */ + public void testCountPercentage() { + assertEquals(SendMapsAsyncTask.PROGRESS_UPLOAD_DATA_MIN, SendMapsAsyncTask.getPercentage(0, 5)); + assertEquals( + SendMapsAsyncTask.PROGRESS_UPLOAD_DATA_MAX, SendMapsAsyncTask.getPercentage(50, 50)); + assertEquals((int) ((double) 5 / 11 + * (SendMapsAsyncTask.PROGRESS_UPLOAD_DATA_MAX - SendMapsAsyncTask.PROGRESS_UPLOAD_DATA_MIN) + + SendMapsAsyncTask.PROGRESS_UPLOAD_DATA_MIN), SendMapsAsyncTask.getPercentage(5, 11)); + } + +} \ No newline at end of file diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/maps/SendMapsUtilsTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/maps/SendMapsUtilsTest.java new file mode 100644 index 000000000..a7df7ccdf --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/maps/SendMapsUtilsTest.java @@ -0,0 +1,149 @@ +/* + * Copyright 2012 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.io.maps; + +import com.google.android.apps.mytracks.io.gdata.maps.MapsFeature; + +import android.location.Location; + +import java.util.ArrayList; + +import junit.framework.TestCase; + +/** + * Tests {@link SendMapsUtils}. + * + * @author Jimmy Shih + */ +public class SendMapsUtilsTest extends TestCase { + + /** + * Test {@link SendMapsUtils#buildMapsMarkerFeature(String, String, String, + * Location)} with a title. + */ + public void testBuildMapsMarkerFeature_with_title() { + Location location = new Location("test"); + location.setLatitude(123.0); + location.setLongitude(456.0); + MapsFeature mapFeature = SendMapsUtils.buildMapsMarkerFeature( + "name", "this\nmap\ndescription", "url", location); + assertEquals(MapsFeature.MARKER, mapFeature.getType()); + assertNotNull(mapFeature.getAndroidId()); + assertEquals("name", mapFeature.getTitle()); + assertEquals("this
map
description", mapFeature.getDescription()); + assertEquals("url", mapFeature.getIconUrl()); + assertEquals(123.0, mapFeature.getPoint(0).getLatitude()); + assertEquals(456.0, mapFeature.getPoint(0).getLongitude()); + } + + /** + * Test {@link SendMapsUtils#buildMapsMarkerFeature(String, String, String, + * Location)} with an empty title. + */ + public void testBuildMapsMarkerFeature_empty_title() { + Location location = new Location("test"); + location.setLatitude(123.0); + location.setLongitude(456.0); + MapsFeature mapFeature = SendMapsUtils.buildMapsMarkerFeature( + "", "description", "url", location); + assertEquals(MapsFeature.MARKER, mapFeature.getType()); + assertNotNull(mapFeature.getAndroidId()); + assertEquals("-", mapFeature.getTitle()); + assertEquals("description", mapFeature.getDescription()); + assertEquals("url", mapFeature.getIconUrl()); + assertEquals(123.0, mapFeature.getPoint(0).getLatitude()); + assertEquals(456.0, mapFeature.getPoint(0).getLongitude()); + } + + /** + * Test {@link SendMapsUtils#buildMapsMarkerFeature(String, String, String, + * Location)} with a null title. + */ + public void testBuildMapsMarkerFeature_null_title() { + Location location = new Location("test"); + location.setLatitude(123.0); + location.setLongitude(456.0); + MapsFeature mapFeature = SendMapsUtils.buildMapsMarkerFeature( + null, "description", "url", location); + assertEquals(MapsFeature.MARKER, mapFeature.getType()); + assertNotNull(mapFeature.getAndroidId()); + assertEquals("-", mapFeature.getTitle()); + assertEquals("description", mapFeature.getDescription()); + assertEquals("url", mapFeature.getIconUrl()); + assertEquals(123.0, mapFeature.getPoint(0).getLatitude()); + assertEquals(456.0, mapFeature.getPoint(0).getLongitude()); + } + + /** + * Test {@link SendMapsUtils#buildMapsLineFeature(String, ArrayList)} with a + * title. + */ + public void testBuildMapsLineFeature_with_title() { + ArrayList locations = new ArrayList(); + Location location = new Location("test"); + location.setLatitude(50.0); + location.setLongitude(100.0); + locations.add(location); + MapsFeature mapFeature = SendMapsUtils.buildMapsLineFeature("name", locations); + + assertEquals(MapsFeature.LINE, mapFeature.getType()); + assertNotNull(mapFeature.getAndroidId()); + assertEquals("name", mapFeature.getTitle()); + assertEquals(0x80FF0000, mapFeature.getColor()); + assertEquals(50.0, mapFeature.getPoint(0).getLatitude()); + assertEquals(100.0, mapFeature.getPoint(0).getLongitude()); + } + + /** + * Test {@link SendMapsUtils#buildMapsLineFeature(String, ArrayList)} with an + * empty title. + */ + public void testBuildMapsLineFeature_empty_title() { + ArrayList locations = new ArrayList(); + Location location = new Location("test"); + location.setLatitude(50.0); + location.setLongitude(100.0); + locations.add(location); + MapsFeature mapFeature = SendMapsUtils.buildMapsLineFeature("", locations); + + assertEquals(MapsFeature.LINE, mapFeature.getType()); + assertNotNull(mapFeature.getAndroidId()); + assertEquals("-", mapFeature.getTitle()); + assertEquals(0x80FF0000, mapFeature.getColor()); + assertEquals(50.0, mapFeature.getPoint(0).getLatitude()); + assertEquals(100.0, mapFeature.getPoint(0).getLongitude()); + } + + /** + * Test {@link SendMapsUtils#buildMapsLineFeature(String, ArrayList)} with a + * null title. + */ + public void testBuildMapsLineFeature_null_title() { + ArrayList locations = new ArrayList(); + Location location = new Location("test"); + location.setLatitude(50.0); + location.setLongitude(100.0); + locations.add(location); + MapsFeature mapFeature = SendMapsUtils.buildMapsLineFeature(null, locations); + + assertEquals(MapsFeature.LINE, mapFeature.getType()); + assertNotNull(mapFeature.getAndroidId()); + assertEquals("-", mapFeature.getTitle()); + assertEquals(0x80FF0000, mapFeature.getColor()); + assertEquals(50.0, mapFeature.getPoint(0).getLatitude()); + assertEquals(100.0, mapFeature.getPoint(0).getLongitude()); + } +} \ No newline at end of file diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/sendtogoogle/SendRequestTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/sendtogoogle/SendRequestTest.java new file mode 100644 index 000000000..4e379512e --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/sendtogoogle/SendRequestTest.java @@ -0,0 +1,287 @@ +/* + * Copyright 2012 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.io.sendtogoogle; + +import android.accounts.Account; +import android.os.Parcel; +import android.os.Parcelable; +import android.test.AndroidTestCase; + +/** + * Tests the {@link SendRequest}. + * + * @author Youtao Liu + */ +public class SendRequestTest extends AndroidTestCase { + + private SendRequest sendRequest; + + private final static String ACCOUNTNAME = "testAccount1"; + private final static String ACCOUNTYPE = "testType1"; + private final static String DRIVE_SHARE_EMAILS = "foo@foo.com"; + private final static String SHARE_URL = "url@url.com"; + + @Override + protected void setUp() throws Exception { + super.setUp(); + sendRequest = new SendRequest(1); + } + + /** + * Tests the method {@link SendRequest#getTrackId()}. The value should be set + * to 1 when it is initialed in setup method. + */ + public void testGetTrackId() { + assertEquals(1, sendRequest.getTrackId()); + } + + public void testIsSendMaps() { + assertEquals(false, sendRequest.isSendMaps()); + sendRequest.setSendMaps(true); + assertEquals(true, sendRequest.isSendMaps()); + } + + public void testIsSendFusionTables() { + assertEquals(false, sendRequest.isSendFusionTables()); + sendRequest.setSendFusionTables(true); + assertEquals(true, sendRequest.isSendFusionTables()); + } + + /** + * Tests the method {@link SendRequest#isSendSpreadsheets()}. The value should + * be set to false which is its default value when it is initialed in setup + * method. + */ + public void testIsSendSpreadsheets() { + assertEquals(false, sendRequest.isSendSpreadsheets()); + sendRequest.setSendSpreadsheets(true); + assertEquals(true, sendRequest.isSendSpreadsheets()); + } + + /** + * Tests the method {@link SendRequest#getAccount()}. The value should be set + * to null which is its default value when it is initialed in setup method. + */ + public void testGetAccount() { + assertEquals(null, sendRequest.getAccount()); + Account account = new Account(ACCOUNTNAME, ACCOUNTYPE); + sendRequest.setAccount(account); + assertEquals(account, sendRequest.getAccount()); + } + + /** + * Tests the method {@link SendRequest#isMapsSuccess()}. The value should be + * set to false which is its default value when it is initialed in setup + * method. + */ + public void testIsMapsSuccess() { + assertEquals(false, sendRequest.isMapsSuccess()); + sendRequest.setMapsSuccess(true); + assertEquals(true, sendRequest.isMapsSuccess()); + } + + /** + * Tests the method {@link SendRequest#isFusionTablesSuccess()}. The value + * should be set to false which is its default value when it is initialed in + * setup method. + */ + public void testIsFusionTablesSuccess() { + assertEquals(false, sendRequest.isFusionTablesSuccess()); + sendRequest.setFusionTablesSuccess(true); + assertEquals(true, sendRequest.isFusionTablesSuccess()); + } + + /** + * Tests the method {@link SendRequest#isSpreadsheetsSuccess()}. The value + * should be set to false which is its default value when it is initialed in + * setup method. + */ + public void testIsSpreadsheetsSuccess() { + assertEquals(false, sendRequest.isSpreadsheetsSuccess()); + sendRequest.setSpreadsheetsSuccess(true); + assertEquals(true, sendRequest.isSpreadsheetsSuccess()); + } + + /** + * Tests SendRequest.CREATOR.createFromParcel when all values are true. + */ + public void testCreateFromParcel_true() { + Parcel parcel = Parcel.obtain(); + parcel.setDataPosition(0); + parcel.writeLong(2); + parcel.writeByte((byte) 1); + parcel.writeByte((byte) 1); + parcel.writeByte((byte) 1); + parcel.writeByte((byte) 1); + parcel.writeByte((byte) 1); + parcel.writeByte((byte) 1); + parcel.writeString(DRIVE_SHARE_EMAILS); + Account account = new Account(ACCOUNTNAME, ACCOUNTYPE); + parcel.writeParcelable(account, 0); + parcel.writeByte((byte) 1); + parcel.writeByte((byte) 1); + parcel.writeByte((byte) 1); + parcel.writeByte((byte) 1); + parcel.writeString(SHARE_URL); + parcel.setDataPosition(0); + sendRequest = SendRequest.CREATOR.createFromParcel(parcel); + assertEquals(2, sendRequest.getTrackId()); + assertTrue(sendRequest.isSendDrive()); + assertTrue(sendRequest.isSendMaps()); + assertTrue(sendRequest.isSendFusionTables()); + assertTrue(sendRequest.isSendSpreadsheets()); + assertTrue(sendRequest.isDriveSync()); + assertTrue(sendRequest.isDriveSharePublic()); + assertEquals(DRIVE_SHARE_EMAILS, sendRequest.getDriveShareEmails()); + assertEquals(account, sendRequest.getAccount()); + assertTrue(sendRequest.isDriveSuccess()); + assertTrue(sendRequest.isMapsSuccess()); + assertTrue(sendRequest.isFusionTablesSuccess()); + assertTrue(sendRequest.isSpreadsheetsSuccess()); + assertEquals(SHARE_URL, sendRequest.getShareUrl()); + } + + /** + * Tests SendRequest.CREATOR.createFromParcel when all values are false. + */ + public void testCreateFromParcel_false() { + Parcel parcel = Parcel.obtain(); + parcel.setDataPosition(0); + parcel.writeLong(4); + parcel.writeByte((byte) 0); + parcel.writeByte((byte) 0); + parcel.writeByte((byte) 0); + parcel.writeByte((byte) 0); + parcel.writeByte((byte) 0); + parcel.writeByte((byte) 0); + parcel.writeString(null); + Account account = new Account(ACCOUNTNAME, ACCOUNTYPE); + parcel.writeParcelable(account, 0); + parcel.writeByte((byte) 0); + parcel.writeByte((byte) 0); + parcel.writeByte((byte) 0); + parcel.writeByte((byte) 0); + parcel.writeString(null); + parcel.setDataPosition(0); + sendRequest = SendRequest.CREATOR.createFromParcel(parcel); + assertEquals(4, sendRequest.getTrackId()); + assertFalse(sendRequest.isSendDrive()); + assertFalse(sendRequest.isSendMaps()); + assertFalse(sendRequest.isSendFusionTables()); + assertFalse(sendRequest.isSendSpreadsheets()); + assertFalse(sendRequest.isDriveSync()); + assertFalse(sendRequest.isDriveSharePublic()); + assertNull(sendRequest.getDriveShareEmails()); + assertEquals(account, sendRequest.getAccount()); + assertFalse(sendRequest.isDriveSuccess()); + assertFalse(sendRequest.isMapsSuccess()); + assertFalse(sendRequest.isFusionTablesSuccess()); + assertFalse(sendRequest.isSpreadsheetsSuccess()); + assertNull(sendRequest.getShareUrl()); + } + + /** + * Tests {@link SendRequest#writeToParcel(Parcel, int)} with default values. + */ + public void testWriteToParcel_default() { + sendRequest = new SendRequest(1); + Parcel parcel = Parcel.obtain(); + parcel.setDataPosition(0); + sendRequest.writeToParcel(parcel, 1); + parcel.setDataPosition(0); + long trackId = parcel.readLong(); + boolean sendDrive = parcel.readByte() == 1; + boolean sendMaps = parcel.readByte() == 1; + boolean sendFusionTables = parcel.readByte() == 1; + boolean sendSpreadsheets = parcel.readByte() == 1; + boolean driveSync = parcel.readByte() == 1; + boolean driveSharePublic = parcel.readByte() == 1; + String dirveShareEmails = parcel.readString(); + Parcelable account = parcel.readParcelable(null); + boolean driveSuccess = parcel.readByte() == 1; + boolean mapsSuccess = parcel.readByte() == 1; + boolean fusionTablesSuccess = parcel.readByte() == 1; + boolean spreadsheetsSuccess = parcel.readByte() == 1; + String shareUrl = parcel.readString(); + assertEquals(1, trackId); + assertFalse(sendDrive); + assertFalse(sendMaps); + assertFalse(sendFusionTables); + assertFalse(sendSpreadsheets); + assertFalse(driveSync); + assertFalse(driveSharePublic); + assertNull(dirveShareEmails); + assertNull(account); + assertFalse(driveSuccess); + assertFalse(mapsSuccess); + assertFalse(fusionTablesSuccess); + assertFalse(spreadsheetsSuccess); + assertNull(shareUrl); + } + + /** + * Tests {@link SendRequest#writeToParcel(Parcel, int)}. + */ + public void testWriteToParcel() { + sendRequest = new SendRequest(4); + sendRequest.setSendDrive(true); + sendRequest.setSendMaps(true); + sendRequest.setSendFusionTables(true); + sendRequest.setSendSpreadsheets(true); + sendRequest.setDriveSync(true); + sendRequest.setDriveSharePublic(true); + sendRequest.setDriveShareEmails(DRIVE_SHARE_EMAILS); + Account accountNew = new Account(ACCOUNTNAME + "2", ACCOUNTYPE + "2"); + sendRequest.setAccount(accountNew); + sendRequest.setMapsSuccess(true); + sendRequest.setDriveSuccess(true); + sendRequest.setFusionTablesSuccess(true); + sendRequest.setSpreadsheetsSuccess(true); + sendRequest.setShareUrl(SHARE_URL); + Parcel parcel = Parcel.obtain(); + parcel.setDataPosition(0); + sendRequest.writeToParcel(parcel, 1); + parcel.setDataPosition(0); + long trackId = parcel.readLong(); + boolean sendDrive = parcel.readByte() == 1; + boolean sendMaps = parcel.readByte() == 1; + boolean sendFusionTables = parcel.readByte() == 1; + boolean sendSpreadsheets = parcel.readByte() == 1; + boolean driveSync = parcel.readByte() == 1; + boolean driveSharePublic = parcel.readByte() == 1; + String driveShareEmails = parcel.readString(); + Parcelable account = parcel.readParcelable(null); + boolean driveSuccess = parcel.readByte() == 1; + boolean mapsSuccess = parcel.readByte() == 1; + boolean fusionTablesSuccess = parcel.readByte() == 1; + boolean spreadsheetsSuccess = parcel.readByte() == 1; + String shareUrl = parcel.readString(); + assertEquals(4, trackId); + assertTrue(sendDrive); + assertTrue(sendMaps); + assertTrue(sendFusionTables); + assertTrue(sendSpreadsheets); + assertTrue(driveSync); + assertTrue(driveSharePublic); + assertEquals(DRIVE_SHARE_EMAILS, driveShareEmails); + assertEquals(accountNew, account); + assertTrue(driveSuccess); + assertTrue(mapsSuccess); + assertTrue(fusionTablesSuccess); + assertTrue(spreadsheetsSuccess); + assertEquals(SHARE_URL, shareUrl); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/sendtogoogle/SendToGoogleUtilsTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/sendtogoogle/SendToGoogleUtilsTest.java new file mode 100644 index 000000000..5577d5c64 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/sendtogoogle/SendToGoogleUtilsTest.java @@ -0,0 +1,124 @@ +/* + * Copyright 2012 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.io.sendtogoogle; + +/** + * Tests the {@link SendToGoogleUtils}. + * + * @author Youtao Liu + */ +import com.google.android.apps.mytracks.TrackStubUtils; +import com.google.android.apps.mytracks.content.MyTracksLocation; +import com.google.android.apps.mytracks.content.Track; + +import android.location.Location; + +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +public class SendToGoogleUtilsTest extends TestCase { + + private final static long TRACK_ID = 1L; + private final static String TRACK_CATEGORY = "trackCategory"; + private final static String TRACK_NAME = "trackName"; + private final static double DIFFERENCE = 0.02; + private final static double INVALID_LATITUDE = 91; + + /** + * Tests the method + * {@link SendToGoogleUtils#endSegment(Track, long, ArrayList)} + * when there is only one location in a segment. + */ + public void testPrepareTrackSegment_onlyOneLocation() { + Track segment = TrackStubUtils.createTrack(1); + assertFalse(SendToGoogleUtils.endSegment(segment, -1L, null)); + } + + /** + * Tests the method + * {@link SendToGoogleUtils#endSegment(Track, long, ArrayList)} when there + * is no stop time. + */ + public void testPrepareTrackSegment_noStopTime() { + Track segment = TrackStubUtils.createTrack(2); + assertEquals(-1L, segment.getTripStatistics().getStopTime()); + + ArrayList tracksArray = new ArrayList(); + assertTrue(SendToGoogleUtils.endSegment( + segment, segment.getLocations().get(1).getTime(), tracksArray)); + assertEquals(segment, tracksArray.get(0)); + // The stop time should be the time of last location + assertEquals( + segment.getLocations().get(1).getTime(), segment.getTripStatistics().getStopTime()); + } + + /** + * Tests the method + * {@link SendToGoogleUtils#prepareLocations(Track, java.util.List)} . + */ + public void testPrepareLocations() { + Track trackStub = TrackStubUtils.createTrack(2); + trackStub.setId(TRACK_ID); + trackStub.setName(TRACK_NAME); + trackStub.setCategory(TRACK_CATEGORY); + + List locationsArray = new ArrayList(); + // Adds 100 location to List. + for (int i = 0; i < 100; i++) { + // Use this variable as a flag to make all points in the track can be kept + // after run the LocationUtils#decimate(Track, double) with + // Ramer–Douglas–Peucker algorithm. + double latitude = TrackStubUtils.INITIAL_LATITUDE; + if (i % 2 == 0) { + latitude -= DIFFERENCE * (i % 10); + } + // Inserts 9 points which have wrong latitude, so would have 10 segments. + if (i % 10 == 0 && i > 0) { + MyTracksLocation location = TrackStubUtils.createMyTracksLocation(); + location.setLatitude(INVALID_LATITUDE); + locationsArray.add(location); + } else { + locationsArray.add(TrackStubUtils.createMyTracksLocation(latitude, + TrackStubUtils.INITIAL_LONGITUDE + DIFFERENCE * (i % 10), + TrackStubUtils.INITIAL_ALTITUDE + DIFFERENCE * (i % 10))); + } + } + ArrayList result = SendToGoogleUtils.prepareLocations(trackStub, locationsArray); + assertEquals(10, result.size()); + // Checks all segments. + for (int i = 0; i < 10; i++) { + Track segmentOne = result.get(i); + assertEquals(TRACK_ID, segmentOne.getId()); + assertEquals(TRACK_NAME, segmentOne.getName()); + assertEquals(TRACK_CATEGORY, segmentOne.getCategory()); + } + // Checks all locations in the first segment. + for (int j = 0; j < 9; j++) { + double latitude = TrackStubUtils.INITIAL_LATITUDE; + if (j % 2 == 0) { + latitude -= DIFFERENCE * (j % 10); + } + Location oneLocation = result.get(0).getLocations().get(j); + assertEquals(TrackStubUtils.createMyTracksLocation().getAltitude() + DIFFERENCE * (j % 10), + oneLocation.getAltitude()); + assertEquals(latitude, oneLocation.getLatitude()); + assertEquals(TrackStubUtils.createMyTracksLocation().getLongitude() + DIFFERENCE * (j % 10), + oneLocation.getLongitude()); + } + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/spreadsheets/SendSpreadsheetsUtilsTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/spreadsheets/SendSpreadsheetsUtilsTest.java new file mode 100644 index 000000000..d830d1ba1 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/io/spreadsheets/SendSpreadsheetsUtilsTest.java @@ -0,0 +1,74 @@ +/* + * Copyright 2012 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.io.spreadsheets; + +import com.google.android.apps.mytracks.io.spreadsheets.SendSpreadsheetsUtils; + +import android.test.AndroidTestCase; + +/** + * Tests {@link SendSpreadsheetsUtils}. + * + * @author Jimmy Shih + */ +public class SendSpreadsheetsUtilsTest extends AndroidTestCase { + + /** + * Tests {@link SendSpreadsheetsUtils#getDistance(double, boolean)} with metric units. + */ + public void testGetDistance_metric() { + assertEquals("1.22", SendSpreadsheetsUtils.getDistance(1222.3, true)); + } + + /** + * Tests {@link SendSpreadsheetsUtils#getDistance(double, boolean)} with imperial + * units. + */ + public void testGetDistance_imperial() { + assertEquals("0.76", SendSpreadsheetsUtils.getDistance(1222.3, false)); + } + + /** + * Tests {@link SendSpreadsheetsUtils#getSpeed(double, boolean)} with metric units. + */ + public void testGetSpeed_metric() { + assertEquals("15.55", SendSpreadsheetsUtils.getSpeed(4.32, true)); + } + + /** + * Tests {@link SendSpreadsheetsUtils#getSpeed(double, boolean)} with imperial units. + */ + public void testGetSpeed_imperial() { + assertEquals("9.66", SendSpreadsheetsUtils.getSpeed(4.32, false)); + } + + /** + * Tests {@link SendSpreadsheetsUtils#getElevation(double, boolean)} with metric + * units. + */ + public void testGetElevation_metric() { + assertEquals("3", SendSpreadsheetsUtils.getElevation(3.456, true)); + } + + /** + * Tests {@link SendSpreadsheetsUtils#getElevation(double, boolean)} with imperial + * units. + */ + public void testGetElevation_imperial() { + assertEquals("11", SendSpreadsheetsUtils.getElevation(3.456, false)); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/maps/DynamicSpeedTrackPathDescriptorTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/maps/DynamicSpeedTrackPathDescriptorTest.java new file mode 100644 index 000000000..ad18a243c --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/maps/DynamicSpeedTrackPathDescriptorTest.java @@ -0,0 +1,104 @@ +/* + * Copyright 2012 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.maps; + +import com.google.android.apps.mytracks.util.PreferencesUtils; +import com.google.android.maps.mytracks.R; + +import android.content.Context; +import android.test.AndroidTestCase; + +/** + * Tests for the {@link DynamicSpeedTrackPathDescriptor}. + * + * @author Youtao Liu + */ +public class DynamicSpeedTrackPathDescriptorTest extends AndroidTestCase { + + private Context context; + + @Override + protected void setUp() throws Exception { + super.setUp(); + context = getContext(); + } + + /** + * Tests the method {@link DynamicSpeedTrackPathDescriptor#getSpeedMargin()} + * with zero, normal and illegal value. + */ + public void testGetSpeedMargin() { + // The default value of speedMargin is 25. + int[] expectations = { 0, 50, 99, 25 }; + // Test + for (int i = 0; i < expectations.length; i++) { + PreferencesUtils.setInt(context, R.string.track_color_mode_percentage_key, expectations[i]); + DynamicSpeedTrackPathDescriptor dynamicSpeedTrackPathDescriptor = new DynamicSpeedTrackPathDescriptor( + context); + assertEquals(expectations[i], dynamicSpeedTrackPathDescriptor.getSpeedMargin()); + } + } + + /** + * Tests {@link DynamicSpeedTrackPathDescriptor#getSlowSpeed()}. + */ + public void testGetSlowSpeed() { + DynamicSpeedTrackPathDescriptor dynamicSpeedTrackPathDescriptor = new DynamicSpeedTrackPathDescriptor( + context); + dynamicSpeedTrackPathDescriptor.setAverageMovingSpeed(50); + dynamicSpeedTrackPathDescriptor.setSpeedMargin(10); + assertEquals(50.0, dynamicSpeedTrackPathDescriptor.getAverageMovingSpeed()); + assertEquals(45.0, dynamicSpeedTrackPathDescriptor.getSlowSpeed()); + } + + /** + * Tests {@link DynamicSpeedTrackPathDescriptor#getNormalSpeed()}. + */ + public void testGetNormalSpeed() { + DynamicSpeedTrackPathDescriptor dynamicSpeedTrackPathDescriptor = new DynamicSpeedTrackPathDescriptor( + context); + dynamicSpeedTrackPathDescriptor.setAverageMovingSpeed(50); + dynamicSpeedTrackPathDescriptor.setSpeedMargin(10); + assertEquals(50.0, dynamicSpeedTrackPathDescriptor.getAverageMovingSpeed()); + assertEquals(55.0, dynamicSpeedTrackPathDescriptor.getNormalSpeed()); + } + + /** + * Tests {@link DynamicSpeedTrackPathDescriptor#updateState(com.google.android.apps.mytracks.stats.TripStatistics)} + * by different averageMovingSpeed. + */ + public void testIsDiffereceSignificant() { + DynamicSpeedTrackPathDescriptor dynamicSpeedTrackPathDescriptor = new DynamicSpeedTrackPathDescriptor( + context); + double[] averageMovingSpeeds = { 0, 30, 30, 30 }; + double[] newAverageMovingSpeed = { 20, 30, + // Difference is less than CRITICAL_DIFFERENCE_PERCENTAGE + 30 * (1 + (DynamicSpeedTrackPathDescriptor.CRITICAL_DIFFERENCE_PERCENTAGE / 100) / 2), + // Difference is more than CRITICAL_DIFFERENCE_PERCENTAGE + 30 * (1 + (DynamicSpeedTrackPathDescriptor.CRITICAL_DIFFERENCE_PERCENTAGE / 100.00) * 2) }; + boolean[] expectedValues = { true, false, false, true }; + double[] expectedAverageMovingSpeed = { 0, 30, 30, 30 }; + // Test + for (int i = 0; i < newAverageMovingSpeed.length; i++) { + dynamicSpeedTrackPathDescriptor.setAverageMovingSpeed(averageMovingSpeeds[i]); + assertEquals(expectedValues[i], dynamicSpeedTrackPathDescriptor.isDifferenceSignificant( + averageMovingSpeeds[i], newAverageMovingSpeed[i])); + assertEquals(expectedAverageMovingSpeed[i], + dynamicSpeedTrackPathDescriptor.getAverageMovingSpeed()); + } + } +} \ No newline at end of file diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/maps/FixedSpeedTrackPathDescriptorTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/maps/FixedSpeedTrackPathDescriptorTest.java new file mode 100644 index 000000000..ec9df1791 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/maps/FixedSpeedTrackPathDescriptorTest.java @@ -0,0 +1,92 @@ +/* + * Copyright 2012 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.maps; + +import com.google.android.apps.mytracks.util.PreferencesUtils; +import com.google.android.apps.mytracks.util.UnitConversions; +import com.google.android.maps.mytracks.R; + +import android.content.Context; +import android.test.AndroidTestCase; + +/** + * Tests for the {@link FixedSpeedTrackPathDescriptor}. + * + * @author Youtao Liu + */ +public class FixedSpeedTrackPathDescriptorTest extends AndroidTestCase { + + @Override + protected void tearDown() throws Exception { + Context context = getContext(); + PreferencesUtils.setString( + context, R.string.stats_units_key, PreferencesUtils.STATS_UNITS_DEFAULT); + PreferencesUtils.setInt(context, R.string.track_color_mode_slow_key, + PreferencesUtils.TRACK_COLOR_MODE_SLOW_DEFAULT); + PreferencesUtils.setInt(context, R.string.track_color_mode_medium_key, + PreferencesUtils.TRACK_COLOR_MODE_MEDIUM_DEFAULT); + super.tearDown(); + } + + /** + * Tests when the slow speed and the normal speed are both zero. + */ + public void testGetSpeed_zero() { + testSpeed(0, 0); + } + + /** + * Tests when the slow speed and the normal speed are both one. + */ + public void testGetSpeed_one() { + testSpeed(1, 1); + } + + /** + * Tests when the slow speed and the normal speed are both large number. E.g., + * 99 and 100. + */ + public void testGetSpeed_large() { + testSpeed(99, 100); + } + + /** + * Tests when the slow speed and the normal speed are both the default value. + */ + public void testGetSpeed_default() { + testSpeed(PreferencesUtils.TRACK_COLOR_MODE_SLOW_DEFAULT, + PreferencesUtils.TRACK_COLOR_MODE_MEDIUM_DEFAULT); + } + + private void testSpeed(int slowSpeed, int normalSpeed) { + testSpeed(slowSpeed, normalSpeed, true); + testSpeed(slowSpeed, normalSpeed, false); + } + + private void testSpeed(int slowSpeed, int normalSpeed, boolean metric) { + Context context = getContext(); + PreferencesUtils.setString(context, R.string.stats_units_key, + context.getString(metric ? R.string.stats_units_metric : R.string.stats_units_imperial)); + PreferencesUtils.setInt(context, R.string.track_color_mode_slow_key, slowSpeed); + PreferencesUtils.setInt(context, R.string.track_color_mode_medium_key, normalSpeed); + FixedSpeedTrackPathDescriptor fixedSpeedTrackPathDescriptor = new FixedSpeedTrackPathDescriptor( + context); + double expectedSlowSpeed = metric ? slowSpeed : slowSpeed * UnitConversions.MI_TO_KM; + double expectedNormalSpeed = metric ? normalSpeed : normalSpeed * UnitConversions.MI_TO_KM; + assertEquals(expectedSlowSpeed, fixedSpeedTrackPathDescriptor.getSlowSpeed()); + assertEquals(expectedNormalSpeed, fixedSpeedTrackPathDescriptor.getNormalSpeed()); + } +} \ No newline at end of file diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/maps/MultiColorTrackPathTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/maps/MultiColorTrackPathTest.java new file mode 100644 index 000000000..c388fab8b --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/maps/MultiColorTrackPathTest.java @@ -0,0 +1,60 @@ +/* + * Copyright 2012 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.maps; + +import android.content.Context; +import android.test.AndroidTestCase; + +/** + * Tests for the {@link MultiColorTrackPath}. + * + * @author Youtao Liu + */ +public class MultiColorTrackPathTest extends AndroidTestCase { + + private MultiColorTrackPath multiColorTrackPath; + private Context context; + + @Override + protected void setUp() throws Exception { + super.setUp(); + context = getContext(); + } + + /** + * Tests the {@link MultiColorTrackPath#getColor(double)} when use dynamic speed + * track path descriptor. + */ + public void testGetColor_DynamicSpeedTrackPathDescriptor() { + DynamicSpeedTrackPathDescriptor dynamicSpeedTrackPathDescriptor = new DynamicSpeedTrackPathDescriptor( + context); + dynamicSpeedTrackPathDescriptor.setAverageMovingSpeed(50); + dynamicSpeedTrackPathDescriptor.setSpeedMargin(10); + multiColorTrackPath = new MultiColorTrackPath(context, dynamicSpeedTrackPathDescriptor); + + // Slow speed should be below 45 (10% of 50), and fast speed should be above + // 55 (10% of 50). + assertEquals(multiColorTrackPath.getSlowColor(), multiColorTrackPath.getColor(5)); + assertEquals(multiColorTrackPath.getSlowColor(), multiColorTrackPath.getColor(44)); + assertEquals(multiColorTrackPath.getNormalColor(), multiColorTrackPath.getColor(50)); + assertEquals(multiColorTrackPath.getNormalColor(), multiColorTrackPath.getColor(54)); + assertEquals(multiColorTrackPath.getFastColor(), multiColorTrackPath.getColor(56)); + assertEquals(multiColorTrackPath.getFastColor(), multiColorTrackPath.getColor(100)); + + assertNotSame(multiColorTrackPath.getSlowColor(), multiColorTrackPath.getNormalColor()); + assertNotSame(multiColorTrackPath.getSlowColor(), multiColorTrackPath.getFastColor()); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/AdaptiveLocationListenerPolicyTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/AdaptiveLocationListenerPolicyTest.java new file mode 100644 index 000000000..22741cad5 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/AdaptiveLocationListenerPolicyTest.java @@ -0,0 +1,76 @@ +/* + * Copyright 2012 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.services; + +import junit.framework.TestCase; + +/** + * Tests the {@link AdaptiveLocationListenerPolicy}. + * + * @author youtaol + */ +public class AdaptiveLocationListenerPolicyTest extends TestCase { + + private AdaptiveLocationListenerPolicy adocationListenerPolicy; + private static final long MIN = 1000; + private static final long MAX = 3000; + private static final int MIN_DISTANCE = 10; + private static final long NEW_IDLE_TIME_BIG = 10000; + private static final long NEW_IDLE_TIME_NORMAL = 5000; + private static final long NEW_IDLE_TIME_SMALL = 2000; + private static final long NEW_IDLE_TIME_LESS_THAN_MIN = 500; + + @Override + protected void setUp() throws Exception { + super.setUp(); + adocationListenerPolicy = new AdaptiveLocationListenerPolicy(MIN, MAX, MIN_DISTANCE); + } + + /** + * Tests the + * {@link AdaptiveLocationListenerPolicy#getDesiredPollingInterval()} in four + * situations. + *

    + *
  • The newIdleTime is bigger than max interval.
  • + *
  • The newIdleTime is between min and max interval.
  • + *
  • The newIdleTime is smaller than max interval.
  • + *
  • The newIdleTime is smaller than the smallest interval unit.
  • + *
+ */ + public void testGetDesiredPollingInterval() { + adocationListenerPolicy.updateIdleTime(NEW_IDLE_TIME_BIG); + assertEquals(MAX, adocationListenerPolicy.getDesiredPollingInterval()); + + adocationListenerPolicy.updateIdleTime(NEW_IDLE_TIME_NORMAL); + // First get the half of NEW_IDLE_TIME_NORMAL, and then round it to the + // nearest second. + assertEquals((NEW_IDLE_TIME_NORMAL / 2 / 1000) * 1000, + adocationListenerPolicy.getDesiredPollingInterval()); + + adocationListenerPolicy.updateIdleTime(NEW_IDLE_TIME_SMALL); + assertEquals(MIN, adocationListenerPolicy.getDesiredPollingInterval()); + + adocationListenerPolicy.updateIdleTime(NEW_IDLE_TIME_LESS_THAN_MIN); + assertEquals(MIN, adocationListenerPolicy.getDesiredPollingInterval()); + } + + /** + * Tests the method {@link AdaptiveLocationListenerPolicy#getMinDistance()}. + */ + public void testGetMinDistance() { + assertEquals(MIN_DISTANCE, adocationListenerPolicy.getMinDistance()); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/ControlRecordingServiceTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/ControlRecordingServiceTest.java new file mode 100644 index 000000000..e7c887a5f --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/ControlRecordingServiceTest.java @@ -0,0 +1,105 @@ +/* + * Copyright 2012 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.services; + +import com.google.android.maps.mytracks.R; +import com.google.android.testing.mocking.UsesMocks; + +import android.content.Context; +import android.content.Intent; +import android.os.RemoteException; +import android.test.ServiceTestCase; + +import org.easymock.EasyMock; + +/** + * Tests {@link ControlRecordingService}. + * + * @author Youtao Liu + */ +public class ControlRecordingServiceTest extends ServiceTestCase { + + private Context context; + private ControlRecordingService controlRecordingService; + + public ControlRecordingServiceTest() { + super(ControlRecordingService.class); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + context = getContext(); + } + + /** + * Tests the start of {@link ControlRecordingService} and tests the method + * {@link ControlRecordingService#onHandleIntent(Intent, ITrackRecordingService)} + * to start a track recording. + */ + @UsesMocks(ITrackRecordingService.class) + public void testStartRecording() { + assertNull(controlRecordingService); + Intent intent = startControlRecordingService(context.getString(R.string.track_action_start)); + assertNotNull(controlRecordingService); + + ITrackRecordingService iTrackRecordingServiceMock = EasyMock + .createStrictMock(ITrackRecordingService.class); + try { + EasyMock.expect(iTrackRecordingServiceMock.startNewTrack()).andReturn(1L); + EasyMock.replay(iTrackRecordingServiceMock); + controlRecordingService.onHandleIntent(intent, iTrackRecordingServiceMock); + EasyMock.verify(iTrackRecordingServiceMock); + } catch (RemoteException e) { + fail(); + } + } + + /** + * Tests the method + * {@link ControlRecordingService#onHandleIntent(Intent, ITrackRecordingService)} + * to stop a track recording. + */ + @UsesMocks(ITrackRecordingService.class) + public void testStopRecording() { + Intent intent = startControlRecordingService(context.getString(R.string.track_action_end)); + + ITrackRecordingService iTrackRecordingServiceMock = EasyMock + .createStrictMock(ITrackRecordingService.class); + try { + iTrackRecordingServiceMock.endCurrentTrack(); + EasyMock.replay(iTrackRecordingServiceMock); + controlRecordingService.onHandleIntent(intent, iTrackRecordingServiceMock); + EasyMock.verify(iTrackRecordingServiceMock); + } catch (RemoteException e) { + fail(); + } + } + + /** + * Starts a ControlRecordingService with a specified action. + * + * @param action the action string in the start intent + */ + private Intent startControlRecordingService(String action) { + Intent intent = new Intent(context, ControlRecordingService.class); + intent.setAction(action); + startService(intent); + controlRecordingService = getService(); + return intent; + } + +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/TestRecordingService.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/TestRecordingService.java new file mode 100644 index 000000000..42b467c92 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/TestRecordingService.java @@ -0,0 +1,65 @@ +// Copyright 2012 Google Inc. All Rights Reserved. + +package com.google.android.apps.mytracks.services; + +import android.app.PendingIntent; +import android.app.Service; +import android.test.ServiceTestCase; +import android.util.Log; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * A {@link TrackRecordingService} that can be used with + * {@link ServiceTestCase}. {@link ServiceTestCase} throws a null pointer + * exception when the service calls + * {@link Service#startForeground(int, android.app.Notification)} and + * {@link Service#stopForeground(boolean)}. + *

+ * See http://code.google.com/p/android/issues/detail?id=12122 + *

+ * Wrap these two methods in wrappers and override them. + * + * @author Jimmy Shih + */ +public class TestRecordingService extends TrackRecordingService { + + private static final String TAG = TestRecordingService.class.getSimpleName(); + + @Override + protected void startForegroundService(PendingIntent pendingIntent, int messageId) { + try { + Method setForegroundMethod = Service.class.getMethod("setForeground", boolean.class); + setForegroundMethod.invoke(this, true); + } catch (SecurityException e) { + Log.e(TAG, "Unable to start a service in foreground", e); + } catch (NoSuchMethodException e) { + Log.e(TAG, "Unable to start a service in foreground", e); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Unable to start a service in foreground", e); + } catch (IllegalAccessException e) { + Log.e(TAG, "Unable to start a service in foreground", e); + } catch (InvocationTargetException e) { + Log.e(TAG, "Unable to start a service in foreground", e); + } + } + + @Override + protected void stopForegroundService() { + try { + Method setForegroundMethod = Service.class.getMethod("setForeground", boolean.class); + setForegroundMethod.invoke(this, false); + } catch (SecurityException e) { + Log.e(TAG, "Unable to start a service in foreground", e); + } catch (NoSuchMethodException e) { + Log.e(TAG, "Unable to start a service in foreground", e); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Unable to start a service in foreground", e); + } catch (IllegalAccessException e) { + Log.e(TAG, "Unable to start a service in foreground", e); + } catch (InvocationTargetException e) { + Log.e(TAG, "Unable to start a service in foreground", e); + } + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/TrackRecordingServiceTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/TrackRecordingServiceTest.java new file mode 100644 index 000000000..1ebf39ced --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/TrackRecordingServiceTest.java @@ -0,0 +1,798 @@ +/* + * 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. + */ +package com.google.android.apps.mytracks.services; + +import com.google.android.apps.mytracks.Constants; +import com.google.android.apps.mytracks.content.MyTracksProvider; +import com.google.android.apps.mytracks.content.MyTracksProviderUtils; +import com.google.android.apps.mytracks.content.Track; +import com.google.android.apps.mytracks.content.Waypoint; +import com.google.android.apps.mytracks.content.Waypoint.WaypointType; +import com.google.android.apps.mytracks.content.WaypointCreationRequest; +import com.google.android.apps.mytracks.stats.TripStatistics; +import com.google.android.apps.mytracks.util.ApiAdapterFactory; +import com.google.android.apps.mytracks.util.GoogleLocationUtils; +import com.google.android.apps.mytracks.util.PreferencesUtils; +import com.google.android.maps.mytracks.R; + +import android.content.BroadcastReceiver; +import android.content.ContentResolver; +import android.content.Context; +import android.content.ContextWrapper; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.SharedPreferences; +import android.database.Cursor; +import android.location.Location; +import android.net.Uri; +import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteException; +import android.provider.Settings; +import android.test.RenamingDelegatingContext; +import android.test.ServiceTestCase; +import android.test.mock.MockContentProvider; +import android.test.mock.MockContentResolver; +import android.test.mock.MockCursor; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; +import android.util.Log; + +import java.util.ArrayList; +import java.util.List; + +/** + * Tests for the MyTracks track recording service. + *

+ * TODO: The original class, ServiceTestCase, has a few limitations, e.g. it's + * not possible to properly shutdown the service, unless tearDown() is called, + * which prevents from testing multiple scenarios in a single test (see + * runFunctionTest for more details). + * + * @author Bartlomiej Niechwiej + */ +public class TrackRecordingServiceTest extends ServiceTestCase { + + private Context context; + private MyTracksProviderUtils providerUtils; + + /* + * In order to support starting and binding to the service in the same unit + * test, we provide a workaround, as the original class doesn't allow to bind + * after the service has been previously started. + */ + + private boolean bound; + private Intent serviceIntent; + + public TrackRecordingServiceTest() { + super(TestRecordingService.class); + } + + /** + * A context wrapper with the user provided {@link ContentResolver}. TODO: + * Move to test utils package. + */ + public static class MockContext extends ContextWrapper { + private final ContentResolver contentResolver; + + public MockContext(ContentResolver contentResolver, Context base) { + super(base); + this.contentResolver = contentResolver; + } + + @Override + public ContentResolver getContentResolver() { + return contentResolver; + } + } + + @Override + protected IBinder bindService(Intent intent) { + if (getService() != null) { + if (bound) { + throw new IllegalStateException("Service: " + getService() + " is already bound"); + } + bound = true; + serviceIntent = intent.cloneFilter(); + return getService().onBind(intent); + } else { + return super.bindService(intent); + } + } + + @Override + protected void shutdownService() { + if (bound) { + assertNotNull(getService()); + getService().onUnbind(serviceIntent); + bound = false; + } + super.shutdownService(); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + + /* + * Create a mock context that uses a mock content resolver and a renaming + * delegating context. + */ + MockContentResolver mockContentResolver = new MockContentResolver(); + RenamingDelegatingContext renamingDelegatingContext = new RenamingDelegatingContext( + getContext(), getContext(), "test."); + context = new MockContext(mockContentResolver, renamingDelegatingContext); + + // Set up the mock content resolver + MyTracksProvider myTracksProvider = new MyTracksProvider(); + myTracksProvider.attachInfo(context, null); + mockContentResolver.addProvider(MyTracksProviderUtils.AUTHORITY, myTracksProvider); + + MockContentProvider settingsProvider = new MockContentProvider(context) { + @Override + public Bundle call(String method, String arg, Bundle extras) { + return null; + } + + @Override + public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, + String sortOrder) { + return null; + } + }; + mockContentResolver.addProvider(Settings.AUTHORITY, settingsProvider); + + MockContentProvider googleSettingsProvider = new MockContentProvider(context) { + @Override + public Bundle call(String method, String arg, Bundle extras) { + return null; + } + + @Override + public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, + String sortOrder) { + MockCursor mockCursor = new MockCursor() { + @Override + public int getCount() { + return 1; + } + + @Override + public boolean moveToNext() { + return true; + } + + @Override + public String getString(int columnIndex) { + return String.valueOf(GoogleLocationUtils.USE_LOCATION_FOR_SERVICES_ON); + } + + @Override + public void close() {} + }; + return mockCursor; + } + }; + mockContentResolver.addProvider("com.google.settings", googleSettingsProvider); + + // Set the context + setContext(context); + + providerUtils = MyTracksProviderUtils.Factory.get(context); + + SharedPreferences sharedPreferences = context.getSharedPreferences( + Constants.SETTINGS_NAME, Context.MODE_PRIVATE); + // Let's use default values. + ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(sharedPreferences.edit().clear()); + + // Disable auto resume by default. + updateAutoResumePrefs(PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT, 0); + // No recording track. + PreferencesUtils.setLong( + context, R.string.recording_track_id_key, PreferencesUtils.RECORDING_TRACK_ID_DEFAULT); + } + + @SmallTest + public void testStartable() { + startService(createStartIntent()); + assertNotNull(getService()); + } + + @MediumTest + public void testBindable() { + IBinder service = bindService(createStartIntent()); + assertNotNull(service); + } + + @MediumTest + public void testResumeAfterReboot_shouldResume() throws Exception { + // Insert a dummy track and mark it as recording track. + createDummyTrack(123L, System.currentTimeMillis(), true); + + // Clear the number of attempts and set the timeout to 10 min. + updateAutoResumePrefs(PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT, + PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_DEFAULT); + + // Start the service in "resume" mode (simulates the on-reboot action). + Intent startIntent = createStartIntent(); + startIntent.putExtra(TrackRecordingService.RESUME_TRACK_EXTRA_NAME, true); + startService(startIntent); + assertNotNull(getService()); + + // We expect to resume the previous track. + assertTrue(getService().isRecording()); + ITrackRecordingService service = bindAndGetService(createStartIntent()); + assertEquals(123L, service.getRecordingTrackId()); + } + + /* + * TODO: shutdownService() has a bug and doesn't set mServiceCreated to false, + * thus preventing from a second call to onCreate(). Report the bug to Android + * team. Until then, the following tests and checks must be commented out. + * + * TODO: If fixed, remove "disabled" prefix from the test name. + */ + @MediumTest + public void disabledTestResumeAfterReboot_simulateReboot() throws Exception { + updateAutoResumePrefs(PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT, + PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_DEFAULT); + ITrackRecordingService service = bindAndGetService(createStartIntent()); + assertFalse(service.isRecording()); + + // Simulate recording a track. + long id = service.startNewTrack(); + assertTrue(service.isRecording()); + assertEquals(id, service.getRecordingTrackId()); + shutdownService(); + assertEquals(id, PreferencesUtils.getLong(context, R.string.recording_track_id_key)); + + // Start the service in "resume" mode (simulates the on-reboot action). + Intent startIntent = createStartIntent(); + startIntent.putExtra(TrackRecordingService.RESUME_TRACK_EXTRA_NAME, true); + startService(startIntent); + assertNotNull(getService()); + + assertTrue(getService().isRecording()); + } + + @MediumTest + public void testResumeAfterReboot_noRecordingTrack() throws Exception { + // Insert a dummy track and mark it as recording track. + createDummyTrack(123L, System.currentTimeMillis(), false); + + // Clear the number of attempts and set the timeout to 10 min. + updateAutoResumePrefs(PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT, + PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_DEFAULT); + + // Start the service in "resume" mode (simulates the on-reboot action). + Intent startIntent = createStartIntent(); + startIntent.putExtra(TrackRecordingService.RESUME_TRACK_EXTRA_NAME, true); + startService(startIntent); + assertNotNull(getService()); + + // We don't expect to resume the previous track, because it was stopped. + assertFalse(getService().isRecording()); + ITrackRecordingService service = bindAndGetService(createStartIntent()); + assertEquals(-1L, service.getRecordingTrackId()); + } + + @MediumTest + public void testResumeAfterReboot_expiredTrack() throws Exception { + // Insert a dummy track last updated 20 min ago. + createDummyTrack(123L, System.currentTimeMillis() - 20 * 60 * 1000, true); + + // Clear the number of attempts and set the timeout to 10 min. + updateAutoResumePrefs(PreferencesUtils.AUTO_RESUME_TRACK_CURRENT_RETRY_DEFAULT, + PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_DEFAULT); + + // Start the service in "resume" mode (simulates the on-reboot action). + Intent startIntent = createStartIntent(); + startIntent.putExtra(TrackRecordingService.RESUME_TRACK_EXTRA_NAME, true); + startService(startIntent); + assertNotNull(getService()); + + // We don't expect to resume the previous track, because it has expired. + assertFalse(getService().isRecording()); + ITrackRecordingService service = bindAndGetService(createStartIntent()); + assertEquals(-1L, service.getRecordingTrackId()); + } + + @MediumTest + public void testResumeAfterReboot_tooManyAttempts() throws Exception { + // Insert a dummy track. + createDummyTrack(123L, System.currentTimeMillis(), true); + + // Set the number of attempts to max. + updateAutoResumePrefs(TrackRecordingService.MAX_AUTO_RESUME_TRACK_RETRY_ATTEMPTS, + PreferencesUtils.AUTO_RESUME_TRACK_TIMEOUT_DEFAULT); + + // Start the service in "resume" mode (simulates the on-reboot action). + Intent startIntent = createStartIntent(); + startIntent.putExtra(TrackRecordingService.RESUME_TRACK_EXTRA_NAME, true); + startService(startIntent); + assertNotNull(getService()); + + // We don't expect to resume the previous track, because there were already + // too many attempts. + assertFalse(getService().isRecording()); + ITrackRecordingService service = bindAndGetService(createStartIntent()); + assertEquals(-1L, service.getRecordingTrackId()); + } + + @MediumTest + public void testRecording_noTracks() throws Exception { + List tracks = providerUtils.getAllTracks(); + assertTrue(tracks.isEmpty()); + + ITrackRecordingService service = bindAndGetService(createStartIntent()); + // Test if we start in no-recording mode by default. + assertFalse(service.isRecording()); + assertEquals(-1L, service.getRecordingTrackId()); + } + + @MediumTest + public void testRecording_oldTracks() throws Exception { + createDummyTrack(123L, -1L, false); + + ITrackRecordingService service = bindAndGetService(createStartIntent()); + assertFalse(service.isRecording()); + assertEquals(-1L, service.getRecordingTrackId()); + } + + @MediumTest + public void testRecording_orphanedRecordingTrack() throws Exception { + // Just set recording track to a bogus value. + PreferencesUtils.setLong(context, R.string.recording_track_id_key, 256L); + + // Make sure that the service will not start recording and will clear + // the bogus track. + ITrackRecordingService service = bindAndGetService(createStartIntent()); + assertFalse(service.isRecording()); + assertEquals(-1L, service.getRecordingTrackId()); + } + + /** + * Synchronous/waitable broadcast receiver to be used in testing. + */ + private class BlockingBroadcastReceiver extends BroadcastReceiver { + private static final long MAX_WAIT_TIME_MS = 10000; + private List receivedIntents = new ArrayList(); + + public List getReceivedIntents() { + return receivedIntents; + } + + @Override + public void onReceive(Context ctx, Intent intent) { + Log.d("MyTracksTest", "Got broadcast: " + intent); + synchronized (receivedIntents) { + receivedIntents.add(intent); + receivedIntents.notifyAll(); + } + } + + public boolean waitUntilReceived(int receiveCount) { + long deadline = System.currentTimeMillis() + MAX_WAIT_TIME_MS; + synchronized (receivedIntents) { + while (receivedIntents.size() < receiveCount) { + try { + // Wait releases synchronized lock until it returns + receivedIntents.wait(500); + } catch (InterruptedException e) { + // Do nothing + } + + if (System.currentTimeMillis() > deadline) { + return false; + } + } + } + + return true; + } + } + + @MediumTest + public void testStartNewTrack_noRecording() throws Exception { + // NOTICE: due to the way Android permissions work, if this fails, + // uninstall the test apk then retry - the test must be installed *after* + // My Tracks (go figure). + // Reference: http://code.google.com/p/android/issues/detail?id=5521 + BlockingBroadcastReceiver startReceiver = new BlockingBroadcastReceiver(); + String startAction = context.getString(R.string.track_started_broadcast_action); + context.registerReceiver(startReceiver, new IntentFilter(startAction)); + + List tracks = providerUtils.getAllTracks(); + assertTrue(tracks.isEmpty()); + + ITrackRecordingService service = bindAndGetService(createStartIntent()); + assertFalse(service.isRecording()); + + long id = service.startNewTrack(); + assertTrue(id >= 0); + assertTrue(service.isRecording()); + Track track = providerUtils.getTrack(id); + assertNotNull(track); + assertEquals(id, track.getId()); + assertEquals(PreferencesUtils.getString( + context, R.string.default_activity_key, PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT), + track.getCategory()); + assertEquals(id, PreferencesUtils.getLong(context, R.string.recording_track_id_key)); + assertEquals(id, service.getRecordingTrackId()); + + // Verify that the start broadcast was received. + assertTrue(startReceiver.waitUntilReceived(1)); + List receivedIntents = startReceiver.getReceivedIntents(); + assertEquals(1, receivedIntents.size()); + Intent broadcastIntent = receivedIntents.get(0); + assertEquals(startAction, broadcastIntent.getAction()); + assertEquals(id, + broadcastIntent.getLongExtra(context.getString(R.string.track_id_broadcast_extra), -1L)); + + context.unregisterReceiver(startReceiver); + } + + @MediumTest + public void testStartNewTrack_alreadyRecording() throws Exception { + createDummyTrack(123L, -1L, true); + + ITrackRecordingService service = bindAndGetService(createStartIntent()); + assertTrue(service.isRecording()); + + // Starting a new track when there is a recording should just return -1L. + long newTrack = service.startNewTrack(); + assertEquals(-1L, newTrack); + + assertEquals(123L, PreferencesUtils.getLong(context, R.string.recording_track_id_key)); + assertEquals(123L, service.getRecordingTrackId()); + } + + @MediumTest + public void testEndCurrentTrack_alreadyRecording() throws Exception { + // See comment above if this fails randomly. + BlockingBroadcastReceiver stopReceiver = new BlockingBroadcastReceiver(); + String stopAction = context.getString(R.string.track_stopped_broadcast_action); + context.registerReceiver(stopReceiver, new IntentFilter(stopAction)); + + createDummyTrack(123L, -1L, true); + + ITrackRecordingService service = bindAndGetService(createStartIntent()); + assertTrue(service.isRecording()); + + // End the current track. + service.endCurrentTrack(); + assertFalse(service.isRecording()); + assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, + PreferencesUtils.getLong(context, R.string.recording_track_id_key)); + assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, service.getRecordingTrackId()); + + // Verify that the stop broadcast was received. + assertTrue(stopReceiver.waitUntilReceived(1)); + List receivedIntents = stopReceiver.getReceivedIntents(); + assertEquals(1, receivedIntents.size()); + Intent broadcastIntent = receivedIntents.get(0); + assertEquals(stopAction, broadcastIntent.getAction()); + assertEquals(123L, + broadcastIntent.getLongExtra(context.getString(R.string.track_id_broadcast_extra), -1L)); + + context.unregisterReceiver(stopReceiver); + } + + @MediumTest + public void testEndCurrentTrack_noRecording() throws Exception { + ITrackRecordingService service = bindAndGetService(createStartIntent()); + assertFalse(service.isRecording()); + + /* + * Ending the current track when there is no recording should not result in + * any error. + */ + service.endCurrentTrack(); + + assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, + PreferencesUtils.getLong(context, R.string.recording_track_id_key)); + assertEquals(PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, service.getRecordingTrackId()); + } + + @MediumTest + public void testIntegration_completeRecordingSession() throws Exception { + List tracks = providerUtils.getAllTracks(); + assertTrue(tracks.isEmpty()); + fullRecordingSession(); + } + + @MediumTest + public void testInsertStatisticsMarker_noRecordingTrack() throws Exception { + ITrackRecordingService service = bindAndGetService(createStartIntent()); + assertFalse(service.isRecording()); + + long waypointId = service.insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS); + assertEquals(-1L, waypointId); + } + + @MediumTest + public void testInsertStatisticsMarker_validLocation() throws Exception { + createDummyTrack(123L, -1L, true); + + ITrackRecordingService service = bindAndGetService(createStartIntent()); + assertTrue(service.isRecording()); + assertFalse(service.isPaused()); + insertLocation(service); + + assertEquals(1, service.insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS)); + assertEquals(2, service.insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS)); + + Waypoint wpt = providerUtils.getWaypoint(2); + assertEquals(getContext().getString(R.string.marker_statistics_icon_url), wpt.getIcon()); + assertEquals(getContext().getString(R.string.marker_split_name_format, 1), wpt.getName()); + assertEquals(WaypointType.STATISTICS, wpt.getType()); + assertEquals(123L, wpt.getTrackId()); + assertEquals(0.0, wpt.getLength()); + assertNotNull(wpt.getLocation()); + assertNotNull(wpt.getTripStatistics()); + // TODO check the rest of the params. + + // TODO: Check waypoint 2. + } + + @MediumTest + public void testInsertWaypointMarker_noRecordingTrack() throws Exception { + ITrackRecordingService service = bindAndGetService(createStartIntent()); + assertFalse(service.isRecording()); + + long waypointId = service.insertWaypoint(WaypointCreationRequest.DEFAULT_WAYPOINT); + assertEquals(-1L, waypointId); + } + + @MediumTest + public void testInsertWaypointMarker_validWaypoint() throws Exception { + createDummyTrack(123L, -1L, true); + + ITrackRecordingService service = bindAndGetService(createStartIntent()); + assertTrue(service.isRecording()); + insertLocation(service); + + assertEquals(1, service.insertWaypoint(WaypointCreationRequest.DEFAULT_WAYPOINT)); + Waypoint wpt = providerUtils.getWaypoint(1); + assertEquals(getContext().getString(R.string.marker_waypoint_icon_url), wpt.getIcon()); + assertEquals(getContext().getString(R.string.marker_name_format, 1), wpt.getName()); + assertEquals(WaypointType.WAYPOINT, wpt.getType()); + assertEquals(123L, wpt.getTrackId()); + assertEquals(0.0, wpt.getLength()); + assertNotNull(wpt.getLocation()); + assertNull(wpt.getTripStatistics()); + } + + @MediumTest + public void testWithProperties_voiceFrequencyDefault() throws Exception { + PreferencesUtils.setInt( + context, R.string.voice_frequency_key, PreferencesUtils.VOICE_FREQUENCY_DEFAULT); + fullRecordingSession(); + } + + @MediumTest + public void testWithProperties_voiceFrequencyByDistance() throws Exception { + PreferencesUtils.setInt(context, R.string.voice_frequency_key, -1); + fullRecordingSession(); + } + + @MediumTest + public void testWithProperties_voiceFrequencyByTime() throws Exception { + PreferencesUtils.setInt(context, R.string.voice_frequency_key, 1); + fullRecordingSession(); + } + + @MediumTest + public void testWithProperties_maxRecordingDistanceDefault() throws Exception { + PreferencesUtils.setInt(context, R.string.max_recording_distance_key, + PreferencesUtils.MAX_RECORDING_DISTANCE_DEFAULT); + fullRecordingSession(); + } + + @MediumTest + public void testWithProperties_maxRecordingDistance() throws Exception { + PreferencesUtils.setInt(context, R.string.max_recording_distance_key, 50); + fullRecordingSession(); + } + + @MediumTest + public void testWithProperties_minRecordingDistanceDefault() throws Exception { + PreferencesUtils.setInt(context, R.string.recording_distance_interval_key, + PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT); + fullRecordingSession(); + } + + @MediumTest + public void testWithProperties_minRecordingDistance() throws Exception { + PreferencesUtils.setInt(context, R.string.recording_distance_interval_key, 2); + fullRecordingSession(); + } + + @MediumTest + public void testWithProperties_splitFrequencyDefault() throws Exception { + PreferencesUtils.setInt( + context, R.string.split_frequency_key, PreferencesUtils.SPLIT_FREQUENCY_DEFAULT); + fullRecordingSession(); + } + + @MediumTest + public void testWithProperties_splitFrequencyByDistance() throws Exception { + PreferencesUtils.setInt(context, R.string.split_frequency_key, -1); + fullRecordingSession(); + } + + @MediumTest + public void testWithProperties_splitFrequencyByTime() throws Exception { + PreferencesUtils.setInt(context, R.string.split_frequency_key, 1); + fullRecordingSession(); + } + + @MediumTest + public void testWithProperties_metricUnitsDefault() throws Exception { + PreferencesUtils.setString( + context, R.string.stats_units_key, PreferencesUtils.STATS_UNITS_DEFAULT); + fullRecordingSession(); + } + + @MediumTest + public void testWithProperties_metricUnitsDisabled() throws Exception { + PreferencesUtils.setString( + context, R.string.stats_units_key, context.getString(R.string.stats_units_imperial)); + fullRecordingSession(); + } + + @MediumTest + public void testWithProperties_minRecordingIntervalDefault() throws Exception { + PreferencesUtils.setInt(context, R.string.min_recording_interval_key, + PreferencesUtils.MIN_RECORDING_INTERVAL_DEFAULT); + fullRecordingSession(); + } + + @MediumTest + public void testWithProperties_minRecordingInterval() throws Exception { + PreferencesUtils.setInt(context, R.string.min_recording_interval_key, 2); + fullRecordingSession(); + } + + @MediumTest + public void testWithProperties_minRequiredAccuracyDefault() throws Exception { + PreferencesUtils.setInt(context, R.string.recording_gps_accuracy_key, + PreferencesUtils.RECORDING_GPS_ACCURACY_DEFAULT); + fullRecordingSession(); + } + + @MediumTest + public void testWithProperties_minRequiredAccuracy() throws Exception { + PreferencesUtils.setInt(context, R.string.recording_gps_accuracy_key, 500); + fullRecordingSession(); + } + + @MediumTest + public void testWithProperties_sensorTypeDefault() throws Exception { + PreferencesUtils.setString( + context, R.string.sensor_type_key, PreferencesUtils.SENSOR_TYPE_DEFAULT); + fullRecordingSession(); + } + + @MediumTest + public void testWithProperties_sensorTypeZephyr() throws Exception { + PreferencesUtils.setString( + context, R.string.sensor_type_key, context.getString(R.string.sensor_type_value_zephyr)); + fullRecordingSession(); + } + + private ITrackRecordingService bindAndGetService(Intent intent) { + ITrackRecordingService service = ITrackRecordingService.Stub.asInterface(bindService(intent)); + assertNotNull(service); + return service; + } + + private Track createDummyTrack(long id, long stopTime, boolean isRecording) { + Track dummyTrack = new Track(); + dummyTrack.setId(id); + dummyTrack.setName("Dummy Track"); + TripStatistics tripStatistics = new TripStatistics(); + tripStatistics.setStopTime(stopTime); + dummyTrack.setTripStatistics(tripStatistics); + addTrack(dummyTrack, isRecording); + return dummyTrack; + } + + private void updateAutoResumePrefs(int attempts, int timeoutMins) { + PreferencesUtils.setInt(context, R.string.auto_resume_track_current_retry_key, attempts); + PreferencesUtils.setInt(context, R.string.auto_resume_track_timeout_key, timeoutMins); + } + + private Intent createStartIntent() { + Intent startIntent = new Intent(); + startIntent.setClass(context, TrackRecordingService.class); + return startIntent; + } + + private void addTrack(Track track, boolean isRecording) { + assertTrue(track.getId() >= 0); + providerUtils.insertTrack(track); + assertEquals(track.getId(), providerUtils.getTrack(track.getId()).getId()); + PreferencesUtils.setLong(context, R.string.recording_track_id_key, + isRecording ? track.getId() : PreferencesUtils.RECORDING_TRACK_ID_DEFAULT); + PreferencesUtils.setBoolean(context, R.string.recording_track_paused_key, !isRecording); + } + + private void fullRecordingSession() throws Exception { + ITrackRecordingService service = bindAndGetService(createStartIntent()); + assertFalse(service.isRecording()); + + // Start a track. + long id = service.startNewTrack(); + assertTrue(id >= 0); + assertTrue(service.isRecording()); + Track track = providerUtils.getTrack(id); + assertNotNull(track); + assertEquals(id, track.getId()); + assertEquals(id, PreferencesUtils.getLong(context, R.string.recording_track_id_key)); + assertEquals(id, service.getRecordingTrackId()); + + // Insert a few points, markers and statistics. + long startTime = System.currentTimeMillis(); + for (int i = 0; i < 30; i++) { + Location loc = new Location("gps"); + loc.setLongitude(35.0f + i / 10.0f); + loc.setLatitude(45.0f - i / 5.0f); + loc.setAccuracy(5); + loc.setSpeed(10); + loc.setTime(startTime + i * 10000); + loc.setBearing(3.0f); + service.insertTrackPoint(loc); + + if (i % 10 == 0) { + service.insertWaypoint(WaypointCreationRequest.DEFAULT_STATISTICS); + } else if (i % 7 == 0) { + service.insertWaypoint(WaypointCreationRequest.DEFAULT_WAYPOINT); + } + } + + // Stop the track. Validate if it has correct data. + service.endCurrentTrack(); + assertFalse(service.isRecording()); + assertEquals(-1L, service.getRecordingTrackId()); + track = providerUtils.getTrack(id); + assertNotNull(track); + assertEquals(id, track.getId()); + TripStatistics tripStatistics = track.getTripStatistics(); + assertNotNull(tripStatistics); + assertTrue(tripStatistics.getStartTime() > 0); + assertTrue(tripStatistics.getStopTime() >= tripStatistics.getStartTime()); + } + + /** + * Inserts a location and waits for 100ms. + * + * @param trackRecordingService the track recording service + */ + private void insertLocation(ITrackRecordingService trackRecordingService) + throws RemoteException, InterruptedException { + Location location = new Location("gps"); + location.setLongitude(35.0f); + location.setLatitude(45.0f); + location.setAccuracy(5); + location.setSpeed(10); + location.setTime(System.currentTimeMillis()); + location.setBearing(3.0f); + trackRecordingService.insertTrackPoint(location); + Thread.sleep(200); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/sensors/PolarMessageParserTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/sensors/PolarMessageParserTest.java new file mode 100644 index 000000000..bcc6fe555 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/sensors/PolarMessageParserTest.java @@ -0,0 +1,69 @@ +package com.google.android.apps.mytracks.services.sensors; + +import com.google.android.apps.mytracks.content.Sensor; +import com.google.android.apps.mytracks.util.ApiAdapterFactory; + +import junit.framework.TestCase; + +public class PolarMessageParserTest extends TestCase { + + PolarMessageParser parser = new PolarMessageParser(); + // A complete and valid Polar HxM packet + // FE08F701D1001104FE08F702D1001104 + private final byte[] originalBuf = + {(byte) 0xFE, 0x08, (byte) 0xF7, 0x01, (byte) 0xD1, 0x00, 0x11, 0x04, (byte) 0xFE, 0x08, + (byte) 0xF7, 0x02, (byte) 0xD1, 0x00, 0x11, 0x04}; + private byte[] buf; + + public void setUp() { + buf = ApiAdapterFactory.getApiAdapter().copyByteArray(originalBuf, 0, originalBuf.length); + } + + public void testIsValid() { + assertTrue(parser.isValid(buf)); + } + + public void testIsValid_invalidHeader() { + // Invalidate header. + buf[0] = 0x03; + assertFalse(parser.isValid(buf)); + } + + public void testIsValid_invalidCheckbyte() { + // Invalidate checkbyte. + buf[2] = 0x03; + assertFalse(parser.isValid(buf)); + } + + public void testIsValid_invalidSequence() { + // Invalidate sequence. + buf[3] = 0x11; + assertFalse(parser.isValid(buf)); + } + + public void testParseBuffer() { + buf[5] = 70; + Sensor.SensorDataSet sds = parser.parseBuffer(buf); + assertTrue(sds.hasHeartRate()); + assertTrue(sds.getHeartRate().getState() == Sensor.SensorState.SENDING); + assertEquals(70, sds.getHeartRate().getValue()); + } + + public void testFindNextAlignment_offset() { + // The first 4 bytes are garbage + buf = new byte[originalBuf.length + 4]; + buf[0] = 4; + buf[1] = 2; + buf[2] = 4; + buf[3] = 2; + + // Then the valid message. + System.arraycopy(originalBuf, 0, buf, 4, originalBuf.length); + assertEquals(4, parser.findNextAlignment(buf)); + } + + public void testFindNextAlignment_invalid() { + buf[0] = 0; + assertEquals(-1, parser.findNextAlignment(buf)); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/sensors/SensorManagerFactoryTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/sensors/SensorManagerFactoryTest.java new file mode 100644 index 000000000..4c920bb59 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/sensors/SensorManagerFactoryTest.java @@ -0,0 +1,47 @@ +package com.google.android.apps.mytracks.services.sensors; + +import com.google.android.apps.mytracks.Constants; +import com.google.android.apps.mytracks.util.ApiAdapterFactory; +import com.google.android.apps.mytracks.util.PreferencesUtils; +import com.google.android.maps.mytracks.R; + +import android.content.Context; +import android.content.SharedPreferences; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; + +public class SensorManagerFactoryTest extends AndroidTestCase { + + @Override + protected void setUp() throws Exception { + super.setUp(); + + SharedPreferences sharedPreferences = getContext().getSharedPreferences( + Constants.SETTINGS_NAME, Context.MODE_PRIVATE); + // Let's use default values. + ApiAdapterFactory.getApiAdapter().applyPreferenceChanges(sharedPreferences.edit().clear()); + } + + @SmallTest + public void testDefaultSettings() throws Exception { + assertNull(SensorManagerFactory.getSystemSensorManager(getContext())); + } + + @SmallTest + public void testCreateZephyr() throws Exception { + assertClassForName(ZephyrSensorManager.class, R.string.sensor_type_value_zephyr); + } + + @SmallTest + public void testCreatePolar() throws Exception { + assertClassForName(PolarSensorManager.class, R.string.sensor_type_value_polar); + } + + private void assertClassForName(Class c, int i) { + PreferencesUtils.setString(getContext(), R.string.sensor_type_key, getContext().getString(i)); + SensorManager sm = SensorManagerFactory.getSystemSensorManager(getContext()); + assertNotNull(sm); + assertTrue(c.isInstance(sm)); + SensorManagerFactory.releaseSystemSensorManager(); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/sensors/StrideReadingsTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/sensors/StrideReadingsTest.java new file mode 100644 index 000000000..43e186208 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/sensors/StrideReadingsTest.java @@ -0,0 +1,63 @@ +/* + * 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.services.sensors; + +import junit.framework.TestCase; + +/** + * @author Dominik Rottsches + */ +public class StrideReadingsTest extends TestCase { + + public void testNoReadingOnStartup() { + StrideReadings strideReadings = new StrideReadings(); + assertEquals(StrideReadings.CADENCE_NOT_AVAILABLE, strideReadings.getCadence()); + } + + public void testAverageCadenceAvailable() { + StrideReadings strideReadings = new StrideReadings(); + // 2 steps / second => Cadence is 120 / minute + for (int i = 1; i <= 30; i++) { + strideReadings.updateStrideReading(i*2); + if (i >= StrideReadings.MIN_READINGS_FOR_AVERAGE) { + assertEquals(120, strideReadings.getCadence()); + } else { + assertEquals(StrideReadings.CADENCE_NOT_AVAILABLE, strideReadings.getCadence()); + } + } + } + + /** + * Tests for correct calculation after rolling over at 128 strides, + * just like the HxM seems to do it. + */ + public void testRollover() { + StrideReadings strideReadings = new StrideReadings(); + // 1 step per second => Cadence is 60 / minute + // Updating readings counting upwards from initialStrides - + // initialStrides set to a value below 128 to ensure rollover. + int initialStrides = 128 - StrideReadings.NUM_READINGS_FOR_AVERAGE - 5; + + for (int i = 1; i <= StrideReadings.NUM_READINGS_FOR_AVERAGE + 10; i++) { + strideReadings.updateStrideReading((initialStrides + i) % 128); + if (i >= StrideReadings.MIN_READINGS_FOR_AVERAGE) { + assertEquals(60, strideReadings.getCadence()); + } else { + assertEquals(StrideReadings.CADENCE_NOT_AVAILABLE, strideReadings.getCadence()); + } + } + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/sensors/ZephyrMessageParserTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/sensors/ZephyrMessageParserTest.java new file mode 100644 index 000000000..61d99167a --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/sensors/ZephyrMessageParserTest.java @@ -0,0 +1,55 @@ +package com.google.android.apps.mytracks.services.sensors; + +import com.google.android.apps.mytracks.content.Sensor; + +import junit.framework.TestCase; + +public class ZephyrMessageParserTest extends TestCase { + + ZephyrMessageParser parser = new ZephyrMessageParser(); + + public void testIsValid() { + byte[] smallBuf = new byte[59]; + assertFalse(parser.isValid(smallBuf)); + // A complete and valid Zephyr HxM packet + byte[] buf = { 2,38,55,26,0,49,101,80,0,49,98,100,42,113,120,-53,-24,-60,-123,-61,117,-69,42,-75,74,-78,51,-79,27,-83,28,-88,28,-93,29,-98,25,-103,26,-108,26,-113,59,-118,0,0,0,0,0,0,-22,3,125,1,48,0,96,4,30,0 }; + // Make buffer invalid + buf[0] = buf[58] = buf[59] = 0; + assertFalse(parser.isValid(buf)); + buf[0] = 0x02; + assertFalse(parser.isValid(buf)); + buf[58] = 0x1E; + assertFalse(parser.isValid(buf)); + buf[59] = 0x03; + assertTrue(parser.isValid(buf)); + } + + public void testParseBuffer() { + byte[] buf = new byte[60]; + // Heart Rate (-1 =^ 255 unsigned byte) + buf[12] = -1; + // Battery Level + buf[11] = 51; + // Cadence (=^ 255*16 strides/min) + buf[56] = -1; + buf[57] = 15; + Sensor.SensorDataSet sds = parser.parseBuffer(buf); + assertTrue(sds.hasHeartRate()); + assertTrue(sds.getHeartRate().getState() == Sensor.SensorState.SENDING); + assertEquals(255, sds.getHeartRate().getValue()); + assertTrue(sds.hasBatteryLevel()); + assertTrue(sds.getBatteryLevel().getState() == Sensor.SensorState.SENDING); + assertEquals(51, sds.getBatteryLevel().getValue()); + assertTrue(sds.hasCadence()); + assertTrue(sds.getCadence().getState() == Sensor.SensorState.SENDING); + assertEquals(255, sds.getCadence().getValue()); + } + + public void testFindNextAlignment() { + byte[] buf = new byte[60]; + assertEquals(-1, parser.findNextAlignment(buf)); + buf[10] = 0x03; + buf[11] = 0x02; + assertEquals(10, parser.findNextAlignment(buf)); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/tasks/AnnouncementPeriodicTaskFactoryTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/tasks/AnnouncementPeriodicTaskFactoryTest.java new file mode 100644 index 000000000..34db282fa --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/tasks/AnnouncementPeriodicTaskFactoryTest.java @@ -0,0 +1,33 @@ +/* + * 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. + */ + +package com.google.android.apps.mytracks.services.tasks; + +import android.test.AndroidTestCase; + +/** + * Tests for {@link AnnouncementPeriodicTaskFactory}. + * These tests require Donut+ to run. + * + * @author Rodrigo Damazio + */ +public class AnnouncementPeriodicTaskFactoryTest extends AndroidTestCase { + public void testCreate() { + PeriodicTaskFactory factory = new AnnouncementPeriodicTaskFactory(); + PeriodicTask task = factory.create(getContext()); + assertTrue(task instanceof AnnouncementPeriodicTask); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/tasks/AnnouncementPeriodicTaskTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/tasks/AnnouncementPeriodicTaskTest.java new file mode 100644 index 000000000..82b4fd40c --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/services/tasks/AnnouncementPeriodicTaskTest.java @@ -0,0 +1,533 @@ +/* + * 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. + */ +package com.google.android.apps.mytracks.services.tasks; + +import static com.google.android.testing.mocking.AndroidMock.capture; +import static com.google.android.testing.mocking.AndroidMock.eq; +import static com.google.android.testing.mocking.AndroidMock.expect; +import static com.google.android.testing.mocking.AndroidMock.same; + +import com.google.android.apps.mytracks.stats.TripStatistics; +import com.google.android.apps.mytracks.util.StringUtils; +import com.google.android.testing.mocking.AndroidMock; +import com.google.android.testing.mocking.UsesMocks; + +import android.content.Context; +import android.speech.tts.TextToSpeech; +import android.speech.tts.TextToSpeech.OnInitListener; +import android.speech.tts.TextToSpeech.OnUtteranceCompletedListener; +import android.telephony.PhoneStateListener; +import android.telephony.TelephonyManager; +import android.test.AndroidTestCase; + +import java.util.HashMap; +import java.util.Locale; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.easymock.Capture; +import org.easymock.EasyMock; + +/** + * Tests for {@link AnnouncementPeriodicTask}. + * WARNING: I'm not responsible if your eyes start bleeding while reading this + * code. You have been warned. It's still better than no test, though. + * + * @author Rodrigo Damazio + */ +public class AnnouncementPeriodicTaskTest extends AndroidTestCase { + + // Use something other than our hardcoded value + private static final Locale DEFAULT_LOCALE = Locale.KOREAN; + private static final String ANNOUNCEMENT = "I can haz cheeseburger?"; + private Locale oldDefaultLocale; + + private AnnouncementPeriodicTask task; + private AnnouncementPeriodicTask mockTask; + private Capture initListenerCapture; + private Capture phoneListenerCapture; + private TextToSpeechDelegate ttsDelegate; + private TextToSpeechInterface tts; + + /** + * Mockable interface that we delegate TTS calls to. + */ + interface TextToSpeechInterface { + int addEarcon(String earcon, String packagename, int resourceId); + int addEarcon(String earcon, String filename); + int addSpeech(String text, String packagename, int resourceId); + int addSpeech(String text, String filename); + boolean areDefaultsEnforced(); + String getDefaultEngine(); + Locale getLanguage(); + int isLanguageAvailable(Locale loc); + boolean isSpeaking(); + int playEarcon(String earcon, int queueMode, + HashMap params); + int playSilence(long durationInMs, int queueMode, + HashMap params); + int setEngineByPackageName(String enginePackageName); + int setLanguage(Locale loc); + int setOnUtteranceCompletedListener(OnUtteranceCompletedListener listener); + int setPitch(float pitch); + int setSpeechRate(float speechRate); + void shutdown(); + int speak(String text, int queueMode, HashMap params); + int stop(); + int synthesizeToFile(String text, HashMap params, + String filename); + } + + /** + * Subclass of {@link TextToSpeech} which delegates calls to the interface + * above. + * The logic here is stupid and the author is ashamed of having to write it + * like this, but basically the issue is that TextToSpeech cannot be mocked + * without running its constructor, its constructor runs async operations + * which call other methods (and then if the methods are part of a mock we'd + * have to set a behavior, but we can't 'cause the object hasn't been fully + * built yet). + * The logic is that calls made during the constructor (when tts is not yet + * set) will go up to the original class, but after tts is set we'll forward + * them all to the mock. + */ + private class TextToSpeechDelegate + extends TextToSpeech implements TextToSpeechInterface { + public TextToSpeechDelegate(Context context, OnInitListener listener) { + super(context, listener); + } + + @Override + public int addEarcon(String earcon, String packagename, int resourceId) { + if (tts == null) { + return super.addEarcon(earcon, packagename, resourceId); + } + return tts.addEarcon(earcon, packagename, resourceId); + } + + @Override + public int addEarcon(String earcon, String filename) { + if (tts == null) { + return super.addEarcon(earcon, filename); + } + return tts.addEarcon(earcon, filename); + } + + @Override + public int addSpeech(String text, String packagename, int resourceId) { + if (tts == null) { + return super.addSpeech(text, packagename, resourceId); + } + return tts.addSpeech(text, packagename, resourceId); + } + + @Override + public int addSpeech(String text, String filename) { + if (tts == null) { + return super.addSpeech(text, filename); + } + return tts.addSpeech(text, filename); + } + + @Override + public Locale getLanguage() { + if (tts == null) { + return super.getLanguage(); + } + return tts.getLanguage(); + } + + @Override + public int isLanguageAvailable(Locale loc) { + if (tts == null) { + return super.isLanguageAvailable(loc); + } + return tts.isLanguageAvailable(loc); + } + + @Override + public boolean isSpeaking() { + if (tts == null) { + return super.isSpeaking(); + } + return tts.isSpeaking(); + } + + @Override + public int playEarcon(String earcon, int queueMode, + HashMap params) { + if (tts == null) { + return super.playEarcon(earcon, queueMode, params); + } + return tts.playEarcon(earcon, queueMode, params); + } + + @Override + public int playSilence(long durationInMs, int queueMode, + HashMap params) { + if (tts == null) { + return super.playSilence(durationInMs, queueMode, params); + } + return tts.playSilence(durationInMs, queueMode, params); + } + + @Override + public int setLanguage(Locale loc) { + if (tts == null) { + return super.setLanguage(loc); + } + return tts.setLanguage(loc); + } + + @Override + public int setOnUtteranceCompletedListener( + OnUtteranceCompletedListener listener) { + if (tts == null) { + return super.setOnUtteranceCompletedListener(listener); + } + return tts.setOnUtteranceCompletedListener(listener); + } + + @Override + public int setPitch(float pitch) { + if (tts == null) { + return super.setPitch(pitch); + } + return tts.setPitch(pitch); + } + + @Override + public int setSpeechRate(float speechRate) { + if (tts == null) { + return super.setSpeechRate(speechRate); + } + return tts.setSpeechRate(speechRate); + } + + @Override + public void shutdown() { + if (tts == null) { + super.shutdown(); + return; + } + tts.shutdown(); + } + + @Override + public int speak( + String text, int queueMode, HashMap params) { + if (tts == null) { + return super.speak(text, queueMode, params); + } + return tts.speak(text, queueMode, params); + } + + @Override + public int stop() { + if (tts == null) { + return super.stop(); + } + return tts.stop(); + } + + @Override + public int synthesizeToFile(String text, HashMap params, + String filename) { + if (tts == null) { + return super.synthesizeToFile(text, params, filename); + } + return tts.synthesizeToFile(text, params, filename); + } + } + + @UsesMocks({ + AnnouncementPeriodicTask.class, + StringUtils.class, + }) + @Override + protected void setUp() throws Exception { + super.setUp(); + + oldDefaultLocale = Locale.getDefault(); + Locale.setDefault(DEFAULT_LOCALE); + + // Eww, the effort required just to mock TextToSpeech is insane + final AtomicBoolean listenerCalled = new AtomicBoolean(); + OnInitListener blockingListener = new OnInitListener() { + @Override + public void onInit(int status) { + synchronized (this) { + listenerCalled.set(true); + notify(); + } + } + }; + + ttsDelegate = new TextToSpeechDelegate(getContext(), blockingListener); + + // Wait for all async operations done in the constructor to finish. + synchronized (blockingListener) { + while (!listenerCalled.get()) { + // Releases the synchronized lock until we're woken up. + blockingListener.wait(); + } + } + + // Phew, done, now we can start forwarding calls + tts = AndroidMock.createMock(TextToSpeechInterface.class); + + initListenerCapture = new Capture(); + phoneListenerCapture = new Capture(); + + // Create a partial forwarding mock + mockTask = AndroidMock.createMock(AnnouncementPeriodicTask.class, getContext()); + task = new AnnouncementPeriodicTask(getContext()) { + @Override + protected TextToSpeech newTextToSpeech(Context ctx, + OnInitListener onInitListener) { + return mockTask.newTextToSpeech(ctx, onInitListener); + } + + @Override + protected String getAnnouncement(TripStatistics stats) { + return mockTask.getAnnouncement(stats); + } + + @Override + protected void listenToPhoneState( + PhoneStateListener listener, int events) { + mockTask.listenToPhoneState(listener, events); + } + }; + } + + @Override + protected void tearDown() { + Locale.setDefault(oldDefaultLocale); + } + + public void testStart() { + doStart(); + OnInitListener ttsInitListener = initListenerCapture.getValue(); + assertNotNull(ttsInitListener); + + AndroidMock.replay(tts); + + ttsInitListener.onInit(TextToSpeech.SUCCESS); + + AndroidMock.verify(mockTask, tts); + } + + public void testStart_notReady() { + doStart(); + OnInitListener ttsInitListener = initListenerCapture.getValue(); + assertNotNull(ttsInitListener); + + AndroidMock.replay(tts); + + ttsInitListener.onInit(TextToSpeech.ERROR); + + AndroidMock.verify(mockTask, tts); + } + + public void testShutdown() { + // First, start + doStart(); + AndroidMock.verify(mockTask); + AndroidMock.reset(mockTask); + + // Then, shut down + PhoneStateListener phoneListener = phoneListenerCapture.getValue(); + mockTask.listenToPhoneState( + same(phoneListener), eq(PhoneStateListener.LISTEN_NONE)); + tts.shutdown(); + AndroidMock.replay(mockTask, tts); + task.shutdown(); + AndroidMock.verify(mockTask, tts); + } + + public void testRun() throws Exception { + // Expect service data calls + TripStatistics stats = new TripStatistics(); + + // Expect announcement building call + expect(mockTask.getAnnouncement(same(stats))).andStubReturn(ANNOUNCEMENT); + + // Put task in "ready" state + startTask(TextToSpeech.SUCCESS); + + expect(tts.isLanguageAvailable(DEFAULT_LOCALE)).andStubReturn(TextToSpeech.LANG_AVAILABLE); + expect(tts.setLanguage(DEFAULT_LOCALE)).andReturn(TextToSpeech.LANG_AVAILABLE); + expect(tts.setSpeechRate(AnnouncementPeriodicTask.TTS_SPEECH_RATE)).andReturn( + TextToSpeech.SUCCESS); + expect(tts.setOnUtteranceCompletedListener((OnUtteranceCompletedListener) EasyMock.anyObject())) + .andReturn(0); + + // Expect actual announcement call + expect( + tts.speak(eq(ANNOUNCEMENT), eq(TextToSpeech.QUEUE_FLUSH), + eq(AnnouncementPeriodicTask.SPEECH_PARAMS))).andReturn(0); + + // Run the announcement + AndroidMock.replay(tts); + task.announce(stats); + AndroidMock.verify(mockTask, tts); + } + + public void testRun_notReady() throws Exception { + // Put task in "not ready" state + startTask(TextToSpeech.ERROR); + + // Run the announcement + AndroidMock.replay(tts); + task.run(null); + AndroidMock.verify(mockTask, tts); + } + + public void testRun_duringCall() throws Exception { + startTask(TextToSpeech.SUCCESS); + + expect(tts.isSpeaking()).andStubReturn(false); + + // Run the announcement + AndroidMock.replay(tts); + PhoneStateListener phoneListener = phoneListenerCapture.getValue(); + phoneListener.onCallStateChanged(TelephonyManager.CALL_STATE_OFFHOOK, null); + task.run(null); + AndroidMock.verify(mockTask, tts); + } + + public void testRun_ringWhileSpeaking() throws Exception { + startTask(TextToSpeech.SUCCESS); + + expect(tts.isSpeaking()).andStubReturn(true); + expect(tts.stop()).andReturn(TextToSpeech.SUCCESS); + + AndroidMock.replay(tts); + + // Update the state to ringing - this should stop the current announcement. + PhoneStateListener phoneListener = phoneListenerCapture.getValue(); + phoneListener.onCallStateChanged(TelephonyManager.CALL_STATE_RINGING, null); + + // Run the announcement - this should do nothing. + task.run(null); + + AndroidMock.verify(mockTask, tts); + } + + public void testRun_whileRinging() throws Exception { + startTask(TextToSpeech.SUCCESS); + + expect(tts.isSpeaking()).andStubReturn(false); + + // Run the announcement + AndroidMock.replay(tts); + PhoneStateListener phoneListener = phoneListenerCapture.getValue(); + phoneListener.onCallStateChanged(TelephonyManager.CALL_STATE_RINGING, null); + task.run(null); + AndroidMock.verify(mockTask, tts); + } + + public void testRun_noService() throws Exception { + startTask(TextToSpeech.SUCCESS); + + // Run the announcement + AndroidMock.replay(tts); + task.run(null); + AndroidMock.verify(mockTask, tts); + } + + public void testRun_noStats() throws Exception { + // Expect service data calls + + startTask(TextToSpeech.SUCCESS); + + // Run the announcement + AndroidMock.replay(tts); + task.run(null); + AndroidMock.verify(mockTask, tts); + } + + /** + * Tests {@link AnnouncementPeriodicTask#getAnnounceTime(long)} with time zero. + */ + public void testGetAnnounceTime_time_zero() { + long time = 0; // 0 seconds + assertEquals("0 minutes 0 seconds", task.getAnnounceTime(time)); + } + + /** + * Tests {@link AnnouncementPeriodicTask#getAnnounceTime(long)} with time one. + */ + public void testGetAnnounceTime_time_one() { + long time = 1 * 1000; // 1 second + assertEquals("0 minutes 1 second", task.getAnnounceTime(time)); + } + + /** + * Tests {@link AnnouncementPeriodicTask#getAnnounceTime(long)} with singular + * numbers with the hour unit. + */ + public void testGetAnnounceTime_singular_has_hour() { + long time = (1 * 60 * 60 * 1000) + (1 * 60 * 1000) + (1 * 1000); // 1 hour 1 minute 1 second + assertEquals("1 hour 1 minute 1 second", task.getAnnounceTime(time)); + } + + /** + * Tests {@link AnnouncementPeriodicTask#getAnnounceTime(long)} with plural numbers + * with the hour unit. + */ + public void testGetAnnounceTime_plural_has_hour() { + long time = (2 * 60 * 60 * 1000) + (2 * 60 * 1000) + (2 * 1000); // 2 hours 2 minutes 2 seconds + assertEquals("2 hours 2 minutes 2 seconds", task.getAnnounceTime(time)); + } + + /** + * Tests {@link AnnouncementPeriodicTask#getAnnounceTime(long)} with singular + * numbers without the hour unit. + */ + public void testGetAnnounceTime_singular_no_hour() { + long time = (1 * 60 * 1000) + (1 * 1000); // 1 minute 1 second + assertEquals("1 minute 1 second", task.getAnnounceTime(time)); + } + + /** + * Tests {@link AnnouncementPeriodicTask#getAnnounceTime(long)} with plural numbers + * without the hour unit. + */ + public void testGetAnnounceTime_plural_no_hour() { + long time = (2 * 60 * 1000) + (2 * 1000); // 2 minutes 2 seconds + assertEquals("2 minutes 2 seconds", task.getAnnounceTime(time)); + } + + private void startTask(int state) { + AndroidMock.resetToNice(tts); + AndroidMock.replay(tts); + doStart(); + OnInitListener ttsInitListener = initListenerCapture.getValue(); + ttsInitListener.onInit(state); + AndroidMock.resetToDefault(tts); + } + + private void doStart() { + mockTask.listenToPhoneState(capture(phoneListenerCapture), + eq(PhoneStateListener.LISTEN_CALL_STATE)); + expect(mockTask.newTextToSpeech( + same(getContext()), capture(initListenerCapture))) + .andStubReturn(ttsDelegate); + AndroidMock.replay(mockTask); + task.start(); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/stats/DoubleBufferTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/stats/DoubleBufferTest.java new file mode 100644 index 000000000..0af9196e5 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/stats/DoubleBufferTest.java @@ -0,0 +1,117 @@ +/* + * Copyright 2009 Google Inc. All Rights Reserved. + */ + +package com.google.android.apps.mytracks.stats; + +import junit.framework.TestCase; + +/** + * Test for the DoubleBuffer class. + * + * @author Sandor Dornbush + */ +public class DoubleBufferTest extends TestCase { + + /** + * Tests that the constructor leaves the buffer in a valid state. + */ + public void testConstructor() { + DoubleBuffer buffer = new DoubleBuffer(10); + assertFalse(buffer.isFull()); + assertEquals(0.0, buffer.getAverage()); + double[] averageAndVariance = buffer.getAverageAndVariance(); + assertEquals(0.0, averageAndVariance[0]); + assertEquals(0.0, averageAndVariance[1]); + } + + /** + * Simple test with 10 of the same values. + */ + public void testBasic() { + DoubleBuffer buffer = new DoubleBuffer(10); + + for (int i = 0; i < 9; i++) { + buffer.setNext(1.0); + assertFalse(buffer.isFull()); + assertEquals(1.0, buffer.getAverage()); + double[] averageAndVariance = buffer.getAverageAndVariance(); + assertEquals(1.0, averageAndVariance[0]); + assertEquals(0.0, averageAndVariance[1]); + } + buffer.setNext(1); + assertTrue(buffer.isFull()); + assertEquals(1.0, buffer.getAverage()); + double[] averageAndVariance = buffer.getAverageAndVariance(); + assertEquals(1.0, averageAndVariance[0]); + assertEquals(0.0, averageAndVariance[1]); + } + + /** + * Tests with 5 entries of -10 and 5 entries of 10. + */ + public void testSplit() { + DoubleBuffer buffer = new DoubleBuffer(10); + + for (int i = 0; i < 5; i++) { + buffer.setNext(-10); + assertFalse(buffer.isFull()); + assertEquals(-10.0, buffer.getAverage()); + double[] averageAndVariance = buffer.getAverageAndVariance(); + assertEquals(-10.0, averageAndVariance[0]); + assertEquals(0.0, averageAndVariance[1]); + } + + for (int i = 1; i < 5; i++) { + buffer.setNext(10); + assertFalse(buffer.isFull()); + double expectedAverage = ((i * 10.0) - 50.0) / (i + 5); + assertEquals(buffer.toString(), + expectedAverage, buffer.getAverage(), 0.01); + double[] averageAndVariance = buffer.getAverageAndVariance(); + assertEquals(expectedAverage, averageAndVariance[0]); + } + buffer.setNext(10); + assertTrue(buffer.isFull()); + assertEquals(0.0, buffer.getAverage()); + double[] averageAndVariance = buffer.getAverageAndVariance(); + assertEquals(0.0, averageAndVariance[0]); + assertEquals(100.0, averageAndVariance[1]); + } + + /** + * Tests that reset leaves the buffer in a valid state. + */ + public void testReset() { + DoubleBuffer buffer = new DoubleBuffer(10); + + for (int i = 0; i < 100; i++) { + buffer.setNext(i); + } + assertTrue(buffer.isFull()); + + buffer.reset(); + assertFalse(buffer.isFull()); + assertEquals(0.0, buffer.getAverage()); + double[] averageAndVariance = buffer.getAverageAndVariance(); + assertEquals(0.0, averageAndVariance[0]); + assertEquals(0.0, averageAndVariance[1]); + } + + + /** + * Tests that if a lot of items are inserted the smoothing and looping works. + */ + public void testLoop() { + DoubleBuffer buffer = new DoubleBuffer(10); + + for (int i = 0; i < 1000; i++) { + buffer.setNext(i); + assertEquals(i >= 9, buffer.isFull()); + if (i > 10) { + assertEquals(i - 4.5, buffer.getAverage()); + } + } + } + +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/stats/ExtremityMonitorTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/stats/ExtremityMonitorTest.java new file mode 100644 index 000000000..d5cba3126 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/stats/ExtremityMonitorTest.java @@ -0,0 +1,63 @@ +/** + * Copyright 2009 Google Inc. All Rights Reserved. + */ +package com.google.android.apps.mytracks.stats; + +import junit.framework.TestCase; +import java.util.Random; + +/** + * This class test the ExtremityMonitor class. + * + * @author Sandor Dornbush + */ +public class ExtremityMonitorTest extends TestCase { + + public ExtremityMonitorTest(String name) { + super(name); + } + + public void testInitialize() { + ExtremityMonitor monitor = new ExtremityMonitor(); + assertEquals(Double.POSITIVE_INFINITY, monitor.getMin()); + assertEquals(Double.NEGATIVE_INFINITY, monitor.getMax()); + } + + public void testSimple() { + ExtremityMonitor monitor = new ExtremityMonitor(); + assertTrue(monitor.update(0)); + assertTrue(monitor.update(1)); + assertEquals(0.0, monitor.getMin()); + assertEquals(1.0, monitor.getMax()); + assertFalse(monitor.update(1)); + assertFalse(monitor.update(0.5)); + } + + /** + * Throws a bunch of random numbers between [0,1] at the monitor. + */ + public void testRandom() { + ExtremityMonitor monitor = new ExtremityMonitor(); + Random random = new Random(42); + for (int i = 0; i < 1000; i++) { + monitor.update(random.nextDouble()); + } + assertTrue(monitor.getMin() < 0.1); + assertTrue(monitor.getMax() < 1.0); + assertTrue(monitor.getMin() >= 0.0); + assertTrue(monitor.getMax() > 0.9); + } + + public void testReset() { + ExtremityMonitor monitor = new ExtremityMonitor(); + assertTrue(monitor.update(0)); + assertTrue(monitor.update(1)); + monitor.reset(); + assertEquals(Double.POSITIVE_INFINITY, monitor.getMin()); + assertEquals(Double.NEGATIVE_INFINITY, monitor.getMax()); + assertTrue(monitor.update(0)); + assertTrue(monitor.update(1)); + assertEquals(0.0, monitor.getMin()); + assertEquals(1.0, monitor.getMax()); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/stats/TripStatisticsTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/stats/TripStatisticsTest.java new file mode 100644 index 000000000..3a34bf5ab --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/stats/TripStatisticsTest.java @@ -0,0 +1,107 @@ +/* + * 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. + */ +package com.google.android.apps.mytracks.stats; + +import junit.framework.TestCase; + +/** + * Tests for {@link TripStatistics}. + * This only tests non-trivial pieces of that class. + * + * @author Rodrigo Damazio + */ +public class TripStatisticsTest extends TestCase { + + private TripStatistics statistics; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + statistics = new TripStatistics(); + } + + public void testSetBounds() { + // This is not a trivial setter, conversion happens in it + statistics.setBounds(12345, -34567, 56789, -98765); + assertEquals(12345, statistics.getLeft()); + assertEquals(-34567, statistics.getTop()); + assertEquals(56789, statistics.getRight()); + assertEquals(-98765, statistics.getBottom()); + } + + public void testMerge() { + TripStatistics statistics2 = new TripStatistics(); + statistics.setStartTime(1000L); // Resulting start time + statistics.setStopTime(2500L); + statistics2.setStartTime(3000L); + statistics2.setStopTime(4000L); // Resulting stop time + statistics.setTotalTime(1500L); + statistics2.setTotalTime(1000L); // Result: 1500+1000 + statistics.setMovingTime(700L); + statistics2.setMovingTime(600L); // Result: 700+600 + statistics.setTotalDistance(750.0); + statistics2.setTotalDistance(350.0); // Result: 750+350 + statistics.setTotalElevationGain(50.0); + statistics2.setTotalElevationGain(850.0); // Result: 850+50 + statistics.setMaxSpeed(60.0); // Resulting max speed + statistics2.setMaxSpeed(30.0); + statistics.setMaxElevation(1250.0); + statistics.setMinElevation(1200.0); // Resulting min elevation + statistics2.setMaxElevation(3575.0); // Resulting max elevation + statistics2.setMinElevation(2800.0); + statistics.setMaxGrade(15.0); + statistics.setMinGrade(-25.0); // Resulting min grade + statistics2.setMaxGrade(35.0); // Resulting max grade + statistics2.setMinGrade(0.0); + statistics2.setCalorie(50.0); + + // Resulting bounds: -10000, 35000, 30000, -40000 + statistics.setBounds(-10000, 20000, 30000, -40000); + statistics2.setBounds(-5000, 35000, 0, 20000); + + statistics.merge(statistics2); + + assertEquals(1000L, statistics.getStartTime()); + assertEquals(4000L, statistics.getStopTime()); + assertEquals(2500L, statistics.getTotalTime()); + assertEquals(1300L, statistics.getMovingTime()); + assertEquals(1100.0, statistics.getTotalDistance()); + assertEquals(900.0, statistics.getTotalElevationGain()); + assertEquals(statistics.getTotalDistance()/ (statistics.getMovingTime() / 1000.0), statistics.getMaxSpeed()); + assertEquals(-10000, statistics.getLeft()); + assertEquals(30000, statistics.getRight()); + assertEquals(35000, statistics.getTop()); + assertEquals(-40000, statistics.getBottom()); + assertEquals(1200.0, statistics.getMinElevation()); + assertEquals(3575.0, statistics.getMaxElevation()); + assertEquals(-25.0, statistics.getMinGrade()); + assertEquals(35.0, statistics.getMaxGrade()); + assertEquals(50.0, statistics.getCalorie()); + } + + public void testGetAverageSpeed() { + statistics.setTotalDistance(1000.0); + statistics.setTotalTime(50000); // in milliseconds + assertEquals(20.0, statistics.getAverageSpeed()); + } + + public void testGetAverageMovingSpeed() { + statistics.setTotalDistance(1000.0); + statistics.setMovingTime(20000); // in milliseconds + assertEquals(50.0, statistics.getAverageMovingSpeed()); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/stats/TripStatisticsUpdaterTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/stats/TripStatisticsUpdaterTest.java new file mode 100644 index 000000000..8d43dfd75 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/stats/TripStatisticsUpdaterTest.java @@ -0,0 +1,331 @@ +// Copyright 2009 Google Inc. All Rights Reserved. + +package com.google.android.apps.mytracks.stats; + +import com.google.android.apps.mytracks.util.CalorieUtils.ActivityType; +import com.google.android.apps.mytracks.util.PreferencesUtils; + +import android.location.Location; + +import junit.framework.TestCase; + +/** + * Tests {@link TripStatisticsUpdater}. + * + * @author Sandor Dornbush + */ +public class TripStatisticsUpdaterTest extends TestCase { + + private static final long ONE_SECOND = 1000; + private static final long TEN_SECONDS = 10 * ONE_SECOND; + private static final float MOVING_SPEED = 11.1f; + private static final double DEFAULT_WEIGHT = 65.0; + + private TripStatisticsUpdater tripStatisticsUpdater = null; + + @Override + protected void setUp() throws Exception { + tripStatisticsUpdater = new TripStatisticsUpdater(System.currentTimeMillis()); + } + + /** + * Sends some moving and waiting locations and then checks the statistics. + */ + public void testAddLocationSimple() { + long startTime = 1000; + tripStatisticsUpdater = new TripStatisticsUpdater(startTime); + TripStatistics tripStatistics = tripStatisticsUpdater.getTripStatistics(); + + assertEquals(0.0, tripStatisticsUpdater.getSmoothedElevation()); + assertEquals(Double.POSITIVE_INFINITY, tripStatistics.getMinElevation()); + assertEquals(Double.NEGATIVE_INFINITY, tripStatistics.getMaxElevation()); + assertEquals(0.0, tripStatistics.getMaxSpeed()); + assertEquals(Double.POSITIVE_INFINITY, tripStatistics.getMinGrade()); + assertEquals(Double.NEGATIVE_INFINITY, tripStatistics.getMaxGrade()); + assertEquals(0.0, tripStatistics.getTotalElevationGain()); + assertEquals(0, tripStatistics.getMovingTime()); + assertEquals(0.0, tripStatistics.getTotalDistance()); + + // Time:0 ~ 99; Location:0 ~ 99 + addMoveLocations(100, startTime, tripStatistics, 0, 0); + // Time:100 ~ 199; Location:99 + addWaitLocations(100, startTime, tripStatistics, 100, 99); + // Time:200 ~ 299; Location:100 ~ 199 + addMoveLocations(100, startTime, tripStatistics, 200, 100); + // Time:300 ~ 399; Location:199 + addWaitLocations(100, startTime, tripStatistics, 300, 199); + // Time:400 ~ 499; Location:200 ~ 299 + addMoveLocations(100, startTime, tripStatistics, 400, 200); + // Time:500 ~ 599; Location:299 + addWaitLocations(100, startTime, tripStatistics, 500, 299); + // Time:600 ~ 699; Location:300 ~ 399 + addMoveLocations(100, startTime, tripStatistics, 600, 300); + } + + /** + * Sends some disordered locations and checks the statistics. In some + * situation, especially when signal is not good, MyTracks may receive such + * data. + */ + public void testAddLocation_disorderedLocatiions() { + long startTime = 1000; + tripStatisticsUpdater = new TripStatisticsUpdater(startTime); + TripStatistics tripStatistics = tripStatisticsUpdater.getTripStatistics(); + + addLocations(5, startTime, tripStatistics, 0, 0); + addLocations(5, startTime, tripStatistics, 5, 0); + addLocations(5, startTime, tripStatistics, 10, -5); + addLocations(5, startTime, tripStatistics, 15, 5); + } + + /** + * Tests {@link TripStatisticsUpdater#updateElevation(double)} with constant + * elevations. + */ + public void testElevationSimple() throws Exception { + for (double elevation = 0; elevation < 1000; elevation += 10) { + tripStatisticsUpdater = new TripStatisticsUpdater(System.currentTimeMillis()); + for (int i = 0; i < 100; i++) { + tripStatisticsUpdater.updateElevation(elevation); + assertEquals(elevation, tripStatisticsUpdater.getSmoothedElevation()); + + TripStatistics tripStatistics = tripStatisticsUpdater.getTripStatistics(); + assertEquals(elevation, tripStatistics.getMinElevation()); + assertEquals(elevation, tripStatistics.getMaxElevation()); + assertEquals(elevation, tripStatistics.getTotalElevationGain()); + } + } + } + + /** + * Tests {@link TripStatisticsUpdater#updateGrade(double, double)} with + * elevation gain. + */ + public void testElevationGain() throws Exception { + for (double i = 0; i < 1000; i++) { + tripStatisticsUpdater.updateElevation(i); + assertEquals(i, tripStatisticsUpdater.getSmoothedElevation(), + TripStatisticsUpdater.ELEVATION_SMOOTHING_FACTOR / 2); + + TripStatistics data = tripStatisticsUpdater.getTripStatistics(); + assertEquals(0.0, data.getMinElevation()); + assertEquals(i, data.getMaxElevation(), TripStatisticsUpdater.ELEVATION_SMOOTHING_FACTOR / 2); + assertEquals( + i, data.getTotalElevationGain(), TripStatisticsUpdater.ELEVATION_SMOOTHING_FACTOR); + } + } + + /** + * Tests {@link TripStatisticsUpdater#updateGrade(double, double)} with grade + * of 1 and -1. + */ + public void testGradeSimple() throws Exception { + for (double i = 0; i < 1000; i++) { + tripStatisticsUpdater.updateGrade(100.0, 100.0); + assertEquals(1.0, tripStatisticsUpdater.getTripStatistics().getMaxGrade()); + assertEquals(1.0, tripStatisticsUpdater.getTripStatistics().getMinGrade()); + } + for (double i = 0; i < 1000; i++) { + tripStatisticsUpdater.updateGrade(100.0, -100.0); + if (i >= TripStatisticsUpdater.GRADE_SMOOTHING_FACTOR) { + assertEquals(1.0, tripStatisticsUpdater.getTripStatistics().getMaxGrade()); + // add 0.1 delta since changing min grade from 1 to -1 + assertEquals(-1.0, tripStatisticsUpdater.getTripStatistics().getMinGrade(), 0.1); + } + } + } + + /** + * Tests {@link TripStatisticsUpdater#updateGrade(double, double)} with + * distance of 1. The grade should get ignored. + */ + public void testGradeIgnoreShort() throws Exception { + for (double i = 0; i < 100; i++) { + /* + * The value of the elevation does not matter. This is just to fill the + * elevation buffer. + */ + tripStatisticsUpdater.updateElevation(i); + tripStatisticsUpdater.updateGrade(1.0, 100.0); + assertEquals( + Double.NEGATIVE_INFINITY, tripStatisticsUpdater.getTripStatistics().getMaxGrade()); + assertEquals( + Double.POSITIVE_INFINITY, tripStatisticsUpdater.getTripStatistics().getMinGrade()); + } + } + + /** + * Tests {@link TripStatisticsUpdater#updateSpeed(long, double, long, double)} + * with speed of zero. + */ + public void testUpdateSpeedIncludeZero() { + for (int i = 0; i < 1000; i++) { + tripStatisticsUpdater.updateSpeed(i + ONE_SECOND, 0.0, i, 4.0); + assertEquals(0.0, tripStatisticsUpdater.getTripStatistics().getMaxSpeed()); + } + } + + /** + * Tests {@link TripStatisticsUpdater#updateSpeed(long, double, long, double)} + * with the error code 128. The speed should get ignored. + */ + public void testUpdateSpeedIngoreErrorCode() { + long time = 12344000; + tripStatisticsUpdater.updateSpeed(time + ONE_SECOND, 128.0, time, 0.0); + assertEquals(0.0, tripStatisticsUpdater.getTripStatistics().getMaxSpeed()); + } + + /** + * Tests {@link TripStatisticsUpdater#updateSpeed(long, double, long, double)} + * with a large speed change. The speed should get ignored. + */ + public void testUpdateSpeedIngoreLargeAcceleration() { + long time = 12344000; + tripStatisticsUpdater.updateSpeed(time + ONE_SECOND, 100.0, time, 1.0); + assertEquals(0.0, tripStatisticsUpdater.getTripStatistics().getMaxSpeed()); + } + + /** + * Tests {@link TripStatisticsUpdater#updateSpeed(long, double, long, double)} + * with constant speed. + */ + public void testUpdateSpeed() { + double speed = 4.0; + for (int i = 0; i < 1000; i++) { + tripStatisticsUpdater.updateSpeed(i + ONE_SECOND, speed, i, speed); + assertEquals(speed, tripStatisticsUpdater.getTripStatistics().getMaxSpeed()); + } + } + + /** + * Sends some locations which keeping moving and checks the statistics. + * + * @param points number of locations + * @param startTime start time of this track + * @param tripStatistics the TripStatistics object + * @param timeOffset offset to start time + * @param locationOffset location offset to start + */ + private void addMoveLocations(int points, long startTime, TripStatistics tripStatistics, + int timeOffset, int locationOffset) { + for (int i = 0; i < points; i++) { + // Going up by 1 meter each time. + // Moving by .001 degree latitude (111 meters). + // Each time slice is 10 seconds. + Location location = getLocation(i + locationOffset, (i + locationOffset) * .001, MOVING_SPEED, + startTime + (timeOffset + i) * TEN_SECONDS); + tripStatisticsUpdater.addLocation(location, + PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT, true, ActivityType.WALKING, + DEFAULT_WEIGHT); + tripStatistics = tripStatisticsUpdater.getTripStatistics(); + + assertEquals((timeOffset + i) * TEN_SECONDS, tripStatistics.getTotalTime()); + assertEquals((locationOffset + i) * TEN_SECONDS, tripStatistics.getMovingTime()); + assertEquals(i + locationOffset, tripStatisticsUpdater.getSmoothedElevation(), + TripStatisticsUpdater.ELEVATION_SMOOTHING_FACTOR / 2); + if (i + locationOffset >= TripStatisticsUpdater.ELEVATION_SMOOTHING_FACTOR) { + assertEquals(0.0, tripStatistics.getMinElevation()); + assertEquals(i + locationOffset, tripStatistics.getMaxElevation(), + TripStatisticsUpdater.ELEVATION_SMOOTHING_FACTOR / 2); + assertEquals(i + locationOffset, tripStatistics.getTotalElevationGain(), + TripStatisticsUpdater.ELEVATION_SMOOTHING_FACTOR); + } + + if (i + locationOffset >= TripStatisticsUpdater.SPEED_SMOOTHING_FACTOR) { + assertEquals(MOVING_SPEED, tripStatistics.getMaxSpeed(), 0.1); + } + + // If there are only moving locations in the track. + if (locationOffset == 0 && (i + locationOffset) >= TripStatisticsUpdater.RUN_SMOOTHING_FACTOR + + TripStatisticsUpdater.GRADE_SMOOTHING_FACTOR) { + // 0.5 m / 111 m = .0045 + assertEquals(0.0045, tripStatistics.getMinGrade(), 0.0001); + // 1 m / 111 m = .009 + assertEquals(0.009, tripStatistics.getMaxGrade(), 0.0001); + } + assertEquals((i + locationOffset) * 111.0, tripStatistics.getTotalDistance(), + (i + locationOffset) * 111.0 * 0.01); + } + } + + /** + * Sends some locations which are not moving and checks the statistics. + * + * @param points number of locations + * @param startTime start time of this track + * @param tripStatistics the TripStatistics object + * @param timeOffset offset to start time + * @param locationOffset location offset to start + */ + private void addWaitLocations(int points, long startTime, TripStatistics tripStatistics, + int timeOffset, int locationOffset) { + for (int i = 0; i < points; i++) { + Location location = getLocation( + locationOffset, locationOffset * .001, 0, startTime + (i + timeOffset) * TEN_SECONDS); + tripStatisticsUpdater.addLocation(location, + PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT, false, ActivityType.WALKING, + DEFAULT_WEIGHT); + + tripStatistics = tripStatisticsUpdater.getTripStatistics(); + assertEquals((i + timeOffset) * TEN_SECONDS, tripStatistics.getTotalTime()); + assertEquals((locationOffset) * TEN_SECONDS, tripStatistics.getMovingTime()); + assertEquals(locationOffset, tripStatisticsUpdater.getSmoothedElevation(), + TripStatisticsUpdater.ELEVATION_SMOOTHING_FACTOR / 2); + assertEquals(0.0, tripStatistics.getMinElevation()); + assertEquals(locationOffset, tripStatistics.getMaxElevation(), + TripStatisticsUpdater.ELEVATION_SMOOTHING_FACTOR / 2); + assertEquals(locationOffset, tripStatistics.getTotalElevationGain(), + TripStatisticsUpdater.ELEVATION_SMOOTHING_FACTOR); + assertEquals(MOVING_SPEED, tripStatistics.getMaxSpeed(), 0.1); + assertEquals(MOVING_SPEED, tripStatistics.getMaxSpeed(), 0.1); + assertEquals( + locationOffset * 111.0, tripStatistics.getTotalDistance(), locationOffset * 111.0 * 0.01); + } + } + + /** + * Sends some locations which are moving and checks some simple policy. + * + * @param points number of locations + * @param startTime start time of this track + * @param tripStatistics the TripStatistics object + * @param timeOffset offset to start time + * @param locationOffset location offset to start + */ + private void addLocations(int points, long startTime, TripStatistics tripStatistics, + int timeOffset, int locationOffset) { + for (int i = 0; i < points; i++) { + // 99999 means a speed should bigger than given speed. + Location location = getLocation(i + locationOffset, (i + locationOffset) * .001, 99999, + startTime + (timeOffset + i) * TEN_SECONDS); + tripStatisticsUpdater.addLocation(location, + PreferencesUtils.RECORDING_DISTANCE_INTERVAL_DEFAULT, true, ActivityType.WALKING, + DEFAULT_WEIGHT); + tripStatistics = tripStatisticsUpdater.getTripStatistics(); + + assertTrue(tripStatistics.getMovingTime() <= tripStatistics.getTotalTime()); + assertTrue(tripStatistics.getAverageSpeed() <= tripStatistics.getAverageMovingSpeed()); + assertTrue(tripStatistics.getAverageMovingSpeed() <= tripStatistics.getMaxSpeed()); + assertTrue(tripStatistics.getStopTime() >= tripStatistics.getStartTime()); + } + } + + /** + * Creates a location and returns it. + * + * @param altitude altitude of location + * @param latitude latitude of location + * @param speed speed of location + * @param time time of location + */ + private Location getLocation(double altitude, double latitude, float speed, long time) { + Location location = new Location("test"); + location.setAccuracy(1.0f); + location.setLongitude(45.0); + location.setAltitude(altitude); + location.setLatitude(latitude); + location.setSpeed(speed); + location.setTime(time); + return location; + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/testing/TestingProviderUtilsFactory.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/testing/TestingProviderUtilsFactory.java new file mode 100644 index 000000000..64705dce1 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/testing/TestingProviderUtilsFactory.java @@ -0,0 +1,38 @@ +// Copyright 2010 Google Inc. All Rights Reserved. + +package com.google.android.apps.mytracks.testing; + +import com.google.android.apps.mytracks.content.MyTracksProviderUtils; +import com.google.android.apps.mytracks.content.MyTracksProviderUtils.Factory; + +import android.content.Context; + +/** + * A fake factory for {@link MyTracksProviderUtils} which always returns a + * predefined instance. + * + * @author Rodrigo Damazio + */ +public class TestingProviderUtilsFactory extends Factory { + private MyTracksProviderUtils instance; + + public TestingProviderUtilsFactory(MyTracksProviderUtils instance) { + this.instance = instance; + } + + @Override + protected MyTracksProviderUtils newForContext(Context context) { + return instance; + } + + public static Factory installWithInstance(MyTracksProviderUtils instance) { + Factory oldFactory = Factory.getInstance(); + Factory factory = new TestingProviderUtilsFactory(instance); + MyTracksProviderUtils.Factory.overrideInstance(factory); + return oldFactory; + } + + public static void restoreOldFactory(Factory factory) { + MyTracksProviderUtils.Factory.overrideInstance(factory); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/util/ChartURLGeneratorTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/util/ChartURLGeneratorTest.java new file mode 100644 index 000000000..176018b17 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/util/ChartURLGeneratorTest.java @@ -0,0 +1,75 @@ +/* + * 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 + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.android.apps.mytracks.util; + +import com.google.android.apps.mytracks.content.Track; +import com.google.android.apps.mytracks.stats.TripStatistics; + +import java.util.Vector; + +import junit.framework.TestCase; + +/** + * Tests for the Chart URL generator. + * + * @author Sandor Dornbush + */ +public class ChartURLGeneratorTest extends TestCase { + + public void testgetChartUrl() { + Vector distances = new Vector(); + Vector elevations = new Vector(); + Track t = new Track(); + TripStatistics stats = t.getTripStatistics(); + stats.setMinElevation(0); + stats.setMaxElevation(2000); + stats.setTotalDistance(100); + + distances.add(0.0); + elevations.add(10.0); + + distances.add(10.0); + elevations.add(300.0); + + distances.add(20.0); + elevations.add(800.0); + + distances.add(50.0); + elevations.add(1900.0); + + distances.add(75.0); + elevations.add(1200.0); + + distances.add(90.0); + elevations.add(700.0); + + distances.add(100.0); + elevations.add(70.0); + + String chart = ChartURLGenerator.getChartUrl(distances, + elevations, + t, + "Title", + true); + + assertEquals( + "http://chart.apis.google.com/chart?&chs=600x350&cht=lxy&" + + "chtt=Title&chxt=x,y&chxr=0,0,0,0|1,0.0,2100.0,300&chco=009A00&" + + "chm=B,00AA00,0,0,0&chg=100000,14.285714285714286,1,0&" + + "chd=e:AAGZMzf.v.5l..,ATJJYY55kkVVCI", + chart); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/util/ChartsExtendedEncoderTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/util/ChartsExtendedEncoderTest.java new file mode 100644 index 000000000..96ea5c8b1 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/util/ChartsExtendedEncoderTest.java @@ -0,0 +1,47 @@ +/* + * 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. + */ +package com.google.android.apps.mytracks.util; + +import junit.framework.TestCase; + +/** + * A unit test for {@link ChartsExtendedEncoder}. + * + * @author Bartlomiej Niechwiej + */ +public class ChartsExtendedEncoderTest extends TestCase { + + public void testGetEncodedValue_validArguments() { + // Valid arguments. + assertEquals("AK", ChartsExtendedEncoder.getEncodedValue(10)); + assertEquals("JO", ChartsExtendedEncoder.getEncodedValue(590)); + assertEquals("AA", ChartsExtendedEncoder.getEncodedValue(0)); + // 64^2 = 4096. + assertEquals("..", ChartsExtendedEncoder.getEncodedValue(4095)); + } + + public void testGetEncodedValue_invalidArguments() { + // Invalid arguments. + assertEquals("__", ChartsExtendedEncoder.getEncodedValue(4096)); + assertEquals("__", ChartsExtendedEncoder.getEncodedValue(1234564096)); + assertEquals("__", ChartsExtendedEncoder.getEncodedValue(-10)); + assertEquals("__", ChartsExtendedEncoder.getEncodedValue(-12324435)); + } + + public void testGetSeparator() { + assertEquals(",", ChartsExtendedEncoder.getSeparator()); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/util/FileUtilsTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/util/FileUtilsTest.java new file mode 100644 index 000000000..e0bdc3fbe --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/util/FileUtilsTest.java @@ -0,0 +1,121 @@ +/* + * 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. + */ +package com.google.android.apps.mytracks.util; + +import android.os.Environment; + +import java.io.File; + +import junit.framework.TestCase; + +/** + * Tests for {@link FileUtils}. + * + * @author Rodrigo Damazio + */ +public class FileUtilsTest extends TestCase { + + /** + * Tests {@link FileUtils#getPath(String...)}. + */ + public void testBuildExternalDirectoryPath() { + String expectedName = Environment.getExternalStorageDirectory() + File.separator + + FileUtils.SDCARD_TOP_DIR + File.separator + "a" + File.separator + "b" + File.separator + + "c"; + String dirName = FileUtils.getPath("a", "b", "c"); + assertEquals(expectedName, dirName); + } + + /** + * Tests {@link FileUtils#buildUniqueFileName(File, String, String)} when the + * file is new. + */ + public void testBuildUniqueFileName_new() { + String filename = FileUtils.buildUniqueFileName(new File("/dir"), "Filename", "ext"); + assertEquals("Filename.ext", filename); + } + + /** + * Tests {@link FileUtils#buildUniqueFileName(File, String, String)} when the + * file exists already. + */ + public void testBuildUniqueFileName_exist() { + // Expect "/default.prop" to exist on the phone/emulator + String filename = FileUtils.buildUniqueFileName(new File("/"), "default", "prop"); + assertEquals("default(1).prop", filename); + } + + /** + * Tests {@link FileUtils#sanitizeFileName(String)} with special characters. + * Verifies that they are sanitized. + */ + public void testSanitizeFileName() { + String name = "Swim\10ming-^across:/the/ pacific (ocean)."; + String expected = "Swim_ming-^across_the_ pacific (ocean)_"; + assertEquals(expected, FileUtils.sanitizeFileName(name)); + } + + /** + * Tests {@link FileUtils#sanitizeFileName(String)} with i18n characters (in + * Chinese and Russian). Verifies that they are allowed. + */ + public void testSanitizeFileName_i18n() { + String name = "您好-привет"; + String expected = "您好-привет"; + assertEquals(expected, FileUtils.sanitizeFileName(name)); + } + + /** + * Tests {@link FileUtils#sanitizeFileName(String)} with special FAT32 + * characters. Verifies that they are allowed. + */ + public void testSanitizeFileName_special_characters() { + String name = "$%'-_@~`!(){}^#&+,;=[] "; + String expected = "$%'-_@~`!(){}^#&+,;=[] "; + assertEquals(expected, FileUtils.sanitizeFileName(name)); + } + + /** + * Tests {@link FileUtils#sanitizeFileName(String)} with multiple escaped + * characters in a row. Verifies that they are collapsed into one underscore. + */ + public void testSanitizeFileName_collapse() { + String name = "hello//there"; + String expected = "hello_there"; + assertEquals(expected, FileUtils.sanitizeFileName(name)); + } + + /** + * Tests {@link FileUtils#truncateFileName(File, String, String)}. Verifies + * the a long file name is truncated. + */ + public void testTruncateFileName() { + File directory = new File("/dir1/dir2/"); + String suffix = ".gpx"; + char[] name = new char[FileUtils.MAX_FAT32_PATH_LENGTH]; + for (int i = 0; i < name.length; i++) { + name[i] = 'a'; + } + String nameString = new String(name); + String truncated = FileUtils.truncateFileName(directory, nameString, suffix); + + for (int i = 0; i < truncated.length(); i++) { + assertEquals('a', truncated.charAt(i)); + } + assertEquals(FileUtils.MAX_FAT32_PATH_LENGTH, + new File(directory, truncated + suffix).getPath().length()); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/util/StringUtilsTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/util/StringUtilsTest.java new file mode 100644 index 000000000..8e03ef044 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/util/StringUtilsTest.java @@ -0,0 +1,183 @@ +/* + * 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. + */ + +package com.google.android.apps.mytracks.util; + +import android.test.AndroidTestCase; + +import java.util.GregorianCalendar; +import java.util.TimeZone; + +/** + * Tests for {@link StringUtils}. + * + * @author Rodrigo Damazio + */ +public class StringUtilsTest extends AndroidTestCase { + + /** + * Tests {@link StringUtils#formatDateTimeIso8601(long)}. + */ + public void testFormatDateTimeIso8601() { + assertEquals("1970-01-01T00:00:12.345Z", StringUtils.formatDateTimeIso8601(12345)); + } + + /** + * Tests {@link StringUtils#formatElapsedTime(long)}. + */ + public void testformatElapsedTime() { + // 1 second + assertEquals("00:01", StringUtils.formatElapsedTime(1000)); + // 10 seconds + assertEquals("00:10", StringUtils.formatElapsedTime(10000)); + // 1 minute + assertEquals("01:00", StringUtils.formatElapsedTime(60000)); + // 10 minutes + assertEquals("10:00", StringUtils.formatElapsedTime(600000)); + // 1 hour + assertEquals("1:00:00", StringUtils.formatElapsedTime(3600000)); + // 10 hours + assertEquals("10:00:00", StringUtils.formatElapsedTime(36000000)); + // 100 hours + assertEquals("100:00:00", StringUtils.formatElapsedTime(360000000)); + } + + /** + * Tests {@link StringUtils#formatElapsedTimeWithHour(long)}. + */ + public void testformatElapsedTimeWithHour() { + // 1 second + assertEquals("0:00:01", StringUtils.formatElapsedTimeWithHour(1000)); + // 10 seconds + assertEquals("0:00:10", StringUtils.formatElapsedTimeWithHour(10000)); + // 1 minute + assertEquals("0:01:00", StringUtils.formatElapsedTimeWithHour(60000)); + // 10 minutes + assertEquals("0:10:00", StringUtils.formatElapsedTimeWithHour(600000)); + // 1 hour + assertEquals("1:00:00", StringUtils.formatElapsedTimeWithHour(3600000)); + // 10 hours + assertEquals("10:00:00", StringUtils.formatElapsedTimeWithHour(36000000)); + // 100 hours + assertEquals("100:00:00", StringUtils.formatElapsedTimeWithHour(360000000)); + } + + /** + * Tests {@link StringUtils#formatDistance(android.content.Context, double, + * boolean)}. + */ + public void testFormatDistance() { + // A large number in metric + assertEquals("5.00 km", StringUtils.formatDistance(getContext(), 5000, true)); + // A large number in imperial + assertEquals("3.11 mi", StringUtils.formatDistance(getContext(), 5000, false)); + // A small number in metric + assertEquals("100.00 m", StringUtils.formatDistance(getContext(), 100, true)); + // A small number in imperial + assertEquals("328.08 ft", StringUtils.formatDistance(getContext(), 100, false)); + } + + /** + * Tests {@link StringUtils#formatCData(String)}. + */ + public void testFormatCData() { + assertEquals("", StringUtils.formatCData("hello")); + assertEquals("there]]>", StringUtils.formatCData("hello]]>there")); + } + + /** + * Tests {@link StringUtils#getTime(String)}. + */ + public void testGetTime() { + assertGetTime("2010-05-04T03:02:01", 2010, 5, 4, 3, 2, 1, 0); + assertGetTime("2010-05-04T03:02:01Z", 2010, 5, 4, 3, 2, 1, 0); + } + + /** + * Tests {@link StringUtils#getTime(String)} with fractional seconds. + */ + public void testGetTime_fractional() { + assertGetTime("2010-05-04T03:02:01.3", 2010, 5, 4, 3, 2, 1, 300); + assertGetTime("2010-05-04T03:02:01.35", 2010, 5, 4, 3, 2, 1, 350); + assertGetTime("2010-05-04T03:02:01.352Z", 2010, 5, 4, 3, 2, 1, 352); + assertGetTime("2010-05-04T03:02:01.3525Z", 2010, 5, 4, 3, 2, 1, 352); + } + + /** + * Tests {@link StringUtils#getTime(String)} with time zone. + */ + public void testGetTime_timezone() { + assertGetTime("2010-05-04T03:02:01Z", 2010, 5, 4, 3, 2, 1, 0); + assertGetTime("2010-05-04T03:02:01+00:00", 2010, 5, 4, 3, 2, 1, 0); + assertGetTime("2010-05-04T03:02:01-00:00", 2010, 5, 4, 3, 2, 1, 0); + assertGetTime("2010-05-04T03:02:01+01:00", 2010, 5, 4, 2, 2, 1, 0); + assertGetTime("2010-05-04T03:02:01+10:30", 2010, 5, 3, 16, 32, 1, 0); + assertGetTime("2010-05-04T03:02:01-09:30", 2010, 5, 4, 12, 32, 1, 0); + assertGetTime("2010-05-04T03:02:01-05:00", 2010, 5, 4, 8, 2, 1, 0); + } + + /** + * Tests {@link StringUtils#getTime(String)} with fractional seconds and time + * zone. + */ + public void testGetTime_fractionalAndTimezone() { + assertGetTime("2010-05-04T03:02:01.352Z", 2010, 5, 4, 3, 2, 1, 352); + assertGetTime("2010-05-04T03:02:01.47+00:00", 2010, 5, 4, 3, 2, 1, 470); + assertGetTime("2010-05-04T03:02:01.5791+03:00", 2010, 5, 4, 0, 2, 1, 579); + assertGetTime("2010-05-04T03:02:01.8-05:30", 2010, 5, 4, 8, 32, 1, 800); + } + + /** + * Asserts the {@link StringUtils#getTime(String)} returns the expected + * values. + * + * @param xmlDateTime the xml date time string + * @param year the expected year + * @param month the expected month + * @param day the expected day + * @param hour the expected hour + * @param minute the expected minute + * @param second the expected second + * @param millisecond the expected milliseconds + */ + private void assertGetTime(String xmlDateTime, int year, int month, int day, int hour, int minute, + int second, int millisecond) { + GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC")); + calendar.set(year, month - 1, day, hour, minute, second); + calendar.set(GregorianCalendar.MILLISECOND, millisecond); + assertEquals(calendar.getTimeInMillis(), StringUtils.getTime(xmlDateTime)); + } + + /** + * Tests {@link StringUtils#getTimeParts(long)} with a positive number. + */ + public void testGetTimeParts_postive() { + int parts[] = StringUtils.getTimeParts(61000); + assertEquals(1, parts[0]); + assertEquals(1, parts[1]); + assertEquals(0, parts[2]); + } + + /** + * Tests {@link StringUtils#getTimeParts(long)} with a negative number. + */ + public void testGetTimeParts_negative() { + int parts[] = StringUtils.getTimeParts(-61000); + assertEquals(-1, parts[0]); + assertEquals(-1, parts[1]); + assertEquals(0, parts[2]); + } +} diff --git a/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/util/TrackNameUtilsTest.java b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/util/TrackNameUtilsTest.java new file mode 100644 index 000000000..202ec0922 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/java/com/google/android/apps/mytracks/util/TrackNameUtilsTest.java @@ -0,0 +1,71 @@ +/* + * 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. + */ + +package com.google.android.apps.mytracks.util; + +import com.google.android.maps.mytracks.R; + +import android.test.AndroidTestCase; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +/** + * Tests {@link TrackNameUtils}. + * + * @author Matthew Simmons + */ +public class TrackNameUtilsTest extends AndroidTestCase { + + private static final long TRACK_ID = 1L; + private static final long START_TIME = 1288213406000L; + + /** + * Tests when the track_name_key is + * settings_recording_track_name_date_local_value. + */ + public void testTrackName_date_local() { + PreferencesUtils.setString(getContext(), R.string.track_name_key, + getContext().getString(R.string.settings_recording_track_name_date_local_value)); + assertEquals(StringUtils.formatDateTime(getContext(), START_TIME), + TrackNameUtils.getTrackName(getContext(), TRACK_ID, START_TIME, null)); + } + + /** + * Tests when the track_name_key is + * settings_recording_track_name_date_iso_8601_value. + */ + public void testTrackName_date_iso_8601() { + PreferencesUtils.setString(getContext(), R.string.track_name_key, + getContext().getString(R.string.settings_recording_track_name_date_iso_8601_value)); + SimpleDateFormat simpleDateFormat = new SimpleDateFormat( + TrackNameUtils.ISO_8601_FORMAT, Locale.US); + assertEquals(simpleDateFormat.format(new Date(START_TIME)), + TrackNameUtils.getTrackName(getContext(), TRACK_ID, START_TIME, null)); + } + + /** + * Tests when the track_name_key is + * settings_recording_track_name_number_value. + */ + public void testTrackName_number() { + PreferencesUtils.setString(getContext(), R.string.track_name_key, + getContext().getString(R.string.settings_recording_track_name_number_value)); + assertEquals( + "Track " + TRACK_ID, TrackNameUtils.getTrackName(getContext(), TRACK_ID, START_TIME, null)); + } +} diff --git a/MyTracks/myTracks/src/androidTest/res/.readme b/MyTracks/myTracks/src/androidTest/res/.readme new file mode 100644 index 000000000..5700541c0 --- /dev/null +++ b/MyTracks/myTracks/src/androidTest/res/.readme @@ -0,0 +1 @@ +This hidden file is here to ensure there is a res folder. diff --git a/MyTracks/AndroidManifest.xml b/MyTracks/myTracks/src/main/AndroidManifest.xml old mode 100755 new mode 100644 similarity index 99% rename from MyTracks/AndroidManifest.xml rename to MyTracks/myTracks/src/main/AndroidManifest.xml index 33f5ba72f..505f9ab9f --- a/MyTracks/AndroidManifest.xml +++ b/MyTracks/myTracks/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> + android:theme="@style/ThemeMyTracks" + tools:replace="android:label" > + + + + + + + + + + \ No newline at end of file diff --git a/MyTracks/myTracksLib/src/main/aidl/com/google/android/apps/mytracks/content/Waypoint.aidl b/MyTracks/myTracksLib/src/main/aidl/com/google/android/apps/mytracks/content/Waypoint.aidl new file mode 100644 index 000000000..fece6fd44 --- /dev/null +++ b/MyTracks/myTracksLib/src/main/aidl/com/google/android/apps/mytracks/content/Waypoint.aidl @@ -0,0 +1,2 @@ +package com.google.android.apps.mytracks.content; +parcelable Waypoint; \ No newline at end of file diff --git a/MyTracks/myTracksLib/src/main/aidl/com/google/android/apps/mytracks/content/WaypointCreationRequest.aidl b/MyTracks/myTracksLib/src/main/aidl/com/google/android/apps/mytracks/content/WaypointCreationRequest.aidl new file mode 100644 index 000000000..c0d008f36 --- /dev/null +++ b/MyTracks/myTracksLib/src/main/aidl/com/google/android/apps/mytracks/content/WaypointCreationRequest.aidl @@ -0,0 +1,2 @@ +package com.google.android.apps.mytracks.content; +parcelable WaypointCreationRequest; \ No newline at end of file diff --git a/MyTracks/myTracksLib/src/main/aidl/com/google/android/apps/mytracks/services/ITrackRecordingService.aidl b/MyTracks/myTracksLib/src/main/aidl/com/google/android/apps/mytracks/services/ITrackRecordingService.aidl new file mode 100644 index 000000000..0ef27b480 --- /dev/null +++ b/MyTracks/myTracksLib/src/main/aidl/com/google/android/apps/mytracks/services/ITrackRecordingService.aidl @@ -0,0 +1,114 @@ +/* + * 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.services; + +import com.google.android.apps.mytracks.content.WaypointCreationRequest; + +/** + * MyTracks service. + * This service is the process that actually records and manages tracks. + */ +interface ITrackRecordingService { + + /** + * Starts gps. + */ + void startGps(); + + /** + * Stops gps. + */ + void stopGps(); + + /** + * Starts recording a new track. + * + * @return the track ID of the new track. + */ + long startNewTrack(); + + /** + * Pauses the current recording track. + */ + void pauseCurrentTrack(); + + /** + * Resumes the current recording track. + */ + void resumeCurrentTrack(); + + /** + * Ends the current recording track. + */ + void endCurrentTrack(); + + /** + * Returns true if currently recording a track. + */ + boolean isRecording(); + + /** + * Returns true if the current recording track is paused. Returns true if not recording. + */ + boolean isPaused(); + + /** + * Gets the current recording track ID. Returns -1 if not recording. + */ + long getRecordingTrackId(); + + /** + * Gets the total time for the current recording track. Returns 0 if not recording. + */ + long getTotalTime(); + + /** + * Inserts a waypoint in the current recording track. + * + * @param request the details of the waypoint to be inserted + * @return the ID of the inserted waypoint + */ + long insertWaypoint(in WaypointCreationRequest request); + + /** + * Inserts a track point in the current recording track. + * + * When recording a track, GPS locations are automatically inserted. This is used for + * inserting special track points or for testing. + * + * @param location the track point to be inserted + */ + void insertTrackPoint(in Location location); + + /** + * Gets the current sensor data. Returns null if there is no data. + + * @return a byte array of the binary version of the Sensor.SensorDataSet object. + */ + byte[] getSensorData(); + + /** + * Gets the current sensor manager state. + * + * return a Sensor.SensorState enum value. + */ + int getSensorState(); + + /** + * Updates the calorie of current recording track. + */ + void updateCalorie(); +} diff --git a/MyTracks/myTracksLib/src/main/aidl/com/google/android/apps/mytracks/stats/TripStatistics.aidl b/MyTracks/myTracksLib/src/main/aidl/com/google/android/apps/mytracks/stats/TripStatistics.aidl new file mode 100644 index 000000000..b411f6ccd --- /dev/null +++ b/MyTracks/myTracksLib/src/main/aidl/com/google/android/apps/mytracks/stats/TripStatistics.aidl @@ -0,0 +1,2 @@ +package com.google.android.apps.mytracks.stats; +parcelable TripStatistics; \ No newline at end of file diff --git a/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/ContentTypeIds.java b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/ContentTypeIds.java new file mode 100644 index 000000000..72c4020ea --- /dev/null +++ b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/ContentTypeIds.java @@ -0,0 +1,35 @@ +/* + * 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. + */ + +package com.google.android.apps.mytracks.content; + +/** + * Utilities for serializing primitive types. + * + * @author Rodrigo Damazio + */ +public class ContentTypeIds { + + private ContentTypeIds() {} + + public static final byte BOOLEAN_TYPE_ID = 0; + public static final byte LONG_TYPE_ID = 1; + public static final byte INT_TYPE_ID = 2; + public static final byte FLOAT_TYPE_ID = 3; + public static final byte DOUBLE_TYPE_ID = 4; + public static final byte STRING_TYPE_ID = 5; + public static final byte BLOB_TYPE_ID = 6; +} diff --git a/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/DescriptionGenerator.java b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/DescriptionGenerator.java new file mode 100644 index 000000000..6a489d40e --- /dev/null +++ b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/DescriptionGenerator.java @@ -0,0 +1,47 @@ +/* + * 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. + */ +package com.google.android.apps.mytracks.content; + +import com.google.android.apps.mytracks.stats.TripStatistics; + +import java.util.Vector; + +/** + * An interface for an object that can generate descriptions of track and + * waypoint. + * + * @author Sandor Dornbush + */ +public interface DescriptionGenerator { + + /** + * Generates a track description. + * + * @param track the track + * @param distances a vector of distances to generate the elevation chart + * @param elevations a vector of elevations to generate the elevation chart + * @param html true to output html, false to output plain text + */ + public String generateTrackDescription( + Track track, Vector distances, Vector elevations, boolean html); + + /** + * Generate a waypoint description from a trip statistics. + * + * @param tripStatistics the trip statistics + */ + public String generateWaypointDescription(TripStatistics tripStatistics); +} diff --git a/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/MyTracksLocation.java b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/MyTracksLocation.java new file mode 100644 index 000000000..081e5d6ec --- /dev/null +++ b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/MyTracksLocation.java @@ -0,0 +1,66 @@ +/* + * 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. + */ +package com.google.android.apps.mytracks.content; + +import com.google.android.apps.mytracks.content.Sensor.SensorDataSet; + +import android.location.Location; + +/** + * This class extends the standard Android location with extra information. + * + * @author Sandor Dornbush + */ +public class MyTracksLocation extends Location { + + private SensorDataSet sensorDataSet = null; + + /** + * The id of this location from the provider. + */ + private int id = -1; + + public MyTracksLocation(Location location, Sensor.SensorDataSet sd) { + super(location); + this.sensorDataSet = sd; + } + + public MyTracksLocation(String provider) { + super(provider); + } + + public SensorDataSet getSensorDataSet() { + return sensorDataSet; + } + + public void setSensorDataSet(SensorDataSet sensorDataSet) { + this.sensorDataSet = sensorDataSet; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public void reset() { + super.reset(); + sensorDataSet = null; + id = -1; + } +} diff --git a/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/MyTracksProviderUtils.java b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/MyTracksProviderUtils.java new file mode 100644 index 000000000..3bdb57c80 --- /dev/null +++ b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/MyTracksProviderUtils.java @@ -0,0 +1,402 @@ +/* + * 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. + */ + +package com.google.android.apps.mytracks.content; + +import com.google.android.apps.mytracks.content.Waypoint.WaypointType; + +import android.content.Context; +import android.database.Cursor; +import android.location.Location; +import android.location.LocationManager; +import android.net.Uri; + +import java.util.Iterator; +import java.util.List; + +/** + * Utilities to access data from the My Tracks content provider. + * + * @author Rodrigo Damazio + */ +public interface MyTracksProviderUtils { + + /** + * The authority (the first part of the URI) for the My Tracks content + * provider. + */ + public static final String AUTHORITY = "com.google.android.maps.mytracks"; + + /** + * Clears a track. Removes waypoints and trackpoints. Only keeps the track id. + * + * @param trackId the track id + */ + public void clearTrack(Context context, long trackId); + + /** + * Creates a {@link Track} from a cursor. + * + * @param cursor the cursor pointing to the track + */ + public Track createTrack(Cursor cursor); + + /** + * Deletes all tracks (including waypoints and track points). + */ + public void deleteAllTracks(Context context); + + /** + * Deletes a track. + * + * @param trackId the track id + */ + public void deleteTrack(Context context, long trackId); + + /** + * Gets all the tracks. If no track exists, an empty list is returned. + *

+ * Note that the returned tracks do not have any track points attached. + */ + public List getAllTracks(); + + /** + * Gets the last track. Returns null if doesn't exist. + */ + public Track getLastTrack(); + + /** + * Gets a track by a track id. Returns null if not found. + *

+ * Note that the returned track doesn't have any track points attached. + * + * @param trackId the track id. + */ + public Track getTrack(long trackId); + + /** + * Gets a track cursor. The caller owns the returned cursor and is responsible + * for closing it. + * + * @param selection the selection. Can be null + * @param selectionArgs the selection arguments. Can be null + * @param sortOrder the sort order. Can be null + */ + public Cursor getTrackCursor(String selection, String[] selectionArgs, String sortOrder); + + /** + * Inserts a track. + *

+ * Note: This doesn't insert any track points. + * + * @param track the track + * @return the content provider URI of the inserted track. + */ + public Uri insertTrack(Track track); + + /** + * Updates a track. + *

+ * Note: This doesn't update any track points. + * + * @param track the track + */ + public void updateTrack(Track track); + + /** + * Creates a waypoint from a cursor. + * + * @param cursor the cursor pointing to the waypoint + */ + public Waypoint createWaypoint(Cursor cursor); + + /** + * Deletes a waypoint. If deleting a statistics waypoint, this will also + * correct the next statistics waypoint after the deleted one to reflect the + * deletion. The generator is used to update the next statistics waypoint. + * + * @param waypointId the waypoint id + * @param descriptionGenerator the description generator. Can be null for + * waypoint marker + */ + public void deleteWaypoint(Context context, long waypointId, DescriptionGenerator descriptionGenerator); + + /** + * Gets the first waypoint id for a track. The first waypoint is special as it + * contains the stats for the track. Returns -1L if it doesn't exist. + * + * @param trackId the track id + */ + public long getFirstWaypointId(long trackId); + + /** + * Gets the last waypoint for a type. Returns null if it doesn't exist. + * + * @param trackId the track id + * @param waypointType the waypoint type + */ + public Waypoint getLastWaypoint(long trackId, WaypointType waypointType); + + /** + * Gets the next waypoint number for a type. Returns -1 if not able to get the + * next waypoint number. + * + * @param trackId the track id + * @param waypointType the waypoint type + */ + public int getNextWaypointNumber(long trackId, WaypointType waypointType); + + /** + * Gets a waypoint from a waypoint id. Returns null if not found. + * + * @param waypointId the waypoint id + */ + public Waypoint getWaypoint(long waypointId); + + /** + * Gets a waypoint cursor. The caller owns the returned cursor and is + * responsible for closing it. + * + * @param selection the selection. Can be null + * @param selectionArgs the selection arguments. Can be null + * @param sortOrder the sort order. Can be null + * @param maxWaypoints the maximum number of waypoints to return. -1 for no + * limit + */ + public Cursor getWaypointCursor( + String selection, String[] selectionArgs, String sortOrder, int maxWaypoints); + + /** + * Gets a waypoint cursor for a track. The caller owns the returned cursor and + * is responsible for closing it. + * + * @param trackId the track id + * @param minWaypointId the minimum waypoint id. -1L to ignore + * @param maxWaypoints the maximum number of waypoints to return. -1 for no + * limit + */ + public Cursor getWaypointCursor(long trackId, long minWaypointId, int maxWaypoints); + + /** + * Gets the number of waypoints for a track. + * + * @param trackId the track id + */ + public int getWaypointCount(long trackId); + + /** + * Inserts a waypoint. + * + * @param waypoint the waypoint + * @return the content provider URI of the inserted waypoint. + */ + public Uri insertWaypoint(Waypoint waypoint); + + /** + * Updates a waypoint. Returns true if successful. + * + * @param waypoint the waypoint + */ + public boolean updateWaypoint(Waypoint waypoint); + + /** + * Inserts multiple track points. + * + * @param locations an array of locations + * @param length the number of locations (from the beginning of the array) to + * insert, or -1 for all of them + * @param trackId the track id + * @return the number of points inserted + */ + public int bulkInsertTrackPoint(Location[] locations, int length, long trackId); + + /** + * Creates a location object from a cursor. + * + * @param cursor the cursor pointing to the location + */ + public Location createTrackPoint(Cursor cursor); + + /** + * Gets the first location id for a track. Returns -1L if it doesn't exist. + * + * @param trackId the track id + */ + public long getFirstTrackPointId(long trackId); + + /** + * Gets the last location id for a track. Returns -1L if it doesn't exist. + * + * @param trackId the track id + */ + public long getLastTrackPointId(long trackId); + + /** + * Gets the track point id of a location. + * + * @param trackId the track id + * @param location the location + * @return track point id if the location is in the track. -1L otherwise. + */ + public long getTrackPointId(long trackId, Location location); + + /** + * Gets the first valid location for a track. Returns null if it doesn't + * exist. + * + * @param trackId the track id + */ + public Location getFirstValidTrackPoint(long trackId); + + /** + * Gets the last valid location for a track. Returns null if it doesn't exist. + * + * @param trackId the track id + */ + public Location getLastValidTrackPoint(long trackId); + + + /** + * Gets the last valid location. + */ + public Location getLastValidTrackPoint(); + + /** + * Creates a location cursor. The caller owns the returned cursor and is + * responsible for closing it. + * + * @param trackId the track id + * @param startTrackPointId the starting track point id. -1L to ignore + * @param maxLocations maximum number of locations to return. -1 for no limit + * @param descending true to sort the result in descending order (latest + * location first) + */ + public Cursor getTrackPointCursor( + long trackId, long startTrackPointId, int maxLocations, boolean descending); + + /** + * Creates a new read-only iterator over a given track's points. It provides a + * lightweight way of iterating over long tracks without failing due to the + * underlying cursor limitations. Since it's a read-only iterator, + * {@link Iterator#remove()} always throws + * {@link UnsupportedOperationException}. Each call to + * {@link LocationIterator#next()} may advance to the next DB record, and if + * so, the iterator calls {@link LocationFactory#createLocation()} and + * populates it with information retrieved from the record. When done with + * iteration, {@link LocationIterator#close()} must be called. + * + * @param trackId the track id + * @param startTrackPointId the starting track point id. -1L to ignore + * @param descending true to sort the result in descending order (latest + * location first) + * @param locationFactory the location factory + */ + public LocationIterator getTrackPointLocationIterator( + long trackId, long startTrackPointId, boolean descending, LocationFactory locationFactory); + + /** + * Inserts a track point. + * + * @param location the location + * @param trackId the track id + * @return the content provider URI of the inserted track point + */ + public Uri insertTrackPoint(Location location, long trackId); + + /** + * A lightweight wrapper around the original {@link Cursor} with a method to + * clean up. + */ + public interface LocationIterator extends Iterator { + + /** + * Gets the most recently retrieved track point id by {@link #next()}. + */ + public long getLocationId(); + + /** + * Closes the iterator. + */ + public void close(); + } + + /** + * A factory for creating new {@link Location}. + */ + public interface LocationFactory { + + /** + * Creates a new {@link Location}. An implementation can create new + * instances or reuse existing instances for optimization. + */ + public Location createLocation(); + } + + /** + * The default {@link LocationFactory} which creates a location each time. + */ + public LocationFactory DEFAULT_LOCATION_FACTORY = new LocationFactory() { + @Override + public Location createLocation() { + return new MyTracksLocation(LocationManager.GPS_PROVIDER); + } + }; + + /** + * A factory which can produce instances of {@link MyTracksProviderUtils}, and + * can be overridden for testing. + */ + public static class Factory { + + private static Factory instance = new Factory(); + + /** + * Creates an instance of {@link MyTracksProviderUtils}. + * + * @param context the context + */ + public static MyTracksProviderUtils get(Context context) { + return instance.newForContext(context); + } + + /** + * Returns the factory instance. + */ + public static Factory getInstance() { + return instance; + } + + /** + * Overrides the factory instance for testing. Don't forget to set it back + * to the original value after testing. + * + * @param factory the factory + */ + public static void overrideInstance(Factory factory) { + instance = factory; + } + + /** + * Creates an instance of {@link MyTracksProviderUtils}. Allows subclasses + * to override for testing. + * + * @param context the context + */ + protected MyTracksProviderUtils newForContext(Context context) { + return new MyTracksProviderUtilsImpl(context.getContentResolver()); + } + } +} diff --git a/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/MyTracksProviderUtilsImpl.java b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/MyTracksProviderUtilsImpl.java new file mode 100644 index 000000000..2bcf13d60 --- /dev/null +++ b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/MyTracksProviderUtilsImpl.java @@ -0,0 +1,1186 @@ +/* + * 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.content; + +import com.google.android.apps.mytracks.content.Sensor.SensorDataSet; +import com.google.android.apps.mytracks.content.Waypoint.WaypointType; +import com.google.android.apps.mytracks.stats.TripStatistics; +import com.google.android.apps.mytracks.util.FileUtils; +import com.google.protobuf.InvalidProtocolBufferException; + +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.location.Location; +import android.net.Uri; +import android.util.Log; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; + +/** + * {@link MyTracksProviderUtils} implementation. + * + * @author Leif Hendrik Wilden + */ +public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils { + + private static final String TAG = MyTracksProviderUtilsImpl.class.getSimpleName(); + + private static final int MAX_LATITUDE = 90000000; + + private final ContentResolver contentResolver; + private int defaultCursorBatchSize = 2000; + + public MyTracksProviderUtilsImpl(ContentResolver contentResolver) { + this.contentResolver = contentResolver; + } + + @Override + public void clearTrack(Context context, long trackId) { + deleteTrackPointsAndWaypoints(context, trackId); + Track track = new Track(); + track.setId(trackId); + updateTrack(track); + } + + @Override + public Track createTrack(Cursor cursor) { + int idIndex = cursor.getColumnIndexOrThrow(TracksColumns._ID); + int nameIndex = cursor.getColumnIndexOrThrow(TracksColumns.NAME); + int descriptionIndex = cursor.getColumnIndexOrThrow(TracksColumns.DESCRIPTION); + int categoryIndex = cursor.getColumnIndexOrThrow(TracksColumns.CATEGORY); + int startIdIndex = cursor.getColumnIndexOrThrow(TracksColumns.STARTID); + int stopIdIndex = cursor.getColumnIndexOrThrow(TracksColumns.STOPID); + int startTimeIndex = cursor.getColumnIndexOrThrow(TracksColumns.STARTTIME); + int stopTimeIndex = cursor.getColumnIndexOrThrow(TracksColumns.STOPTIME); + int numPointsIndex = cursor.getColumnIndexOrThrow(TracksColumns.NUMPOINTS); + int totalDistanceIndex = cursor.getColumnIndexOrThrow(TracksColumns.TOTALDISTANCE); + int totalTimeIndex = cursor.getColumnIndexOrThrow(TracksColumns.TOTALTIME); + int movingTimeIndex = cursor.getColumnIndexOrThrow(TracksColumns.MOVINGTIME); + int minLatIndex = cursor.getColumnIndexOrThrow(TracksColumns.MINLAT); + int maxLatIndex = cursor.getColumnIndexOrThrow(TracksColumns.MAXLAT); + int minLonIndex = cursor.getColumnIndexOrThrow(TracksColumns.MINLON); + int maxLonIndex = cursor.getColumnIndexOrThrow(TracksColumns.MAXLON); + int maxSpeedIndex = cursor.getColumnIndexOrThrow(TracksColumns.MAXSPEED); + int minElevationIndex = cursor.getColumnIndexOrThrow(TracksColumns.MINELEVATION); + int maxElevationIndex = cursor.getColumnIndexOrThrow(TracksColumns.MAXELEVATION); + int elevationGainIndex = cursor.getColumnIndexOrThrow(TracksColumns.ELEVATIONGAIN); + int minGradeIndex = cursor.getColumnIndexOrThrow(TracksColumns.MINGRADE); + int maxGradeIndex = cursor.getColumnIndexOrThrow(TracksColumns.MAXGRADE); + int iconIndex = cursor.getColumnIndexOrThrow(TracksColumns.ICON); + int driveIdIndex = cursor.getColumnIndexOrThrow(TracksColumns.DRIVEID); + int modifiedTimeIndex = cursor.getColumnIndexOrThrow(TracksColumns.MODIFIEDTIME); + int sharedWithMeIndex = cursor.getColumnIndexOrThrow(TracksColumns.SHAREDWITHME); + int sharedOwnerIndex = cursor.getColumnIndexOrThrow(TracksColumns.SHAREDOWNER); + int caloriesIndex = cursor.getColumnIndexOrThrow(TracksColumns.CALORIE); + + Track track = new Track(); + TripStatistics tripStatistics = track.getTripStatistics(); + if (!cursor.isNull(idIndex)) { + track.setId(cursor.getLong(idIndex)); + } + if (!cursor.isNull(nameIndex)) { + track.setName(cursor.getString(nameIndex)); + } + if (!cursor.isNull(descriptionIndex)) { + track.setDescription(cursor.getString(descriptionIndex)); + } + if (!cursor.isNull(categoryIndex)) { + track.setCategory(cursor.getString(categoryIndex)); + } + if (!cursor.isNull(startIdIndex)) { + track.setStartId(cursor.getLong(startIdIndex)); + } + if (!cursor.isNull(stopIdIndex)) { + track.setStopId(cursor.getLong(stopIdIndex)); + } + if (!cursor.isNull(startTimeIndex)) { + tripStatistics.setStartTime(cursor.getLong(startTimeIndex)); + } + if (!cursor.isNull(stopTimeIndex)) { + tripStatistics.setStopTime(cursor.getLong(stopTimeIndex)); + } + if (!cursor.isNull(numPointsIndex)) { + track.setNumberOfPoints(cursor.getInt(numPointsIndex)); + } + if (!cursor.isNull(totalDistanceIndex)) { + tripStatistics.setTotalDistance(cursor.getFloat(totalDistanceIndex)); + } + if (!cursor.isNull(totalTimeIndex)) { + tripStatistics.setTotalTime(cursor.getLong(totalTimeIndex)); + } + if (!cursor.isNull(movingTimeIndex)) { + tripStatistics.setMovingTime(cursor.getLong(movingTimeIndex)); + } + if (!cursor.isNull(minLatIndex) && !cursor.isNull(maxLatIndex) && !cursor.isNull(minLonIndex) + && !cursor.isNull(maxLonIndex)) { + int bottom = cursor.getInt(minLatIndex); + int top = cursor.getInt(maxLatIndex); + int left = cursor.getInt(minLonIndex); + int right = cursor.getInt(maxLonIndex); + tripStatistics.setBounds(left, top, right, bottom); + } + if (!cursor.isNull(maxSpeedIndex)) { + tripStatistics.setMaxSpeed(cursor.getFloat(maxSpeedIndex)); + } + if (!cursor.isNull(minElevationIndex)) { + tripStatistics.setMinElevation(cursor.getFloat(minElevationIndex)); + } + if (!cursor.isNull(maxElevationIndex)) { + tripStatistics.setMaxElevation(cursor.getFloat(maxElevationIndex)); + } + if (!cursor.isNull(elevationGainIndex)) { + tripStatistics.setTotalElevationGain(cursor.getFloat(elevationGainIndex)); + } + if (!cursor.isNull(minGradeIndex)) { + tripStatistics.setMinGrade(cursor.getFloat(minGradeIndex)); + } + if (!cursor.isNull(maxGradeIndex)) { + tripStatistics.setMaxGrade(cursor.getFloat(maxGradeIndex)); + } + if (!cursor.isNull(caloriesIndex)) { + tripStatistics.setCalorie(cursor.getFloat(caloriesIndex)); + } + if (!cursor.isNull(iconIndex)) { + track.setIcon(cursor.getString(iconIndex)); + } + if (!cursor.isNull(driveIdIndex)) { + track.setDriveId(cursor.getString(driveIdIndex)); + } + if (!cursor.isNull(modifiedTimeIndex)) { + track.setModifiedTime(cursor.getLong(modifiedTimeIndex)); + } + if (!cursor.isNull(sharedWithMeIndex)) { + track.setSharedWithMe(cursor.getInt(sharedWithMeIndex) == 1); + } + if (!cursor.isNull(sharedOwnerIndex)) { + track.setSharedOwner(cursor.getString(sharedOwnerIndex)); + } + return track; + } + + @Override + public void deleteAllTracks(Context context) { + contentResolver.delete(TrackPointsColumns.CONTENT_URI, null, null); + contentResolver.delete(WaypointsColumns.CONTENT_URI, null, null); + // Delete tracks last since it triggers a database vaccum call + contentResolver.delete(TracksColumns.CONTENT_URI, null, null); + + File dir = FileUtils.getPhotoDir(); + deleteDirectoryRecurse(context, dir); + } + + @Override + public void deleteTrack(Context context, long trackId) { + deleteTrackPointsAndWaypoints(context, trackId); + + // Delete track last since it triggers a database vaccum call + contentResolver.delete(TracksColumns.CONTENT_URI, TracksColumns._ID + "=?", + new String[] { Long.toString(trackId) }); + } + + /** + * Deletes track points and waypoints of a track. Assumes + * {@link TracksColumns#STARTID}, {@link TracksColumns#STOPID}, and + * {@link TracksColumns#NUMPOINTS} will be updated by the caller. + * + * @param trackId the track id + */ + private void deleteTrackPointsAndWaypoints(Context context, long trackId) { + Track track = getTrack(trackId); + if (track != null) { + String where = TrackPointsColumns._ID + ">=? AND " + TrackPointsColumns._ID + "<=?"; + String[] selectionArgs = new String[] { + Long.toString(track.getStartId()), Long.toString(track.getStopId()) }; + contentResolver.delete(TrackPointsColumns.CONTENT_URI, where, selectionArgs); + } + contentResolver.delete(WaypointsColumns.CONTENT_URI, WaypointsColumns.TRACKID + "=?", + new String[] { Long.toString(trackId) }); + deleteDirectoryRecurse(context, FileUtils.getPhotoDir(trackId)); + } + + /** + * Delete the directory recursively. + * + * @param dir the directory + */ + private void deleteDirectoryRecurse(Context context, File dir) { + if (FileUtils.isDirectory(dir)) { + for (File child : dir.listFiles()) { + deleteDirectoryRecurse(context, child); + } + } + if (dir.exists()) { + dir.delete(); + FileUtils.updateMediaScanner(context, Uri.fromFile(dir)); + } + } + + @Override + public List getAllTracks() { + ArrayList tracks = new ArrayList(); + Cursor cursor = null; + try { + cursor = getTrackCursor(null, null, null, TracksColumns._ID); + if (cursor != null && cursor.moveToFirst()) { + tracks.ensureCapacity(cursor.getCount()); + do { + tracks.add(createTrack(cursor)); + } while (cursor.moveToNext()); + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + return tracks; + } + + @Override + public Track getLastTrack() { + Cursor cursor = null; + try { + // Using the same order as shown in the track list + cursor = getTrackCursor(null, null, null, + TracksColumns.SHAREDWITHME + " ASC, " + TracksColumns.STARTTIME + " DESC"); + if (cursor != null && cursor.moveToNext()) { + return createTrack(cursor); + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + return null; + } + + @Override + public Track getTrack(long trackId) { + if (trackId < 0) { + return null; + } + Cursor cursor = null; + try { + cursor = getTrackCursor(null, TracksColumns._ID + "=?", + new String[] { Long.toString(trackId) }, TracksColumns._ID); + if (cursor != null && cursor.moveToNext()) { + return createTrack(cursor); + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + return null; + } + + @Override + public Cursor getTrackCursor(String selection, String[] selectionArgs, String sortOrder) { + return getTrackCursor(null, selection, selectionArgs, sortOrder); + } + + @Override + public Uri insertTrack(Track track) { + return contentResolver.insert(TracksColumns.CONTENT_URI, createContentValues(track)); + } + + @Override + public void updateTrack(Track track) { + contentResolver.update(TracksColumns.CONTENT_URI, createContentValues(track), + TracksColumns._ID + "=?", new String[] { Long.toString(track.getId()) }); + } + + private ContentValues createContentValues(Track track) { + ContentValues values = new ContentValues(); + TripStatistics tripStatistics = track.getTripStatistics(); + + // Value < 0 indicates no id is available + if (track.getId() >= 0) { + values.put(TracksColumns._ID, track.getId()); + } + values.put(TracksColumns.NAME, track.getName()); + values.put(TracksColumns.DESCRIPTION, track.getDescription()); + values.put(TracksColumns.CATEGORY, track.getCategory()); + values.put(TracksColumns.STARTID, track.getStartId()); + values.put(TracksColumns.STOPID, track.getStopId()); + values.put(TracksColumns.STARTTIME, tripStatistics.getStartTime()); + values.put(TracksColumns.STOPTIME, tripStatistics.getStopTime()); + values.put(TracksColumns.NUMPOINTS, track.getNumberOfPoints()); + values.put(TracksColumns.TOTALDISTANCE, tripStatistics.getTotalDistance()); + values.put(TracksColumns.TOTALTIME, tripStatistics.getTotalTime()); + values.put(TracksColumns.MOVINGTIME, tripStatistics.getMovingTime()); + values.put(TracksColumns.MINLAT, tripStatistics.getBottom()); + values.put(TracksColumns.MAXLAT, tripStatistics.getTop()); + values.put(TracksColumns.MINLON, tripStatistics.getLeft()); + values.put(TracksColumns.MAXLON, tripStatistics.getRight()); + values.put(TracksColumns.AVGSPEED, tripStatistics.getAverageSpeed()); + values.put(TracksColumns.AVGMOVINGSPEED, tripStatistics.getAverageMovingSpeed()); + values.put(TracksColumns.MAXSPEED, tripStatistics.getMaxSpeed()); + values.put(TracksColumns.MINELEVATION, tripStatistics.getMinElevation()); + values.put(TracksColumns.MAXELEVATION, tripStatistics.getMaxElevation()); + values.put(TracksColumns.ELEVATIONGAIN, tripStatistics.getTotalElevationGain()); + values.put(TracksColumns.MINGRADE, tripStatistics.getMinGrade()); + values.put(TracksColumns.MAXGRADE, tripStatistics.getMaxGrade()); + values.put(TracksColumns.ICON, track.getIcon()); + values.put(TracksColumns.DRIVEID, track.getDriveId()); + values.put(TracksColumns.MODIFIEDTIME, track.getModifiedTime()); + values.put(TracksColumns.SHAREDWITHME, track.isSharedWithMe()); + values.put(TracksColumns.SHAREDOWNER, track.getSharedOwner()); + values.put(TracksColumns.CALORIE, tripStatistics.getCalorie()); + + return values; + } + + /** + * Gets a track cursor. + * + * @param projection the projection + * @param selection the selection + * @param selectionArgs the selection arguments + * @param sortOrder the sort oder + */ + private Cursor getTrackCursor( + String[] projection, String selection, String[] selectionArgs, String sortOrder) { + return contentResolver.query( + TracksColumns.CONTENT_URI, projection, selection, selectionArgs, sortOrder); + } + + @Override + public Waypoint createWaypoint(Cursor cursor) { + int idIndex = cursor.getColumnIndexOrThrow(WaypointsColumns._ID); + int nameIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.NAME); + int descriptionIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.DESCRIPTION); + int categoryIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.CATEGORY); + int iconIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.ICON); + int trackIdIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.TRACKID); + int typeIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.TYPE); + int lengthIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.LENGTH); + int durationIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.DURATION); + int startTimeIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.STARTTIME); + int startIdIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.STARTID); + int stopIdIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.STOPID); + int longitudeIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.LONGITUDE); + int latitudeIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.LATITUDE); + int timeIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.TIME); + int altitudeIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.ALTITUDE); + int accuracyIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.ACCURACY); + int speedIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.SPEED); + int bearingIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.BEARING); + int totalDistanceIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.TOTALDISTANCE); + int totalTimeIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.TOTALTIME); + int movingTimeIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.MOVINGTIME); + int maxSpeedIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.MAXSPEED); + int minElevationIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.MINELEVATION); + int maxElevationIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.MAXELEVATION); + int elevationGainIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.ELEVATIONGAIN); + int minGradeIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.MINGRADE); + int maxGradeIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.MAXGRADE); + int calorieIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.CALORIE); + int photoUrlIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.PHOTOURL); + + Waypoint waypoint = new Waypoint(); + + if (!cursor.isNull(idIndex)) { + waypoint.setId(cursor.getLong(idIndex)); + } + if (!cursor.isNull(nameIndex)) { + waypoint.setName(cursor.getString(nameIndex)); + } + if (!cursor.isNull(descriptionIndex)) { + waypoint.setDescription(cursor.getString(descriptionIndex)); + } + if (!cursor.isNull(categoryIndex)) { + waypoint.setCategory(cursor.getString(categoryIndex)); + } + if (!cursor.isNull(iconIndex)) { + waypoint.setIcon(cursor.getString(iconIndex)); + } + if (!cursor.isNull(trackIdIndex)) { + waypoint.setTrackId(cursor.getLong(trackIdIndex)); + } + if (!cursor.isNull(typeIndex)) { + waypoint.setType(WaypointType.values()[cursor.getInt(typeIndex)]); + } + if (!cursor.isNull(lengthIndex)) { + waypoint.setLength(cursor.getFloat(lengthIndex)); + } + if (!cursor.isNull(durationIndex)) { + waypoint.setDuration(cursor.getLong(durationIndex)); + } + if (!cursor.isNull(startIdIndex)) { + waypoint.setStartId(cursor.getLong(startIdIndex)); + } + if (!cursor.isNull(stopIdIndex)) { + waypoint.setStopId(cursor.getLong(stopIdIndex)); + } + + Location location = new Location(""); + if (!cursor.isNull(longitudeIndex) && !cursor.isNull(latitudeIndex)) { + location.setLongitude(((double) cursor.getInt(longitudeIndex)) / 1E6); + location.setLatitude(((double) cursor.getInt(latitudeIndex)) / 1E6); + } + if (!cursor.isNull(timeIndex)) { + location.setTime(cursor.getLong(timeIndex)); + } + if (!cursor.isNull(altitudeIndex)) { + location.setAltitude(cursor.getFloat(altitudeIndex)); + } + if (!cursor.isNull(accuracyIndex)) { + location.setAccuracy(cursor.getFloat(accuracyIndex)); + } + if (!cursor.isNull(speedIndex)) { + location.setSpeed(cursor.getFloat(speedIndex)); + } + if (!cursor.isNull(bearingIndex)) { + location.setBearing(cursor.getFloat(bearingIndex)); + } + waypoint.setLocation(location); + + TripStatistics tripStatistics = new TripStatistics(); + boolean hasTripStatistics = false; + if (!cursor.isNull(startTimeIndex)) { + tripStatistics.setStartTime(cursor.getLong(startTimeIndex)); + hasTripStatistics = true; + } + if (!cursor.isNull(totalDistanceIndex)) { + tripStatistics.setTotalDistance(cursor.getFloat(totalDistanceIndex)); + hasTripStatistics = true; + } + if (!cursor.isNull(totalTimeIndex)) { + tripStatistics.setTotalTime(cursor.getLong(totalTimeIndex)); + hasTripStatistics = true; + } + if (!cursor.isNull(movingTimeIndex)) { + tripStatistics.setMovingTime(cursor.getLong(movingTimeIndex)); + hasTripStatistics = true; + } + if (!cursor.isNull(maxSpeedIndex)) { + tripStatistics.setMaxSpeed(cursor.getFloat(maxSpeedIndex)); + hasTripStatistics = true; + } + if (!cursor.isNull(minElevationIndex)) { + tripStatistics.setMinElevation(cursor.getFloat(minElevationIndex)); + hasTripStatistics = true; + } + if (!cursor.isNull(maxElevationIndex)) { + tripStatistics.setMaxElevation(cursor.getFloat(maxElevationIndex)); + hasTripStatistics = true; + } + if (!cursor.isNull(elevationGainIndex)) { + tripStatistics.setTotalElevationGain(cursor.getFloat(elevationGainIndex)); + hasTripStatistics = true; + } + if (!cursor.isNull(minGradeIndex)) { + tripStatistics.setMinGrade(cursor.getFloat(minGradeIndex)); + hasTripStatistics = true; + } + if (!cursor.isNull(maxGradeIndex)) { + tripStatistics.setMaxGrade(cursor.getFloat(maxGradeIndex)); + hasTripStatistics = true; + } + if (!cursor.isNull(calorieIndex)) { + tripStatistics.setCalorie(cursor.getFloat(calorieIndex)); + hasTripStatistics = true; + } + if (hasTripStatistics) { + waypoint.setTripStatistics(tripStatistics); + } + + if (!cursor.isNull(photoUrlIndex)) { + waypoint.setPhotoUrl(cursor.getString(photoUrlIndex)); + } + return waypoint; + } + + @Override + public void deleteWaypoint(Context context, long waypointId, DescriptionGenerator descriptionGenerator) { + final Waypoint waypoint = getWaypoint(waypointId); + if (waypoint != null && waypoint.getType() == WaypointType.STATISTICS + && descriptionGenerator != null) { + final Waypoint nextWaypoint = getNextStatisticsWaypointAfter(waypoint); + if (nextWaypoint == null) { + Log.d(TAG, "Unable to find the next statistics marker after deleting one."); + } else { + nextWaypoint.getTripStatistics().merge(waypoint.getTripStatistics()); + nextWaypoint.setDescription( + descriptionGenerator.generateWaypointDescription(nextWaypoint.getTripStatistics())); + if (!updateWaypoint(nextWaypoint)) { + Log.e(TAG, "Unable to update the next statistics marker after deleting one."); + } + } + } + if (waypoint != null) { + String photoUrl = waypoint.getPhotoUrl(); + if (photoUrl != null && !photoUrl.equals("")) { + Uri uri = Uri.parse(photoUrl); + File file = new File(uri.getPath()); + if (file.exists()) { + File parent = file.getParentFile(); + file.delete(); + FileUtils.updateMediaScanner(context, uri); + if (parent.listFiles().length == 0) { + parent.delete(); + } + } + } + } + contentResolver.delete(WaypointsColumns.CONTENT_URI, WaypointsColumns._ID + "=?", + new String[] { Long.toString(waypointId) }); + } + + @Override + public long getFirstWaypointId(long trackId) { + if (trackId < 0) { + return -1L; + } + Cursor cursor = null; + try { + cursor = getWaypointCursor(new String[] { WaypointsColumns._ID }, + WaypointsColumns.TRACKID + "=?", new String[] { Long.toString(trackId) }, + WaypointsColumns._ID, 1); + if (cursor != null && cursor.moveToFirst()) { + return cursor.getLong(cursor.getColumnIndexOrThrow(WaypointsColumns._ID)); + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + return -1L; + } + + @Override + public Waypoint getLastWaypoint(long trackId, WaypointType waypointType) { + if (trackId < 0) { + return null; + } + Cursor cursor = null; + try { + String selection = WaypointsColumns.TRACKID + "=? AND " + WaypointsColumns.TYPE + "=?"; + String[] selectionArgs = new String[] { + Long.toString(trackId), Integer.toString(waypointType.ordinal()) }; + cursor = getWaypointCursor(null, selection, selectionArgs, WaypointsColumns._ID + " DESC", 1); + if (cursor != null && cursor.moveToFirst()) { + return createWaypoint(cursor); + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + return null; + } + + @Override + public int getNextWaypointNumber(long trackId, WaypointType waypointType) { + if (trackId < 0) { + return -1; + } + Cursor cursor = null; + try { + String[] projection = { WaypointsColumns._ID }; + String selection = WaypointsColumns.TRACKID + "=? AND " + WaypointsColumns.TYPE + "=?"; + String[] selectionArgs = new String[] { + Long.toString(trackId), Integer.toString(waypointType.ordinal()) }; + cursor = getWaypointCursor(projection, selection, selectionArgs, WaypointsColumns._ID, -1); + if (cursor != null) { + int count = cursor.getCount(); + /* + * For statistics markers, the first marker is for the track statistics, + * so return the count as the next user visible number. + */ + return waypointType == WaypointType.STATISTICS ? count : count + 1; + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + return -1; + } + + @Override + public Waypoint getWaypoint(long waypointId) { + if (waypointId < 0) { + return null; + } + Cursor cursor = null; + try { + cursor = getWaypointCursor(null, WaypointsColumns._ID + "=?", + new String[] { Long.toString(waypointId) }, WaypointsColumns._ID, 1); + if (cursor != null && cursor.moveToFirst()) { + return createWaypoint(cursor); + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + return null; + } + + @Override + public Cursor getWaypointCursor( + String selection, String[] selectionArgs, String sortOrder, int maxWaypoints) { + return getWaypointCursor(null, selection, selectionArgs, sortOrder, maxWaypoints); + } + + @Override + public Cursor getWaypointCursor(long trackId, long minWaypointId, int maxWaypoints) { + if (trackId < 0) { + return null; + } + + String selection; + String[] selectionArgs; + if (minWaypointId >= 0) { + selection = WaypointsColumns.TRACKID + "=? AND " + WaypointsColumns._ID + ">=?"; + selectionArgs = new String[] { Long.toString(trackId), Long.toString(minWaypointId) }; + } else { + selection = WaypointsColumns.TRACKID + "=?"; + selectionArgs = new String[] { Long.toString(trackId) }; + } + return getWaypointCursor(null, selection, selectionArgs, WaypointsColumns._ID, maxWaypoints); + } + + @Override + public int getWaypointCount(long trackId) { + if (trackId < 0) { + return 0; + } + + String[] projection = new String[] { "count(*) AS count" }; + String selection = WaypointsColumns.TRACKID + "=?"; + String[] selectionArgs = new String[] { Long.toString(trackId) }; + Cursor cursor = contentResolver.query( + WaypointsColumns.CONTENT_URI, projection, selection, selectionArgs, WaypointsColumns._ID); + + cursor.moveToFirst(); + int count = cursor.getInt(0); + // not count the first waypoint + return count > 0 ? count - 1 : 0; + } + + @Override + public Uri insertWaypoint(Waypoint waypoint) { + waypoint.setId(-1L); + return contentResolver.insert(WaypointsColumns.CONTENT_URI, createContentValues(waypoint)); + } + + @Override + public boolean updateWaypoint(Waypoint waypoint) { + int rows = contentResolver.update(WaypointsColumns.CONTENT_URI, createContentValues(waypoint), + WaypointsColumns._ID + "=?", new String[] { Long.toString(waypoint.getId()) }); + return rows == 1; + } + + ContentValues createContentValues(Waypoint waypoint) { + ContentValues values = new ContentValues(); + + // Value < 0 indicates no id is available + if (waypoint.getId() >= 0) { + values.put(WaypointsColumns._ID, waypoint.getId()); + } + values.put(WaypointsColumns.NAME, waypoint.getName()); + values.put(WaypointsColumns.DESCRIPTION, waypoint.getDescription()); + values.put(WaypointsColumns.CATEGORY, waypoint.getCategory()); + values.put(WaypointsColumns.ICON, waypoint.getIcon()); + values.put(WaypointsColumns.TRACKID, waypoint.getTrackId()); + values.put(WaypointsColumns.TYPE, waypoint.getType().ordinal()); + values.put(WaypointsColumns.LENGTH, waypoint.getLength()); + values.put(WaypointsColumns.DURATION, waypoint.getDuration()); + values.put(WaypointsColumns.STARTID, waypoint.getStartId()); + values.put(WaypointsColumns.STOPID, waypoint.getStopId()); + + Location location = waypoint.getLocation(); + if (location != null) { + values.put(WaypointsColumns.LONGITUDE, (int) (location.getLongitude() * 1E6)); + values.put(WaypointsColumns.LATITUDE, (int) (location.getLatitude() * 1E6)); + values.put(WaypointsColumns.TIME, location.getTime()); + if (location.hasAltitude()) { + values.put(WaypointsColumns.ALTITUDE, location.getAltitude()); + } + if (location.hasAccuracy()) { + values.put(WaypointsColumns.ACCURACY, location.getAccuracy()); + } + if (location.hasSpeed()) { + values.put(WaypointsColumns.SPEED, location.getSpeed()); + } + if (location.hasBearing()) { + values.put(WaypointsColumns.BEARING, location.getBearing()); + } + } + + TripStatistics tripStatistics = waypoint.getTripStatistics(); + if (tripStatistics != null) { + values.put(WaypointsColumns.STARTTIME, tripStatistics.getStartTime()); + values.put(WaypointsColumns.TOTALDISTANCE, tripStatistics.getTotalDistance()); + values.put(WaypointsColumns.TOTALTIME, tripStatistics.getTotalTime()); + values.put(WaypointsColumns.MOVINGTIME, tripStatistics.getMovingTime()); + values.put(WaypointsColumns.AVGSPEED, tripStatistics.getAverageSpeed()); + values.put(WaypointsColumns.AVGMOVINGSPEED, tripStatistics.getAverageMovingSpeed()); + values.put(WaypointsColumns.MAXSPEED, tripStatistics.getMaxSpeed()); + values.put(WaypointsColumns.MINELEVATION, tripStatistics.getMinElevation()); + values.put(WaypointsColumns.MAXELEVATION, tripStatistics.getMaxElevation()); + values.put(WaypointsColumns.ELEVATIONGAIN, tripStatistics.getTotalElevationGain()); + values.put(WaypointsColumns.MINGRADE, tripStatistics.getMinGrade()); + values.put(WaypointsColumns.MAXGRADE, tripStatistics.getMaxGrade()); + values.put(WaypointsColumns.CALORIE, tripStatistics.getCalorie()); + } + + values.put(WaypointsColumns.PHOTOURL, waypoint.getPhotoUrl()); + return values; + } + + private Waypoint getNextStatisticsWaypointAfter(Waypoint waypoint) { + Cursor cursor = null; + try { + String selection = WaypointsColumns._ID + ">? AND " + WaypointsColumns.TRACKID + "=? AND " + + WaypointsColumns.TYPE + "=" + WaypointType.STATISTICS.ordinal(); + String[] selectionArgs = new String[] { + Long.toString(waypoint.getId()), Long.toString(waypoint.getTrackId()) }; + cursor = getWaypointCursor(null, selection, selectionArgs, WaypointsColumns._ID, 1); + if (cursor != null && cursor.moveToFirst()) { + return createWaypoint(cursor); + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + return null; + } + + /** + * Gets a waypoint cursor. + * + * @param projection the projection + * @param selection the selection + * @param selectionArgs the selection args + * @param sortOrder the sort order + * @param maxWaypoints the maximum number of waypoints + */ + private Cursor getWaypointCursor(String[] projection, String selection, String[] selectionArgs, + String sortOrder, int maxWaypoints) { + if (sortOrder == null) { + sortOrder = WaypointsColumns._ID; + } + if (maxWaypoints >= 0) { + sortOrder += " LIMIT " + maxWaypoints; + } + return contentResolver.query( + WaypointsColumns.CONTENT_URI, projection, selection, selectionArgs, sortOrder); + } + + @Override + public int bulkInsertTrackPoint(Location[] locations, int length, long trackId) { + if (length == -1) { + length = locations.length; + } + ContentValues[] values = new ContentValues[length]; + for (int i = 0; i < length; i++) { + values[i] = createContentValues(locations[i], trackId); + } + return contentResolver.bulkInsert(TrackPointsColumns.CONTENT_URI, values); + } + + @Override + public Location createTrackPoint(Cursor cursor) { + Location location = new MyTracksLocation(""); + fillTrackPoint(cursor, new CachedTrackPointsIndexes(cursor), location); + return location; + } + + @Override + public long getFirstTrackPointId(long trackId) { + if (trackId < 0) { + return -1L; + } + Cursor cursor = null; + try { + String selection = TrackPointsColumns._ID + "=(select min(" + TrackPointsColumns._ID + + ") from " + TrackPointsColumns.TABLE_NAME + " WHERE " + TrackPointsColumns.TRACKID + + "=?)"; + String[] selectionArgs = new String[] { Long.toString(trackId) }; + cursor = getTrackPointCursor(new String[] { TrackPointsColumns._ID }, selection, + selectionArgs, TrackPointsColumns._ID); + if (cursor != null && cursor.moveToFirst()) { + return cursor.getLong(cursor.getColumnIndexOrThrow(TrackPointsColumns._ID)); + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + return -1L; + } + + @Override + public long getLastTrackPointId(long trackId) { + if (trackId < 0) { + return -1L; + } + Cursor cursor = null; + try { + String selection = TrackPointsColumns._ID + "=(select max(" + TrackPointsColumns._ID + + ") from " + TrackPointsColumns.TABLE_NAME + " WHERE " + TrackPointsColumns.TRACKID + + "=?)"; + String[] selectionArgs = new String[] { Long.toString(trackId) }; + cursor = getTrackPointCursor(new String[] { TrackPointsColumns._ID }, selection, + selectionArgs, TrackPointsColumns._ID); + if (cursor != null && cursor.moveToFirst()) { + return cursor.getLong(cursor.getColumnIndexOrThrow(TrackPointsColumns._ID)); + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + return -1L; + } + + @Override + public long getTrackPointId(long trackId, Location location) { + if (trackId < 0) { + return -1L; + } + Cursor cursor = null; + try { + String selection = TrackPointsColumns._ID + "=(select max(" + TrackPointsColumns._ID + + ") from " + TrackPointsColumns.TABLE_NAME + " WHERE " + TrackPointsColumns.TRACKID + + "=? AND " + TrackPointsColumns.TIME + "=?)"; + String[] selectionArgs = new String[] { + Long.toString(trackId), Long.toString(location.getTime()) }; + cursor = getTrackPointCursor(new String[] { TrackPointsColumns._ID }, selection, + selectionArgs, TrackPointsColumns._ID); + if (cursor != null && cursor.moveToFirst()) { + return cursor.getLong(cursor.getColumnIndexOrThrow(TrackPointsColumns._ID)); + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + return -1L; + } + + @Override + public Location getFirstValidTrackPoint(long trackId) { + if (trackId < 0) { + return null; + } + String selection = TrackPointsColumns._ID + "=(select min(" + TrackPointsColumns._ID + ") from " + + TrackPointsColumns.TABLE_NAME + " WHERE " + TrackPointsColumns.TRACKID + "=? AND " + + TrackPointsColumns.LATITUDE + "<=" + MAX_LATITUDE + ")"; + String[] selectionArgs = new String[] { Long.toString(trackId) }; + return findTrackPointBy(selection, selectionArgs); + } + + @Override + public Location getLastValidTrackPoint(long trackId) { + if (trackId < 0) { + return null; + } + String selection = TrackPointsColumns._ID + "=(select max(" + TrackPointsColumns._ID + ") from " + + TrackPointsColumns.TABLE_NAME + " WHERE " + TrackPointsColumns.TRACKID + "=? AND " + + TrackPointsColumns.LATITUDE + "<=" + MAX_LATITUDE + ")"; + String[] selectionArgs = new String[] { Long.toString(trackId) }; + return findTrackPointBy(selection, selectionArgs); + } + + @Override + public Location getLastValidTrackPoint() { + String selection = TrackPointsColumns._ID + "=(select max(" + TrackPointsColumns._ID + ") from " + + TrackPointsColumns.TABLE_NAME + " WHERE " + TrackPointsColumns.LATITUDE + "<=" + + MAX_LATITUDE + ")"; + return findTrackPointBy(selection, null); + } + + @Override + public Cursor getTrackPointCursor( + long trackId, long startTrackPointId, int maxLocations, boolean descending) { + if (trackId < 0) { + return null; + } + + String selection; + String[] selectionArgs; + if (startTrackPointId >= 0) { + String comparison = descending ? "<=" : ">="; + selection = TrackPointsColumns.TRACKID + "=? AND " + TrackPointsColumns._ID + comparison + + "?"; + selectionArgs = new String[] { Long.toString(trackId), Long.toString(startTrackPointId) }; + } else { + selection = TrackPointsColumns.TRACKID + "=?"; + selectionArgs = new String[] { Long.toString(trackId) }; + } + + String sortOrder = TrackPointsColumns._ID; + if (descending) { + sortOrder += " DESC"; + } + if (maxLocations >= 0) { + sortOrder += " LIMIT " + maxLocations; + } + return getTrackPointCursor(null, selection, selectionArgs, sortOrder); + } + + @Override + public LocationIterator getTrackPointLocationIterator(final long trackId, + final long startTrackPointId, final boolean descending, + final LocationFactory locationFactory) { + if (locationFactory == null) { + throw new IllegalArgumentException("locationFactory is null"); + } + return new LocationIterator() { + private long lastTrackPointId = -1L; + private Cursor cursor = getCursor(startTrackPointId); + private final CachedTrackPointsIndexes + indexes = cursor != null ? new CachedTrackPointsIndexes(cursor) + : null; + + /** + * Gets the track point cursor. + * + * @param trackPointId the starting track point id + */ + private Cursor getCursor(long trackPointId) { + return getTrackPointCursor(trackId, trackPointId, defaultCursorBatchSize, descending); + } + + /** + * Advances the cursor to the next batch. Returns true if successful. + */ + private boolean advanceCursorToNextBatch() { + long trackPointId = lastTrackPointId == -1L ? -1L + : lastTrackPointId + (descending ? -1 : 1); + Log.d(TAG, "Advancing track point id: " + trackPointId); + cursor.close(); + cursor = getCursor(trackPointId); + return cursor != null; + } + + @Override + public long getLocationId() { + return lastTrackPointId; + } + + @Override + public boolean hasNext() { + if (cursor == null) { + return false; + } + if (cursor.isAfterLast()) { + return false; + } + if (cursor.isLast()) { + if (cursor.getCount() != defaultCursorBatchSize) { + return false; + } + return advanceCursorToNextBatch() && !cursor.isAfterLast(); + } + return true; + } + + @Override + public Location next() { + if (cursor == null) { + throw new NoSuchElementException(); + } + if (!cursor.moveToNext()) { + if (!advanceCursorToNextBatch() || !cursor.moveToNext()) { + throw new NoSuchElementException(); + } + } + lastTrackPointId = cursor.getLong(indexes.idIndex); + Location location = locationFactory.createLocation(); + fillTrackPoint(cursor, indexes, location); + return location; + } + + @Override + public void close() { + if (cursor != null) { + cursor.close(); + cursor = null; + } + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + @Override + public Uri insertTrackPoint(Location location, long trackId) { + return contentResolver.insert( + TrackPointsColumns.CONTENT_URI, createContentValues(location, trackId)); + } + + /** + * Creates the {@link ContentValues} for a {@link Location}. + * + * @param location the location + * @param trackId the track id + */ + private ContentValues createContentValues(Location location, long trackId) { + ContentValues values = new ContentValues(); + values.put(TrackPointsColumns.TRACKID, trackId); + values.put(TrackPointsColumns.LONGITUDE, (int) (location.getLongitude() * 1E6)); + values.put(TrackPointsColumns.LATITUDE, (int) (location.getLatitude() * 1E6)); + + // Hack for Samsung phones that don't properly populate the time field + long time = location.getTime(); + if (time == 0) { + time = System.currentTimeMillis(); + } + values.put(TrackPointsColumns.TIME, time); + if (location.hasAltitude()) { + values.put(TrackPointsColumns.ALTITUDE, location.getAltitude()); + } + if (location.hasAccuracy()) { + values.put(TrackPointsColumns.ACCURACY, location.getAccuracy()); + } + if (location.hasSpeed()) { + values.put(TrackPointsColumns.SPEED, location.getSpeed()); + } + if (location.hasBearing()) { + values.put(TrackPointsColumns.BEARING, location.getBearing()); + } + + if (location instanceof MyTracksLocation) { + MyTracksLocation myTracksLocation = (MyTracksLocation) location; + if (myTracksLocation.getSensorDataSet() != null) { + values.put(TrackPointsColumns.SENSOR, myTracksLocation.getSensorDataSet().toByteArray()); + } + } + return values; + } + + /** + * Fills a track point from a cursor. + * + * @param cursor the cursor pointing to a location. + * @param indexes the cached track points indexes + * @param location the track point + */ + private void fillTrackPoint(Cursor cursor, CachedTrackPointsIndexes indexes, Location location) { + location.reset(); + + if (!cursor.isNull(indexes.longitudeIndex)) { + location.setLongitude(((double) cursor.getInt(indexes.longitudeIndex)) / 1E6); + } + if (!cursor.isNull(indexes.latitudeIndex)) { + location.setLatitude(((double) cursor.getInt(indexes.latitudeIndex)) / 1E6); + } + if (!cursor.isNull(indexes.timeIndex)) { + location.setTime(cursor.getLong(indexes.timeIndex)); + } + if (!cursor.isNull(indexes.altitudeIndex)) { + location.setAltitude(cursor.getFloat(indexes.altitudeIndex)); + } + if (!cursor.isNull(indexes.accuracyIndex)) { + location.setAccuracy(cursor.getFloat(indexes.accuracyIndex)); + } + if (!cursor.isNull(indexes.speedIndex)) { + location.setSpeed(cursor.getFloat(indexes.speedIndex)); + } + if (!cursor.isNull(indexes.bearingIndex)) { + location.setBearing(cursor.getFloat(indexes.bearingIndex)); + } + if (location instanceof MyTracksLocation && !cursor.isNull(indexes.sensorIndex)) { + MyTracksLocation myTracksLocation = (MyTracksLocation) location; + try { + myTracksLocation.setSensorDataSet( + SensorDataSet.parseFrom(cursor.getBlob(indexes.sensorIndex))); + } catch (InvalidProtocolBufferException e) { + Log.w(TAG, "Failed to parse sensor data.", e); + } + } + } + + private Location findTrackPointBy(String selection, String[] selectionArgs) { + Cursor cursor = null; + try { + cursor = getTrackPointCursor(null, selection, selectionArgs, TrackPointsColumns._ID); + if (cursor != null && cursor.moveToNext()) { + return createTrackPoint(cursor); + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + return null; + } + + /** + * Gets a track point cursor. + * + * @param projection the projection + * @param selection the selection + * @param selectionArgs the selection arguments + * @param sortOrder the sort order + */ + private Cursor getTrackPointCursor( + String[] projection, String selection, String[] selectionArgs, String sortOrder) { + return contentResolver.query( + TrackPointsColumns.CONTENT_URI, projection, selection, selectionArgs, sortOrder); + } + + /** + * A cache of track points indexes. + */ + private static class CachedTrackPointsIndexes { + public final int idIndex; + public final int longitudeIndex; + public final int latitudeIndex; + public final int timeIndex; + public final int altitudeIndex; + public final int accuracyIndex; + public final int speedIndex; + public final int bearingIndex; + public final int sensorIndex; + + public CachedTrackPointsIndexes(Cursor cursor) { + idIndex = cursor.getColumnIndex(TrackPointsColumns._ID); + longitudeIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.LONGITUDE); + latitudeIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.LATITUDE); + timeIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.TIME); + altitudeIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.ALTITUDE); + accuracyIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.ACCURACY); + speedIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.SPEED); + bearingIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.BEARING); + sensorIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.SENSOR); + } + } + + /** + * Sets the default cursor batch size. For testing purpose. + * + * @param defaultCursorBatchSize the default cursor batch size + */ + void setDefaultCursorBatchSize(int defaultCursorBatchSize) { + this.defaultCursorBatchSize = defaultCursorBatchSize; + } +} \ No newline at end of file diff --git a/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/Sensor.java b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/Sensor.java new file mode 100644 index 000000000..f564c75f8 --- /dev/null +++ b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/Sensor.java @@ -0,0 +1,883 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: proto/sensor.proto + +package com.google.android.apps.mytracks.content; + +public final class Sensor { + private Sensor() {} + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistryLite registry) { + } + public enum SensorState + implements com.google.protobuf.Internal.EnumLite { + NONE(0, 1), + CONNECTING(1, 2), + CONNECTED(2, 3), + DISCONNECTED(3, 4), + SENDING(4, 5), + ; + + + public final int getNumber() { return value; } + + public static SensorState valueOf(int value) { + switch (value) { + case 1: return NONE; + case 2: return CONNECTING; + case 3: return CONNECTED; + case 4: return DISCONNECTED; + case 5: return SENDING; + default: return null; + } + } + + public static com.google.protobuf.Internal.EnumLiteMap + internalGetValueMap() { + return internalValueMap; + } + private static com.google.protobuf.Internal.EnumLiteMap + internalValueMap = + new com.google.protobuf.Internal.EnumLiteMap() { + public SensorState findValueByNumber(int number) { + return SensorState.valueOf(number) + ; } + }; + + private final int index; + private final int value; + private SensorState(int index, int value) { + this.index = index; + this.value = value; + } + + // @@protoc_insertion_point(enum_scope:com.google.android.apps.mytracks.content.SensorState) + } + + public static final class SensorData extends + com.google.protobuf.GeneratedMessageLite { + // Use SensorData.newBuilder() to construct. + private SensorData() { + initFields(); + } + private SensorData(boolean noInit) {} + + private static final SensorData defaultInstance; + public static SensorData getDefaultInstance() { + return defaultInstance; + } + + public SensorData getDefaultInstanceForType() { + return defaultInstance; + } + + // required .com.google.android.apps.mytracks.content.SensorState state = 1 [default = NONE]; + public static final int STATE_FIELD_NUMBER = 1; + private boolean hasState; + private com.google.android.apps.mytracks.content.Sensor.SensorState state_; + public boolean hasState() { return hasState; } + public com.google.android.apps.mytracks.content.Sensor.SensorState getState() { return state_; } + + // optional int32 value = 2; + public static final int VALUE_FIELD_NUMBER = 2; + private boolean hasValue; + private int value_ = 0; + public boolean hasValue() { return hasValue; } + public int getValue() { return value_; } + + private void initFields() { + state_ = com.google.android.apps.mytracks.content.Sensor.SensorState.NONE; + } + public final boolean isInitialized() { + if (!hasState) return false; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasState()) { + output.writeEnum(1, getState().getNumber()); + } + if (hasValue()) { + output.writeInt32(2, getValue()); + } + } + + private int memoizedSerializedSize = -1; + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasState()) { + size += com.google.protobuf.CodedOutputStream + .computeEnumSize(1, getState().getNumber()); + } + if (hasValue()) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(2, getValue()); + } + memoizedSerializedSize = size; + return size; + } + + public static com.google.android.apps.mytracks.content.Sensor.SensorData parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static com.google.android.apps.mytracks.content.Sensor.SensorData parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static com.google.android.apps.mytracks.content.Sensor.SensorData parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static com.google.android.apps.mytracks.content.Sensor.SensorData parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static com.google.android.apps.mytracks.content.Sensor.SensorData parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static com.google.android.apps.mytracks.content.Sensor.SensorData parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static com.google.android.apps.mytracks.content.Sensor.SensorData parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static com.google.android.apps.mytracks.content.Sensor.SensorData parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static com.google.android.apps.mytracks.content.Sensor.SensorData parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static com.google.android.apps.mytracks.content.Sensor.SensorData parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(com.google.android.apps.mytracks.content.Sensor.SensorData prototype) { + return newBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessageLite.Builder< + com.google.android.apps.mytracks.content.Sensor.SensorData, Builder> { + private com.google.android.apps.mytracks.content.Sensor.SensorData result; + + // Construct using com.google.android.apps.mytracks.content.Sensor.SensorData.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new com.google.android.apps.mytracks.content.Sensor.SensorData(); + return builder; + } + + protected com.google.android.apps.mytracks.content.Sensor.SensorData internalGetResult() { + return result; + } + + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new com.google.android.apps.mytracks.content.Sensor.SensorData(); + return this; + } + + public Builder clone() { + return create().mergeFrom(result); + } + + public com.google.android.apps.mytracks.content.Sensor.SensorData getDefaultInstanceForType() { + return com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance(); + } + + public boolean isInitialized() { + return result.isInitialized(); + } + public com.google.android.apps.mytracks.content.Sensor.SensorData build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private com.google.android.apps.mytracks.content.Sensor.SensorData buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + public com.google.android.apps.mytracks.content.Sensor.SensorData buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + com.google.android.apps.mytracks.content.Sensor.SensorData returnMe = result; + result = null; + return returnMe; + } + + public Builder mergeFrom(com.google.android.apps.mytracks.content.Sensor.SensorData other) { + if (other == com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance()) return this; + if (other.hasState()) { + setState(other.getState()); + } + if (other.hasValue()) { + setValue(other.getValue()); + } + return this; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + return this; + default: { + if (!parseUnknownField(input, extensionRegistry, tag)) { + return this; + } + break; + } + case 8: { + int rawValue = input.readEnum(); + com.google.android.apps.mytracks.content.Sensor.SensorState value = com.google.android.apps.mytracks.content.Sensor.SensorState.valueOf(rawValue); + if (value != null) { + setState(value); + } + break; + } + case 16: { + setValue(input.readInt32()); + break; + } + } + } + } + + + // required .com.google.android.apps.mytracks.content.SensorState state = 1 [default = NONE]; + public boolean hasState() { + return result.hasState(); + } + public com.google.android.apps.mytracks.content.Sensor.SensorState getState() { + return result.getState(); + } + public Builder setState(com.google.android.apps.mytracks.content.Sensor.SensorState value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasState = true; + result.state_ = value; + return this; + } + public Builder clearState() { + result.hasState = false; + result.state_ = com.google.android.apps.mytracks.content.Sensor.SensorState.NONE; + return this; + } + + // optional int32 value = 2; + public boolean hasValue() { + return result.hasValue(); + } + public int getValue() { + return result.getValue(); + } + public Builder setValue(int value) { + result.hasValue = true; + result.value_ = value; + return this; + } + public Builder clearValue() { + result.hasValue = false; + result.value_ = 0; + return this; + } + + // @@protoc_insertion_point(builder_scope:com.google.android.apps.mytracks.content.SensorData) + } + + static { + defaultInstance = new SensorData(true); + com.google.android.apps.mytracks.content.Sensor.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:com.google.android.apps.mytracks.content.SensorData) + } + + public static final class SensorDataSet extends + com.google.protobuf.GeneratedMessageLite { + // Use SensorDataSet.newBuilder() to construct. + private SensorDataSet() { + initFields(); + } + private SensorDataSet(boolean noInit) {} + + private static final SensorDataSet defaultInstance; + public static SensorDataSet getDefaultInstance() { + return defaultInstance; + } + + public SensorDataSet getDefaultInstanceForType() { + return defaultInstance; + } + + // optional uint64 creation_time = 1 [default = 0]; + public static final int CREATION_TIME_FIELD_NUMBER = 1; + private boolean hasCreationTime; + private long creationTime_ = 0L; + public boolean hasCreationTime() { return hasCreationTime; } + public long getCreationTime() { return creationTime_; } + + // optional .com.google.android.apps.mytracks.content.SensorData heart_rate = 2; + public static final int HEART_RATE_FIELD_NUMBER = 2; + private boolean hasHeartRate; + private com.google.android.apps.mytracks.content.Sensor.SensorData heartRate_; + public boolean hasHeartRate() { return hasHeartRate; } + public com.google.android.apps.mytracks.content.Sensor.SensorData getHeartRate() { return heartRate_; } + + // optional .com.google.android.apps.mytracks.content.SensorData cadence = 3; + public static final int CADENCE_FIELD_NUMBER = 3; + private boolean hasCadence; + private com.google.android.apps.mytracks.content.Sensor.SensorData cadence_; + public boolean hasCadence() { return hasCadence; } + public com.google.android.apps.mytracks.content.Sensor.SensorData getCadence() { return cadence_; } + + // optional .com.google.android.apps.mytracks.content.SensorData power = 4; + public static final int POWER_FIELD_NUMBER = 4; + private boolean hasPower; + private com.google.android.apps.mytracks.content.Sensor.SensorData power_; + public boolean hasPower() { return hasPower; } + public com.google.android.apps.mytracks.content.Sensor.SensorData getPower() { return power_; } + + // optional .com.google.android.apps.mytracks.content.SensorData battery_level = 5; + public static final int BATTERY_LEVEL_FIELD_NUMBER = 5; + private boolean hasBatteryLevel; + private com.google.android.apps.mytracks.content.Sensor.SensorData batteryLevel_; + public boolean hasBatteryLevel() { return hasBatteryLevel; } + public com.google.android.apps.mytracks.content.Sensor.SensorData getBatteryLevel() { return batteryLevel_; } + + private void initFields() { + heartRate_ = com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance(); + cadence_ = com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance(); + power_ = com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance(); + batteryLevel_ = com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance(); + } + public final boolean isInitialized() { + if (hasHeartRate()) { + if (!getHeartRate().isInitialized()) return false; + } + if (hasCadence()) { + if (!getCadence().isInitialized()) return false; + } + if (hasPower()) { + if (!getPower().isInitialized()) return false; + } + if (hasBatteryLevel()) { + if (!getBatteryLevel().isInitialized()) return false; + } + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasCreationTime()) { + output.writeUInt64(1, getCreationTime()); + } + if (hasHeartRate()) { + output.writeMessage(2, getHeartRate()); + } + if (hasCadence()) { + output.writeMessage(3, getCadence()); + } + if (hasPower()) { + output.writeMessage(4, getPower()); + } + if (hasBatteryLevel()) { + output.writeMessage(5, getBatteryLevel()); + } + } + + private int memoizedSerializedSize = -1; + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasCreationTime()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt64Size(1, getCreationTime()); + } + if (hasHeartRate()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(2, getHeartRate()); + } + if (hasCadence()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, getCadence()); + } + if (hasPower()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, getPower()); + } + if (hasBatteryLevel()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, getBatteryLevel()); + } + memoizedSerializedSize = size; + return size; + } + + public static com.google.android.apps.mytracks.content.Sensor.SensorDataSet parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static com.google.android.apps.mytracks.content.Sensor.SensorDataSet parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static com.google.android.apps.mytracks.content.Sensor.SensorDataSet parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static com.google.android.apps.mytracks.content.Sensor.SensorDataSet parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static com.google.android.apps.mytracks.content.Sensor.SensorDataSet parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static com.google.android.apps.mytracks.content.Sensor.SensorDataSet parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static com.google.android.apps.mytracks.content.Sensor.SensorDataSet parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static com.google.android.apps.mytracks.content.Sensor.SensorDataSet parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static com.google.android.apps.mytracks.content.Sensor.SensorDataSet parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static com.google.android.apps.mytracks.content.Sensor.SensorDataSet parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(com.google.android.apps.mytracks.content.Sensor.SensorDataSet prototype) { + return newBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessageLite.Builder< + com.google.android.apps.mytracks.content.Sensor.SensorDataSet, Builder> { + private com.google.android.apps.mytracks.content.Sensor.SensorDataSet result; + + // Construct using com.google.android.apps.mytracks.content.Sensor.SensorDataSet.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new com.google.android.apps.mytracks.content.Sensor.SensorDataSet(); + return builder; + } + + protected com.google.android.apps.mytracks.content.Sensor.SensorDataSet internalGetResult() { + return result; + } + + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new com.google.android.apps.mytracks.content.Sensor.SensorDataSet(); + return this; + } + + public Builder clone() { + return create().mergeFrom(result); + } + + public com.google.android.apps.mytracks.content.Sensor.SensorDataSet getDefaultInstanceForType() { + return com.google.android.apps.mytracks.content.Sensor.SensorDataSet.getDefaultInstance(); + } + + public boolean isInitialized() { + return result.isInitialized(); + } + public com.google.android.apps.mytracks.content.Sensor.SensorDataSet build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private com.google.android.apps.mytracks.content.Sensor.SensorDataSet buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + public com.google.android.apps.mytracks.content.Sensor.SensorDataSet buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + com.google.android.apps.mytracks.content.Sensor.SensorDataSet returnMe = result; + result = null; + return returnMe; + } + + public Builder mergeFrom(com.google.android.apps.mytracks.content.Sensor.SensorDataSet other) { + if (other == com.google.android.apps.mytracks.content.Sensor.SensorDataSet.getDefaultInstance()) return this; + if (other.hasCreationTime()) { + setCreationTime(other.getCreationTime()); + } + if (other.hasHeartRate()) { + mergeHeartRate(other.getHeartRate()); + } + if (other.hasCadence()) { + mergeCadence(other.getCadence()); + } + if (other.hasPower()) { + mergePower(other.getPower()); + } + if (other.hasBatteryLevel()) { + mergeBatteryLevel(other.getBatteryLevel()); + } + return this; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + return this; + default: { + if (!parseUnknownField(input, extensionRegistry, tag)) { + return this; + } + break; + } + case 8: { + setCreationTime(input.readUInt64()); + break; + } + case 18: { + com.google.android.apps.mytracks.content.Sensor.SensorData.Builder subBuilder = com.google.android.apps.mytracks.content.Sensor.SensorData.newBuilder(); + if (hasHeartRate()) { + subBuilder.mergeFrom(getHeartRate()); + } + input.readMessage(subBuilder, extensionRegistry); + setHeartRate(subBuilder.buildPartial()); + break; + } + case 26: { + com.google.android.apps.mytracks.content.Sensor.SensorData.Builder subBuilder = com.google.android.apps.mytracks.content.Sensor.SensorData.newBuilder(); + if (hasCadence()) { + subBuilder.mergeFrom(getCadence()); + } + input.readMessage(subBuilder, extensionRegistry); + setCadence(subBuilder.buildPartial()); + break; + } + case 34: { + com.google.android.apps.mytracks.content.Sensor.SensorData.Builder subBuilder = com.google.android.apps.mytracks.content.Sensor.SensorData.newBuilder(); + if (hasPower()) { + subBuilder.mergeFrom(getPower()); + } + input.readMessage(subBuilder, extensionRegistry); + setPower(subBuilder.buildPartial()); + break; + } + case 42: { + com.google.android.apps.mytracks.content.Sensor.SensorData.Builder subBuilder = com.google.android.apps.mytracks.content.Sensor.SensorData.newBuilder(); + if (hasBatteryLevel()) { + subBuilder.mergeFrom(getBatteryLevel()); + } + input.readMessage(subBuilder, extensionRegistry); + setBatteryLevel(subBuilder.buildPartial()); + break; + } + } + } + } + + + // optional uint64 creation_time = 1 [default = 0]; + public boolean hasCreationTime() { + return result.hasCreationTime(); + } + public long getCreationTime() { + return result.getCreationTime(); + } + public Builder setCreationTime(long value) { + result.hasCreationTime = true; + result.creationTime_ = value; + return this; + } + public Builder clearCreationTime() { + result.hasCreationTime = false; + result.creationTime_ = 0L; + return this; + } + + // optional .com.google.android.apps.mytracks.content.SensorData heart_rate = 2; + public boolean hasHeartRate() { + return result.hasHeartRate(); + } + public com.google.android.apps.mytracks.content.Sensor.SensorData getHeartRate() { + return result.getHeartRate(); + } + public Builder setHeartRate(com.google.android.apps.mytracks.content.Sensor.SensorData value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasHeartRate = true; + result.heartRate_ = value; + return this; + } + public Builder setHeartRate(com.google.android.apps.mytracks.content.Sensor.SensorData.Builder builderForValue) { + result.hasHeartRate = true; + result.heartRate_ = builderForValue.build(); + return this; + } + public Builder mergeHeartRate(com.google.android.apps.mytracks.content.Sensor.SensorData value) { + if (result.hasHeartRate() && + result.heartRate_ != com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance()) { + result.heartRate_ = + com.google.android.apps.mytracks.content.Sensor.SensorData.newBuilder(result.heartRate_).mergeFrom(value).buildPartial(); + } else { + result.heartRate_ = value; + } + result.hasHeartRate = true; + return this; + } + public Builder clearHeartRate() { + result.hasHeartRate = false; + result.heartRate_ = com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance(); + return this; + } + + // optional .com.google.android.apps.mytracks.content.SensorData cadence = 3; + public boolean hasCadence() { + return result.hasCadence(); + } + public com.google.android.apps.mytracks.content.Sensor.SensorData getCadence() { + return result.getCadence(); + } + public Builder setCadence(com.google.android.apps.mytracks.content.Sensor.SensorData value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasCadence = true; + result.cadence_ = value; + return this; + } + public Builder setCadence(com.google.android.apps.mytracks.content.Sensor.SensorData.Builder builderForValue) { + result.hasCadence = true; + result.cadence_ = builderForValue.build(); + return this; + } + public Builder mergeCadence(com.google.android.apps.mytracks.content.Sensor.SensorData value) { + if (result.hasCadence() && + result.cadence_ != com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance()) { + result.cadence_ = + com.google.android.apps.mytracks.content.Sensor.SensorData.newBuilder(result.cadence_).mergeFrom(value).buildPartial(); + } else { + result.cadence_ = value; + } + result.hasCadence = true; + return this; + } + public Builder clearCadence() { + result.hasCadence = false; + result.cadence_ = com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance(); + return this; + } + + // optional .com.google.android.apps.mytracks.content.SensorData power = 4; + public boolean hasPower() { + return result.hasPower(); + } + public com.google.android.apps.mytracks.content.Sensor.SensorData getPower() { + return result.getPower(); + } + public Builder setPower(com.google.android.apps.mytracks.content.Sensor.SensorData value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasPower = true; + result.power_ = value; + return this; + } + public Builder setPower(com.google.android.apps.mytracks.content.Sensor.SensorData.Builder builderForValue) { + result.hasPower = true; + result.power_ = builderForValue.build(); + return this; + } + public Builder mergePower(com.google.android.apps.mytracks.content.Sensor.SensorData value) { + if (result.hasPower() && + result.power_ != com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance()) { + result.power_ = + com.google.android.apps.mytracks.content.Sensor.SensorData.newBuilder(result.power_).mergeFrom(value).buildPartial(); + } else { + result.power_ = value; + } + result.hasPower = true; + return this; + } + public Builder clearPower() { + result.hasPower = false; + result.power_ = com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance(); + return this; + } + + // optional .com.google.android.apps.mytracks.content.SensorData battery_level = 5; + public boolean hasBatteryLevel() { + return result.hasBatteryLevel(); + } + public com.google.android.apps.mytracks.content.Sensor.SensorData getBatteryLevel() { + return result.getBatteryLevel(); + } + public Builder setBatteryLevel(com.google.android.apps.mytracks.content.Sensor.SensorData value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasBatteryLevel = true; + result.batteryLevel_ = value; + return this; + } + public Builder setBatteryLevel(com.google.android.apps.mytracks.content.Sensor.SensorData.Builder builderForValue) { + result.hasBatteryLevel = true; + result.batteryLevel_ = builderForValue.build(); + return this; + } + public Builder mergeBatteryLevel(com.google.android.apps.mytracks.content.Sensor.SensorData value) { + if (result.hasBatteryLevel() && + result.batteryLevel_ != com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance()) { + result.batteryLevel_ = + com.google.android.apps.mytracks.content.Sensor.SensorData.newBuilder(result.batteryLevel_).mergeFrom(value).buildPartial(); + } else { + result.batteryLevel_ = value; + } + result.hasBatteryLevel = true; + return this; + } + public Builder clearBatteryLevel() { + result.hasBatteryLevel = false; + result.batteryLevel_ = com.google.android.apps.mytracks.content.Sensor.SensorData.getDefaultInstance(); + return this; + } + + // @@protoc_insertion_point(builder_scope:com.google.android.apps.mytracks.content.SensorDataSet) + } + + static { + defaultInstance = new SensorDataSet(true); + com.google.android.apps.mytracks.content.Sensor.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:com.google.android.apps.mytracks.content.SensorDataSet) + } + + + static { + } + + public static void internalForceInit() {} + + // @@protoc_insertion_point(outer_class_scope) +} diff --git a/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/Track.java b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/Track.java new file mode 100644 index 000000000..195d2f99d --- /dev/null +++ b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/Track.java @@ -0,0 +1,236 @@ +/* + * 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.content; + +import com.google.android.apps.mytracks.stats.TripStatistics; + +import android.location.Location; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.ArrayList; + +/** + * A track. + * + * @author Leif Hendrik Wilden + * @author Rodrigo Damazio + */ +public class Track implements Parcelable { + + private long id = -1L; + private String name = ""; + private String description = ""; + private String category = ""; + private long startId = -1L; + private long stopId = -1L; + + /* + * The number of location points (present even if the points themselves are + * not loaded) + */ + private int numberOfPoints = 0; + private String icon = ""; + private String driveId = ""; + private long modifiedTime = -1L; + private boolean sharedWithMe = false; + private String sharedOwner = ""; + + private TripStatistics tripStatistics = new TripStatistics(); + + // Location points (which may not have been loaded) + private ArrayList locations = new ArrayList(); + + public Track() {} + + private Track(Parcel in) { + id = in.readLong(); + name = in.readString(); + description = in.readString(); + category = in.readString(); + startId = in.readLong(); + stopId = in.readLong(); + numberOfPoints = in.readInt(); + icon = in.readString(); + driveId = in.readString(); + modifiedTime = in.readLong(); + sharedWithMe = in.readByte() == 1; + sharedOwner = in.readString(); + + ClassLoader classLoader = getClass().getClassLoader(); + tripStatistics = in.readParcelable(classLoader); + + for (int i = 0; i < numberOfPoints; ++i) { + Location location = in.readParcelable(classLoader); + locations.add(location); + } + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeLong(id); + dest.writeString(name); + dest.writeString(description); + dest.writeString(category); + dest.writeLong(startId); + dest.writeLong(stopId); + dest.writeInt(numberOfPoints); + dest.writeString(icon); + dest.writeString(driveId); + dest.writeLong(modifiedTime); + dest.writeByte((byte) (sharedWithMe ? 1 : 0)); + dest.writeString(sharedOwner); + + dest.writeParcelable(tripStatistics, 0); + for (int i = 0; i < numberOfPoints; ++i) { + dest.writeParcelable(locations.get(i), 0); + } + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override + public Track createFromParcel(Parcel in) { + return new Track(in); + } + + @Override + public Track[] newArray(int size) { + return new Track[size]; + } + }; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + public long getStartId() { + return startId; + } + + public void setStartId(long startId) { + this.startId = startId; + } + + public long getStopId() { + return stopId; + } + + public void setStopId(long stopId) { + this.stopId = stopId; + } + + public int getNumberOfPoints() { + return numberOfPoints; + } + + public void setNumberOfPoints(int numberOfPoints) { + this.numberOfPoints = numberOfPoints; + } + + public String getIcon() { + return icon; + } + + public void setIcon(String icon) { + this.icon = icon; + } + + public String getDriveId() { + return driveId; + } + + public void setDriveId(String driveId) { + this.driveId = driveId; + } + + public long getModifiedTime() { + return modifiedTime; + } + + public void setModifiedTime(long modifiedTime) { + this.modifiedTime = modifiedTime; + } + + public boolean isSharedWithMe() { + return sharedWithMe; + } + + public void setSharedWithMe(boolean sharedWithMe) { + this.sharedWithMe = sharedWithMe; + } + + public String getSharedOwner() { + return sharedOwner; + } + + public void setSharedOwner(String sharedOwner) { + this.sharedOwner = sharedOwner; + } + + public TripStatistics getTripStatistics() { + return tripStatistics; + } + + public void setTripStatistics(TripStatistics tripStatistics) { + this.tripStatistics = tripStatistics; + } + + public void addLocation(Location location) { + locations.add(location); + } + + public ArrayList getLocations() { + return locations; + } + + public void setLocations(ArrayList locations) { + this.locations = locations; + } +} diff --git a/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/TrackPointsColumns.java b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/TrackPointsColumns.java new file mode 100644 index 000000000..bac0f62c4 --- /dev/null +++ b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/TrackPointsColumns.java @@ -0,0 +1,90 @@ +/* + * 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.content; + +import static com.google.android.apps.mytracks.content.ContentTypeIds.BLOB_TYPE_ID; +import static com.google.android.apps.mytracks.content.ContentTypeIds.FLOAT_TYPE_ID; +import static com.google.android.apps.mytracks.content.ContentTypeIds.INT_TYPE_ID; +import static com.google.android.apps.mytracks.content.ContentTypeIds.LONG_TYPE_ID; + +import android.net.Uri; +import android.provider.BaseColumns; + +/** + * Constants for the track points table. + * + * @author Leif Hendrik Wilden + */ +public interface TrackPointsColumns extends BaseColumns { + + public static final String TABLE_NAME = "trackpoints"; + public static final Uri CONTENT_URI = Uri.parse( + "content://com.google.android.maps.mytracks/trackpoints"); + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.google.trackpoint"; + public static final String CONTENT_ITEMTYPE = "vnd.android.cursor.item/vnd.google.trackpoint"; + public static final String DEFAULT_SORT_ORDER = "_id"; + + // Columns + public static final String TRACKID = "trackid"; // track id + public static final String LONGITUDE = "longitude"; // longitude + public static final String LATITUDE = "latitude"; // latitude + public static final String TIME = "time"; // time + public static final String ALTITUDE = "elevation"; // altitude + public static final String ACCURACY = "accuracy"; // accuracy + public static final String SPEED = "speed"; // speed + public static final String BEARING = "bearing"; // bearing + public static final String SENSOR = "sensor"; // sensor + + public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + + _ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + + TRACKID + " INTEGER, " + + LONGITUDE + " INTEGER, " + + LATITUDE + " INTEGER, " + + TIME + " INTEGER, " + + ALTITUDE + " FLOAT, " + + ACCURACY + " FLOAT, " + + SPEED + " FLOAT, " + + BEARING + " FLOAT, " + + SENSOR + " BLOB" + + ");"; + + public static final String[] COLUMNS = { + _ID, + TRACKID, + LONGITUDE, + LATITUDE, + TIME, + ALTITUDE, + ACCURACY, + SPEED, + BEARING, + SENSOR + }; + + public static final byte[] COLUMN_TYPES = { + LONG_TYPE_ID, // id + LONG_TYPE_ID, // track id + INT_TYPE_ID, // longitude + INT_TYPE_ID, // latitude + LONG_TYPE_ID, // time + FLOAT_TYPE_ID, // altitude + FLOAT_TYPE_ID, // accuracy + FLOAT_TYPE_ID, // speed + FLOAT_TYPE_ID, // bearing + BLOB_TYPE_ID // sensor + }; +} diff --git a/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/TracksColumns.java b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/TracksColumns.java new file mode 100644 index 000000000..f2e50102a --- /dev/null +++ b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/TracksColumns.java @@ -0,0 +1,195 @@ +/* + * 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.content; + +import android.net.Uri; +import android.provider.BaseColumns; + +/** + * Constants for the tracks table. + * + * @author Leif Hendrik Wilden + */ +public interface TracksColumns extends BaseColumns { + + public static final String TABLE_NAME = "tracks"; + + /** + * Tracks provider uri. + */ + public static final Uri CONTENT_URI = Uri.parse( + "content://com.google.android.maps.mytracks/tracks"); + + /** + * Track content type. + */ + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.google.track"; + + /** + * Track id content type. + */ + public static final String CONTENT_ITEMTYPE = "vnd.android.cursor.item/vnd.google.track"; + + /** + * Tracks table default sort order. + */ + public static final String DEFAULT_SORT_ORDER = "_id"; + + // Columns + public static final String NAME = "name"; // track name + public static final String DESCRIPTION = "description"; // track description + public static final String CATEGORY = "category"; // track activity type + public static final String STARTID = "startid"; // first track point id + public static final String STOPID = "stopid"; // last track point id + public static final String STARTTIME = "starttime"; // track start time + public static final String STOPTIME = "stoptime"; // track stop time + public static final String NUMPOINTS = "numpoints"; // number of track points + public static final String TOTALDISTANCE = "totaldistance"; // total distance + public static final String TOTALTIME = "totaltime"; // total time + public static final String MOVINGTIME = "movingtime"; // moving time + public static final String MINLAT = "minlat"; // minimum latitude + public static final String MAXLAT = "maxlat"; // maximum latitude + public static final String MINLON = "minlon"; // minimum longitude + public static final String MAXLON = "maxlon"; // maximum longitude + public static final String AVGSPEED = "avgspeed"; // average speed + + // average moving speed + public static final String AVGMOVINGSPEED = "avgmovingspeed"; + public static final String MAXSPEED = "maxspeed"; // maximum speed + public static final String MINELEVATION = "minelevation"; // minimum elevation + public static final String MAXELEVATION = "maxelevation"; // maximum elevation + public static final String ELEVATIONGAIN = "elevationgain"; // elevation gain + public static final String MINGRADE = "mingrade"; // minimum grade + public static final String MAXGRADE = "maxgrade"; // maximum grade + public static final String MAPID = "mapid"; // Google Maps id + public static final String TABLEID = "tableid"; // Google Fusion Tables id + public static final String ICON = "icon"; // track activity type icon + public static final String DRIVEID = "driveid"; // Google Drive file id + + // Google drive file modified time + public static final String MODIFIEDTIME = "modifiedtime"; + + // 1 if the Google Drive file is from the "Shared with me" directory + public static final String SHAREDWITHME = "sharedwithme"; + + // The owner of the shared with me track + public static final String SHAREDOWNER = "sharedOwner"; + + // Calorie burned of the track + public static final String CALORIE = "calorie"; + + public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" // table + + _ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " // id + + NAME + " STRING, " // name + + DESCRIPTION + " STRING, " // description + + CATEGORY + " STRING, " // category + + STARTID + " INTEGER, " // start id + + STOPID + " INTEGER, " // stop id + + STARTTIME + " INTEGER, " // start time + + STOPTIME + " INTEGER, " // stop time + + NUMPOINTS + " INTEGER, " // num points + + TOTALDISTANCE + " FLOAT, " // total distance + + TOTALTIME + " INTEGER, " // total time + + MOVINGTIME + " INTEGER, " // moving time + + MINLAT + " INTEGER, " // min latitude + + MAXLAT + " INTEGER, " // max latitude + + MINLON + " INTEGER, " // min longitude + + MAXLON + " INTEGER, " // max longitude + + AVGSPEED + " FLOAT, " // average speed + + AVGMOVINGSPEED + " FLOAT, " // average moving speed + + MAXSPEED + " FLOAT, " // max speed + + MINELEVATION + " FLOAT, " // min elevation + + MAXELEVATION + " FLOAT, " // max elevation + + ELEVATIONGAIN + " FLOAT, " // elevation gain + + MINGRADE + " FLOAT, " // min grade + + MAXGRADE + " FLOAT, " // max grade + + MAPID + " STRING, " // map id + + TABLEID + " STRING, " // table id + + ICON + " STRING, " // icon + + DRIVEID + " STRING, " // drive id + + MODIFIEDTIME + " INTEGER, " // modified time + + SHAREDWITHME + " INTEGER, " // shared with me + + SHAREDOWNER + " STRING, " // shared owner + + CALORIE + " FLOAT);"; // calorie + + public static final String[] COLUMNS = { _ID, // id + NAME, // name + DESCRIPTION, // description + CATEGORY, // category + STARTID, // start id + STOPID, // stop id + STARTTIME, // start time + STOPTIME, // stop time + NUMPOINTS, // num points + TOTALDISTANCE, // total distance + TOTALTIME, // total time + MOVINGTIME, // moving time + MINLAT, // min latitude + MAXLAT, // max latitude + MINLON, // min longitude + MAXLON, // max longitude + AVGSPEED, // average speed + AVGMOVINGSPEED, // average moving speed + MAXSPEED, // max speed + MINELEVATION, // min elevation + MAXELEVATION, // max elevation + ELEVATIONGAIN, // elevation gain + MINGRADE, // min grade + MAXGRADE, // max grade + MAPID, // map id + TABLEID, // table id + ICON, // icon + DRIVEID, // drive id + MODIFIEDTIME, // modified time + SHAREDWITHME, // shared with me + SHAREDOWNER,// shared owner + CALORIE }; // calorie + + public static final byte[] COLUMN_TYPES = { ContentTypeIds.LONG_TYPE_ID, // id + ContentTypeIds.STRING_TYPE_ID, // name + ContentTypeIds.STRING_TYPE_ID, // description + ContentTypeIds.STRING_TYPE_ID, // category + ContentTypeIds.LONG_TYPE_ID, // start id + ContentTypeIds.LONG_TYPE_ID, // stop id + ContentTypeIds.LONG_TYPE_ID, // start time + ContentTypeIds.LONG_TYPE_ID, // stop time + ContentTypeIds.INT_TYPE_ID, // num points + ContentTypeIds.FLOAT_TYPE_ID, // total distance + ContentTypeIds.LONG_TYPE_ID, // total time + ContentTypeIds.LONG_TYPE_ID, // moving time + ContentTypeIds.INT_TYPE_ID, // min latitude + ContentTypeIds.INT_TYPE_ID, // max latitude + ContentTypeIds.INT_TYPE_ID, // min longitude + ContentTypeIds.INT_TYPE_ID, // max longitude + ContentTypeIds.FLOAT_TYPE_ID, // average speed + ContentTypeIds.FLOAT_TYPE_ID, // average moving speed + ContentTypeIds.FLOAT_TYPE_ID, // max speed + ContentTypeIds.FLOAT_TYPE_ID, // min elevation + ContentTypeIds.FLOAT_TYPE_ID, // max elevation + ContentTypeIds.FLOAT_TYPE_ID, // elevation gain + ContentTypeIds.FLOAT_TYPE_ID, // min grade + ContentTypeIds.FLOAT_TYPE_ID, // max grade + ContentTypeIds.STRING_TYPE_ID, // map id + ContentTypeIds.STRING_TYPE_ID, // table id + ContentTypeIds.STRING_TYPE_ID, // icon + ContentTypeIds.STRING_TYPE_ID, // drive id + ContentTypeIds.LONG_TYPE_ID, // modified time + ContentTypeIds.BOOLEAN_TYPE_ID, // shared with me + ContentTypeIds.STRING_TYPE_ID, // shared owner + ContentTypeIds.FLOAT_TYPE_ID // calorie + }; +} diff --git a/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/Waypoint.java b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/Waypoint.java new file mode 100644 index 000000000..dad2be246 --- /dev/null +++ b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/Waypoint.java @@ -0,0 +1,249 @@ +/* + * 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 + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.android.apps.mytracks.content; + +import com.google.android.apps.mytracks.stats.TripStatistics; + +import android.location.Location; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * A waypoint. + * + * @author Leif Hendrik Wilden + * @author Rodrigo Damazio + */ +public final class Waypoint implements Parcelable { + + public static enum WaypointType { + WAYPOINT, STATISTICS; + } + + private long id = -1L; + private String name = ""; + private String description = ""; + private String category = ""; + private String icon = ""; + private long trackId = -1L; + private WaypointType type = WaypointType.WAYPOINT; + private double length = 0.0; + private long duration = 0; + private long startId = -1L; + private long stopId = -1L; + private Location location = null; + private TripStatistics tripStatistics = null; + private String photoUrl = ""; + + public Waypoint() {} + + public Waypoint(String name, String description, String category, String icon, long trackId, + WaypointType type, double length, long duration, long startId, long stopId, Location location, + TripStatistics tripStatistics, String photoUrl) { + this.name = name; + this.description = description; + this.category = category; + this.icon = icon; + this.trackId = trackId; + this.type = type; + this.length = length; + this.duration = duration; + this.startId = startId; + this.stopId = stopId; + this.location = location; + this.tripStatistics = tripStatistics; + this.photoUrl = photoUrl; + } + + private Waypoint(Parcel source) { + id = source.readLong(); + name = source.readString(); + description = source.readString(); + category = source.readString(); + icon = source.readString(); + trackId = source.readLong(); + type = WaypointType.values()[source.readInt()]; + length = source.readDouble(); + duration = source.readLong(); + startId = source.readLong(); + stopId = source.readLong(); + + ClassLoader classLoader = getClass().getClassLoader(); + byte hasLocation = source.readByte(); + if (hasLocation > 0) { + location = source.readParcelable(classLoader); + } + byte hasStats = source.readByte(); + if (hasStats > 0) { + tripStatistics = source.readParcelable(classLoader); + } + photoUrl = source.readString(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeLong(id); + dest.writeString(name); + dest.writeString(description); + dest.writeString(category); + dest.writeString(icon); + dest.writeLong(trackId); + dest.writeInt(type.ordinal()); + dest.writeDouble(length); + dest.writeLong(duration); + dest.writeLong(startId); + dest.writeLong(stopId); + dest.writeByte(location == null ? (byte) 0 : (byte) 1); + if (location != null) { + dest.writeParcelable(location, 0); + } + dest.writeByte(tripStatistics == null ? (byte) 0 : (byte) 1); + if (tripStatistics != null) { + dest.writeParcelable(tripStatistics, 0); + } + dest.writeString(photoUrl); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override + public Waypoint createFromParcel(Parcel in) { + return new Waypoint(in); + } + + @Override + public Waypoint[] newArray(int size) { + return new Waypoint[size]; + } + }; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + public String getIcon() { + return icon; + } + + public void setIcon(String icon) { + this.icon = icon; + } + + public long getTrackId() { + return trackId; + } + + public void setTrackId(long trackId) { + this.trackId = trackId; + } + + public WaypointType getType() { + return type; + } + + public void setType(WaypointType type) { + this.type = type; + } + + public double getLength() { + return length; + } + + public void setLength(double length) { + this.length = length; + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public long getStartId() { + return startId; + } + + public void setStartId(long startId) { + this.startId = startId; + } + + public long getStopId() { + return stopId; + } + + public void setStopId(long stopId) { + this.stopId = stopId; + } + + public Location getLocation() { + return location; + } + + public void setLocation(Location location) { + this.location = location; + } + + public TripStatistics getTripStatistics() { + return tripStatistics; + } + + public void setTripStatistics(TripStatistics tripStatistics) { + this.tripStatistics = tripStatistics; + } + + public String getPhotoUrl() { + return photoUrl; + } + + public void setPhotoUrl(String photoUrl) { + this.photoUrl = photoUrl; + } +} diff --git a/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/WaypointCreationRequest.java b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/WaypointCreationRequest.java new file mode 100644 index 000000000..caf88ff80 --- /dev/null +++ b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/WaypointCreationRequest.java @@ -0,0 +1,126 @@ +/* + * 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. + */ +package com.google.android.apps.mytracks.content; + +import com.google.android.apps.mytracks.content.Waypoint.WaypointType; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * A request for the service to create a waypoint at the current location. + * + * @author Sandor Dornbush + */ +public class WaypointCreationRequest implements Parcelable { + + private WaypointType type; + // true if this marker contains the track statistics + private boolean isTrackStatistics; + private String name; + private String category; + private String description; + private String iconUrl; + private String photoUrl; + + public final static WaypointCreationRequest DEFAULT_WAYPOINT = new WaypointCreationRequest( + WaypointType.WAYPOINT, false); + public final static WaypointCreationRequest DEFAULT_STATISTICS = new WaypointCreationRequest( + WaypointType.STATISTICS, false); + public final static WaypointCreationRequest DEFAULT_START_TRACK = new WaypointCreationRequest( + WaypointType.STATISTICS, true); + + private WaypointCreationRequest(WaypointType type, boolean isTrackStatistics) { + this(type, isTrackStatistics, null, null, null, null, null); + } + + public WaypointCreationRequest(WaypointType type, boolean isTrackStatistics, String name, + String category, String description, String iconUrl, String photoUrl) { + this.type = type; + this.isTrackStatistics = isTrackStatistics; + this.name = name; + this.category = category; + this.description = description; + this.iconUrl = iconUrl; + this.photoUrl = photoUrl; + } + + public static class Creator implements Parcelable.Creator { + + @Override + public WaypointCreationRequest createFromParcel(Parcel source) { + WaypointCreationRequest request = new WaypointCreationRequest( + WaypointType.values()[source.readInt()], + source.readByte() == 1, + source.readString(), + source.readString(), + source.readString(), + source.readString(), + source.readString()); + return request; + } + + public WaypointCreationRequest[] newArray(int size) { + return new WaypointCreationRequest[size]; + } + } + + public static final Creator CREATOR = new Creator(); + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int arg1) { + parcel.writeInt(type.ordinal()); + parcel.writeByte((byte) (isTrackStatistics ? 1 : 0)); + parcel.writeString(name); + parcel.writeString(category); + parcel.writeString(description); + parcel.writeString(iconUrl); + parcel.writeString(photoUrl); + } + + public WaypointType getType() { + return type; + } + + public boolean isTrackStatistics() { + return isTrackStatistics; + } + + public String getName() { + return name; + } + + public String getCategory() { + return category; + } + + public String getDescription() { + return description; + } + + public String getIconUrl() { + return iconUrl; + } + + public String getPhotoUrl() { + return photoUrl; + } +} \ No newline at end of file diff --git a/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/WaypointsColumns.java b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/WaypointsColumns.java new file mode 100644 index 000000000..eb61b72a3 --- /dev/null +++ b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/content/WaypointsColumns.java @@ -0,0 +1,181 @@ +/* + * 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 + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.android.apps.mytracks.content; + +import static com.google.android.apps.mytracks.content.ContentTypeIds.FLOAT_TYPE_ID; +import static com.google.android.apps.mytracks.content.ContentTypeIds.INT_TYPE_ID; +import static com.google.android.apps.mytracks.content.ContentTypeIds.LONG_TYPE_ID; +import static com.google.android.apps.mytracks.content.ContentTypeIds.STRING_TYPE_ID; + +import android.net.Uri; +import android.provider.BaseColumns; + +/** + * Constants for waypoints table. + * + * @author Leif Hendrik Wilden + */ +public interface WaypointsColumns extends BaseColumns { + + public static final String TABLE_NAME = "waypoints"; + public static final Uri CONTENT_URI = Uri.parse( + "content://com.google.android.maps.mytracks/waypoints"); + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.google.waypoint"; + public static final String CONTENT_ITEMTYPE = "vnd.android.cursor.item/vnd.google.waypoint"; + public static final String DEFAULT_SORT_ORDER = "_id"; + + // Columns + public static final String NAME = "name"; // waypoint name + public static final String DESCRIPTION = "description"; // waypoint description + public static final String CATEGORY = "category"; // waypoint category + public static final String ICON = "icon"; // waypoint icon + public static final String TRACKID = "trackid"; // track id + public static final String TYPE = "type"; // type + public static final String LENGTH = "length"; // length of the track (without smoothing) + public static final String DURATION = "duration"; // total duration of the track (not from last waypoint) + public static final String STARTTIME = "starttime"; // start time of the trip statistics + public static final String STARTID = "startid"; // start track point id + public static final String STOPID = "stopid"; // stop track point id + + public static final String LONGITUDE = "longitude"; // longitude + public static final String LATITUDE = "latitude"; // latitude + public static final String TIME = "time"; // time + public static final String ALTITUDE = "elevation"; // altitude + public static final String ACCURACY = "accuracy"; // accuracy + public static final String SPEED = "speed"; // speed + public static final String BEARING = "bearing"; // bearing + + public static final String TOTALDISTANCE = "totaldistance"; // total distance + public static final String TOTALTIME = "totaltime"; // total time + public static final String MOVINGTIME = "movingtime"; // moving time + public static final String AVGSPEED = "avgspeed"; // average speed + public static final String AVGMOVINGSPEED = "avgmovingspeed"; // average moving speed + public static final String MAXSPEED = "maxspeed"; // max speed + public static final String MINELEVATION = "minelevation"; // min elevation + public static final String MAXELEVATION = "maxelevation"; // max elevation + public static final String ELEVATIONGAIN = "elevationgain"; // elevation gain + public static final String MINGRADE = "mingrade"; // min grade + public static final String MAXGRADE = "maxgrade"; // max grade + public static final String CALORIE = "calorie"; // calorie + + public static final String PHOTOURL = "photoUrl"; // url for the photo + + public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + + _ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + + NAME + " STRING, " + + DESCRIPTION + " STRING, " + + CATEGORY + " STRING, " + + ICON + " STRING, " + + TRACKID + " INTEGER, " + + TYPE + " INTEGER, " + + LENGTH + " FLOAT, " + + DURATION + " INTEGER, " + + STARTTIME + " INTEGER, " + + STARTID + " INTEGER, " + + STOPID + " INTEGER, " + + LONGITUDE + " INTEGER, " + + LATITUDE + " INTEGER, " + + TIME + " INTEGER, " + + ALTITUDE + " FLOAT, " + + ACCURACY + " FLOAT, " + + SPEED + " FLOAT, " + + BEARING + " FLOAT, " + + TOTALDISTANCE + " FLOAT, " + + TOTALTIME + " INTEGER, " + + MOVINGTIME + " INTEGER, " + + AVGSPEED + " FLOAT, " + + AVGMOVINGSPEED + " FLOAT, " + + MAXSPEED + " FLOAT, " + + MINELEVATION + " FLOAT, " + + MAXELEVATION + " FLOAT, " + + ELEVATIONGAIN + " FLOAT, " + + MINGRADE + " FLOAT, " + + MAXGRADE + " FLOAT, " + + CALORIE + " FLOAT, " + + PHOTOURL + " STRING" + + ");"; + + public static final String[] COLUMNS = { + _ID, + NAME, + DESCRIPTION, + CATEGORY, + ICON, + TRACKID, + TYPE, + LENGTH, + DURATION, + STARTTIME, + STARTID, + STOPID, + LONGITUDE, + LATITUDE, + TIME, + ALTITUDE, + ACCURACY, + SPEED, + BEARING, + TOTALDISTANCE, + TOTALTIME, + MOVINGTIME, + AVGSPEED, + AVGMOVINGSPEED, + MAXSPEED, + MINELEVATION, + MAXELEVATION, + ELEVATIONGAIN, + MINGRADE, + MAXGRADE, + CALORIE, + PHOTOURL + }; + + public static final byte[] COLUMN_TYPES = { + LONG_TYPE_ID, // id + STRING_TYPE_ID, // name + STRING_TYPE_ID, // description + STRING_TYPE_ID, // category + STRING_TYPE_ID, // icon + LONG_TYPE_ID, // track id + INT_TYPE_ID, // type + FLOAT_TYPE_ID, // length + LONG_TYPE_ID, // duration + LONG_TYPE_ID, // start time + LONG_TYPE_ID, // start id + LONG_TYPE_ID, // stop id + INT_TYPE_ID, // longitude + INT_TYPE_ID, // latitude + LONG_TYPE_ID, // time + FLOAT_TYPE_ID, // altitude + FLOAT_TYPE_ID, // accuracy + FLOAT_TYPE_ID, // speed + FLOAT_TYPE_ID, // bearing + FLOAT_TYPE_ID, // total distance + LONG_TYPE_ID, // total time + LONG_TYPE_ID, // moving time + FLOAT_TYPE_ID, // average speed + FLOAT_TYPE_ID, // average moving speed + FLOAT_TYPE_ID, // max speed + FLOAT_TYPE_ID, // min elevation + FLOAT_TYPE_ID, // max elevation + FLOAT_TYPE_ID, // elevation gain + FLOAT_TYPE_ID, // min grade + FLOAT_TYPE_ID, // max grade + FLOAT_TYPE_ID, // calorie + STRING_TYPE_ID // photo url + }; +} diff --git a/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/lib/MyTracksLibConstants.java b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/lib/MyTracksLibConstants.java new file mode 100644 index 000000000..739cf79f1 --- /dev/null +++ b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/lib/MyTracksLibConstants.java @@ -0,0 +1,28 @@ +/* + * 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. + */ +package com.google.android.apps.mytracks.lib; + +/** + * Constants for the My Tracks common library. + * These constants should ideally not be used by third-party applications. + * + * @author Rodrigo Damazio + */ +public class MyTracksLibConstants { + public static final String TAG = "MyTracksLib"; + + private MyTracksLibConstants() {} +} diff --git a/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/stats/ExtremityMonitor.java b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/stats/ExtremityMonitor.java new file mode 100644 index 000000000..8a4618588 --- /dev/null +++ b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/stats/ExtremityMonitor.java @@ -0,0 +1,117 @@ +/* + * 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 + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.android.apps.mytracks.stats; + +/** + * A helper class that tracks a minimum and a maximum of a variable. + * + * @author Sandor Dornbush + */ +public class ExtremityMonitor { + + // The smallest value seen so far. + private double min; + + // The largest value seen so far. + private double max; + + public ExtremityMonitor() { + reset(); + } + + /** + * Resets this object to it's initial state where the min and max are unknown. + */ + public void reset() { + min = Double.POSITIVE_INFINITY; + max = Double.NEGATIVE_INFINITY; + } + + /** + * Gets the minimum value seen. + */ + public double getMin() { + return min; + } + + /** + * Gets the maximum value seen. + */ + public double getMax() { + return max; + } + + /** + * Updates the min and the max with a new value. + * + * @param value the new value + * @return true if an extremity was found + */ + public boolean update(double value) { + boolean changed = false; + if (value < min) { + min = value; + changed = true; + } + if (value > max) { + max = value; + changed = true; + } + return changed; + } + + /** + * Sets the minimum and maximum values. + * + * @param min the minimum value + * @param max the maximum value + */ + public void set(double min, double max) { + this.min = min; + this.max = max; + } + + /** + * Sets the minimum value. + * + * @param min the minimum value + */ + public void setMin(double min) { + this.min = min; + } + + /** + * Sets the maximum value. + * + * @param max the maximum value + */ + public void setMax(double max) { + this.max = max; + } + + /** + * Returns true if has data. + */ + public boolean hasData() { + return min != Double.POSITIVE_INFINITY && max != Double.NEGATIVE_INFINITY; + } + + @Override + public String toString() { + return "Min: " + min + " Max: " + max; + } +} diff --git a/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/stats/TripStatistics.java b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/stats/TripStatistics.java new file mode 100644 index 000000000..52c2dece6 --- /dev/null +++ b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/stats/TripStatistics.java @@ -0,0 +1,598 @@ +/* + * 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. + */ + +package com.google.android.apps.mytracks.stats; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Statistical data about a trip. The data in this class should be filled out by + * TripStatisticsBuilder. + *

+ * TODO: hashCode and equals + * + * @author Rodrigo Damazio + */ +public class TripStatistics implements Parcelable { + + // The trip start time. This is the system time, might not match the GPs time. + private long startTime = -1L; + + // The trip stop time. This is the system time, might not match the GPS time. + private long stopTime = -1L; + + // The total trip distance (meters). + private double totalDistance; + + // The total time (ms). Updated when new points are received, may be stale. + private long totalTime; + + // The total moving time (ms). Based on when we believe the user is traveling. + private long movingTime; + + // The min and max latitude seen in this trip. + private final ExtremityMonitor latitudeExtremities = new ExtremityMonitor(); + + // The min and max longitude seen in this trip. + private final ExtremityMonitor longitudeExtremities = new ExtremityMonitor(); + + // The maximum speed (meters/second) that we believe is valid. + private double maxSpeed; + + // The min and max elevation (meters) seen on this trip. + private final ExtremityMonitor elevationExtremities = new ExtremityMonitor(); + + // The total elevation gained (meters). + private double totalElevationGain; + + // The min and max grade seen on this trip. + private final ExtremityMonitor gradeExtremities = new ExtremityMonitor(); + + // The calorie of current track. + private double calorie = 0.0; + + /** + * Default constructor. + */ + public TripStatistics() {} + + /** + * Copy constructor. + * + * @param other another statistics data object to copy from + */ + public TripStatistics(TripStatistics other) { + startTime = other.startTime; + stopTime = other.stopTime; + totalDistance = other.totalDistance; + totalTime = other.totalTime; + movingTime = other.movingTime; + latitudeExtremities.set(other.latitudeExtremities.getMin(), other.latitudeExtremities.getMax()); + longitudeExtremities.set( + other.longitudeExtremities.getMin(), other.longitudeExtremities.getMax()); + maxSpeed = other.maxSpeed; + elevationExtremities.set( + other.elevationExtremities.getMin(), other.elevationExtremities.getMax()); + totalElevationGain = other.totalElevationGain; + gradeExtremities.set(other.gradeExtremities.getMin(), other.gradeExtremities.getMax()); + calorie = other.calorie; + } + + /** + * Combines these statistics with those from another object. This assumes that + * the time periods covered by each do not intersect. + * + * @param other another statistics data object + */ + public void merge(TripStatistics other) { + startTime = Math.min(startTime, other.startTime); + stopTime = Math.max(stopTime, other.stopTime); + totalDistance += other.totalDistance; + totalTime += other.totalTime; + movingTime += other.movingTime; + if (other.latitudeExtremities.hasData()) { + latitudeExtremities.update(other.latitudeExtremities.getMin()); + latitudeExtremities.update(other.latitudeExtremities.getMax()); + } + if (other.longitudeExtremities.hasData()) { + longitudeExtremities.update(other.longitudeExtremities.getMin()); + longitudeExtremities.update(other.longitudeExtremities.getMax()); + } + maxSpeed = Math.max(maxSpeed, other.maxSpeed); + if (other.elevationExtremities.hasData()) { + elevationExtremities.update(other.elevationExtremities.getMin()); + elevationExtremities.update(other.elevationExtremities.getMax()); + } + totalElevationGain += other.totalElevationGain; + if (other.gradeExtremities.hasData()) { + gradeExtremities.update(other.gradeExtremities.getMin()); + gradeExtremities.update(other.gradeExtremities.getMax()); + } + calorie += other.calorie; + } + + /** + * Gets the trip start time. The number of milliseconds since epoch. + */ + public long getStartTime() { + return startTime; + } + + /** + * Sets the trip start time. + * + * @param startTime the trip start time in milliseconds since the epoch + */ + public void setStartTime(long startTime) { + this.startTime = startTime; + } + + /** + * Gets the trip stop time. The number of milliseconds since epoch. + */ + public long getStopTime() { + return stopTime; + } + + /** + * Sets the trip stop time. + * + * @param stopTime the stop time in milliseconds since the epoch + */ + public void setStopTime(long stopTime) { + this.stopTime = stopTime; + } + + /** + * Gets the total distance the user traveled in meters. + */ + public double getTotalDistance() { + return totalDistance; + } + + /** + * Sets the total trip distance. + * + * @param totalDistance the trip distance in meters + */ + public void setTotalDistance(double totalDistance) { + this.totalDistance = totalDistance; + } + + /** + * Adds to the current total distance. + * + * @param distance the distance to add in meters + */ + public void addTotalDistance(double distance) { + totalDistance += distance; + } + + /** + * Gets the total time in milliseconds that this track has been active. This + * statistic is only updated when a new point is added to the statistics, so + * it may be off. If you need to calculate the proper total time, use + * {@link #getStartTime} with the current time. + */ + public long getTotalTime() { + return totalTime; + } + + /** + * Sets the trip total time. + * + * @param totalTime the trip total time in milliseconds + */ + public void setTotalTime(long totalTime) { + this.totalTime = totalTime; + } + + /** + * Gets the moving time in milliseconds. + */ + public long getMovingTime() { + return movingTime; + } + + /** + * Sets the trip total moving time. + * + * @param movingTime the trip total moving time in milliseconds + */ + public void setMovingTime(long movingTime) { + this.movingTime = movingTime; + } + + /** + * Adds to the trip total moving time. + * + * @param time the time in milliseconds + */ + public void addMovingTime(long time) { + movingTime += time; + } + + /** + * Gets the topmost position (highest latitude) of the track, in signed + * degrees. + */ + public double getTopDegrees() { + return latitudeExtremities.getMax(); + } + + /** + * Gets the topmost position (highest latitude) of the track, in signed + * millions of degrees. + */ + public int getTop() { + return (int) (latitudeExtremities.getMax() * 1E6); + } + + /** + * Gets the bottommost position (lowest latitude) of the track, in signed + * degrees. + */ + public double getBottomDegrees() { + return latitudeExtremities.getMin(); + } + + /** + * Gets the bottommost position (lowest latitude) of the track, in signed + * millions of degrees. + */ + public int getBottom() { + return (int) (latitudeExtremities.getMin() * 1E6); + } + + /** + * Gets the leftmost position (lowest longitude) of the track, in signed + * degrees. + */ + public double getLeftDegrees() { + return longitudeExtremities.getMin(); + } + + /** + * Gets the leftmost position (lowest longitude) of the track, in signed + * millions of degrees. + */ + public int getLeft() { + return (int) (longitudeExtremities.getMin() * 1E6); + } + + /** + * Gets the rightmost position (highest longitude) of the track, in signed + * degrees. + */ + public double getRightDegrees() { + return longitudeExtremities.getMax(); + } + + /** + * Gets the rightmost position (highest longitude) of the track, in signed + * millions of degrees. + */ + public int getRight() { + return (int) (longitudeExtremities.getMax() * 1E6); + } + + /** + * Gets the mean latitude position of the track, in signed degrees. + */ + public double getMeanLatitude() { + return (getBottomDegrees() + getTopDegrees()) / 2.0; + } + + /** + * Gets the mean longitude position of the track, in signed degrees. + */ + public double getMeanLongitude() { + return (getLeftDegrees() + getRightDegrees()) / 2.0; + } + + /** + * Sets the bounding box for this trip. The unit for all parameters is signed + * millions of degree (degrees * 1E6). + * + * @param leftE6 the leftmost longitude reached + * @param topE6 the topmost latitude reached + * @param rightE6 the rightmost longitude reached + * @param bottomE6 the bottommost latitude reached + */ + public void setBounds(int leftE6, int topE6, int rightE6, int bottomE6) { + latitudeExtremities.set(bottomE6 / 1E6, topE6 / 1E6); + longitudeExtremities.set(leftE6 / 1E6, rightE6 / 1E6); + } + + /** + * Updates a new latitude value. + * + * @param latitude the latitude value in signed decimal degrees + */ + public void updateLatitudeExtremities(double latitude) { + latitudeExtremities.update(latitude); + } + + /** + * Updates a new longitude value. + * + * @param longitude the longitude value in signed decimal degrees + */ + public void updateLongitudeExtremities(double longitude) { + longitudeExtremities.update(longitude); + } + + /** + * Gets the average speed in meters/second. This calculation only takes into + * account the displacement until the last point that was accounted for in + * statistics. + */ + public double getAverageSpeed() { + if (totalTime == 0L) { + return 0.0; + } + return totalDistance / ((double) totalTime / 1000.0); + } + + /** + * Gets the average moving speed in meters/second. + */ + public double getAverageMovingSpeed() { + if (movingTime == 0L) { + return 0.0; + } + return totalDistance / ((double) movingTime / 1000.0); + } + + /** + * Gets the maximum speed in meters/second. + */ + public double getMaxSpeed() { + return Math.max(maxSpeed, getAverageMovingSpeed()); + } + + /** + * Sets the maximum speed. + * + * @param maxSpeed the maximum speed in meters/second + */ + public void setMaxSpeed(double maxSpeed) { + this.maxSpeed = maxSpeed; + } + + /** + * Gets the minimum elevation. This is calculated from the smoothed elevation + * so this can actually be more than the current elevation. + */ + public double getMinElevation() { + return elevationExtremities.getMin(); + } + + /** + * Sets the minimum elevation. + * + * @param elevation the minimum elevation in meters + */ + public void setMinElevation(double elevation) { + elevationExtremities.setMin(elevation); + } + + /** + * Gets the maximum elevation. This is calculated from the smoothed elevation + * so this can actually be less than the current elevation. + */ + public double getMaxElevation() { + return elevationExtremities.getMax(); + } + + /** + * Sets the maximum elevation. + * + * @param elevation the maximum elevation in meters + */ + public void setMaxElevation(double elevation) { + elevationExtremities.setMax(elevation); + } + + /** + * Updates a new elevation. + * + * @param elevation the elevation value in meters + */ + public void updateElevationExtremities(double elevation) { + elevationExtremities.update(elevation); + } + + /** + * Gets the total elevation gain in meters. This is calculated as the sum of + * all positive differences in the smoothed elevation. + */ + public double getTotalElevationGain() { + return totalElevationGain; + } + + /** + * Sets the total elevation gain. + * + * @param totalElevationGain the elevation gain in meters + */ + public void setTotalElevationGain(double totalElevationGain) { + this.totalElevationGain = totalElevationGain; + } + + /** + * Adds to the total elevation gain. + * + * @param gain the elevation gain in meters + */ + public void addTotalElevationGain(double gain) { + totalElevationGain += gain; + } + + /** + * Gets the minimum grade for this trip. + */ + public double getMinGrade() { + return gradeExtremities.getMin(); + } + + /** + * Sets the maximum grade. + * + * @param grade the grade as a fraction (1.0 would mean vertical upwards) + */ + public void setMaxGrade(double grade) { + gradeExtremities.setMax(grade); + } + + /** + * Gets the maximum grade for this trip. + */ + public double getMaxGrade() { + return gradeExtremities.getMax(); + } + + /** + * Sets the minimum grade. + * + * @param grade the grade as a fraction (-1.0 would mean vertical downwards) + */ + public void setMinGrade(double grade) { + gradeExtremities.setMin(grade); + } + + /** + * Updates a new grade value. + * + * @param grade the grade value as a fraction + */ + public void updateGradeExtremities(double grade) { + gradeExtremities.update(grade); + } + + @Override + public String toString() { + return "TripStatistics { Start Time: " + getStartTime() + "; Stop Time: " + getStopTime() + + "; Total Distance: " + getTotalDistance() + "; Total Time: " + getTotalTime() + + "; Moving Time: " + getMovingTime() + "; Min Latitude: " + getBottomDegrees() + + "; Max Latitude: " + getTopDegrees() + "; Min Longitude: " + getLeftDegrees() + + "; Max Longitude: " + getRightDegrees() + "; Max Speed: " + getMaxSpeed() + + "; Min Elevation: " + getMinElevation() + "; Max Elevation: " + getMaxElevation() + + "; Elevation Gain: " + getTotalElevationGain() + "; Min Grade: " + getMinGrade() + + "; Max Grade: " + getMaxGrade() + "; Calorie: " + getCalorie() + + "}"; + } + + /** + * Creator of statistics data from parcels. + */ + public static class Creator implements Parcelable.Creator { + + @Override + public TripStatistics createFromParcel(Parcel source) { + TripStatistics data = new TripStatistics(); + + data.startTime = source.readLong(); + data.stopTime = source.readLong(); + data.totalDistance = source.readDouble(); + data.totalTime = source.readLong(); + data.movingTime = source.readLong(); + + double minLat = source.readDouble(); + double maxLat = source.readDouble(); + data.latitudeExtremities.set(minLat, maxLat); + + double minLong = source.readDouble(); + double maxLong = source.readDouble(); + data.longitudeExtremities.set(minLong, maxLong); + + data.maxSpeed = source.readDouble(); + + double minElev = source.readDouble(); + double maxElev = source.readDouble(); + data.elevationExtremities.set(minElev, maxElev); + data.totalElevationGain = source.readDouble(); + + double minGrade = source.readDouble(); + double maxGrade = source.readDouble(); + data.gradeExtremities.set(minGrade, maxGrade); + + data.calorie = source.readDouble(); + return data; + } + + @Override + public TripStatistics[] newArray(int size) { + return new TripStatistics[size]; + } + } + + /** + * Creator of {@link TripStatistics} from parcels. + */ + public static final Creator CREATOR = new Creator(); + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeLong(startTime); + dest.writeLong(stopTime); + dest.writeDouble(totalDistance); + dest.writeLong(totalTime); + dest.writeLong(movingTime); + dest.writeDouble(latitudeExtremities.getMin()); + dest.writeDouble(latitudeExtremities.getMax()); + dest.writeDouble(longitudeExtremities.getMin()); + dest.writeDouble(longitudeExtremities.getMax()); + dest.writeDouble(maxSpeed); + dest.writeDouble(elevationExtremities.getMin()); + dest.writeDouble(elevationExtremities.getMax()); + dest.writeDouble(totalElevationGain); + dest.writeDouble(gradeExtremities.getMin()); + dest.writeDouble(gradeExtremities.getMax()); + dest.writeDouble(calorie); + } + + /** + * Adds calorie value. + * + * @param calorieAdded add the value to the total calorie + */ + public void addCalorie(double calorieAdded) { + calorie += calorieAdded; + } + + /** + * Sets calorie value. + * + * @param calorie the new value of calorie + */ + public void setCalorie(double calorie) { + this.calorie = calorie; + } + + /** + * Gets calorie value. + */ + public double getCalorie() { + return calorie; + } +} \ No newline at end of file diff --git a/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/util/FileUtils.java b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/util/FileUtils.java new file mode 100644 index 000000000..cd88d3d6c --- /dev/null +++ b/MyTracks/myTracksLib/src/main/java/com/google/android/apps/mytracks/util/FileUtils.java @@ -0,0 +1,291 @@ +/* + * 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. + */ +package com.google.android.apps.mytracks.util; + +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Environment; + +import java.io.File; + +/** + * Utilities for dealing with files. + * + * @author Rodrigo Damazio + */ +public class FileUtils { + + private FileUtils() {} + + /** + * The backups directory under the My Tracks external storage directory. + */ + public static final String BACKUPS_DIR = "backups"; + + /** + * The My Tracks external storage directory. + */ + static final String SDCARD_TOP_DIR = "MyTracks"; + + /** + * The maximum FAT32 path length. See the FAT32 spec at + * http://msdn.microsoft.com/en-us/windows/hardware/gg463080 + */ + static final int MAX_FAT32_PATH_LENGTH = 260; + + /** + * The play tracks directory under the My Tracks cache directory. + */ + public static final String PLAY_TRACKS_DIR = "temp"; + + /** + * The temp files directory under the My Tracks cache directory. + */ + public static final String TEMP_FILES_DIR = "temp_files"; + + /** + * The pictures directory under the My Tracks external storage directory. + */ + private static final String PICTURES_DIR = "pictures"; + + /** + * Returns true if the external storage is available. + */ + public static boolean isExternalStorageAvailable() { + String state = Environment.getExternalStorageState(); + return Environment.MEDIA_MOUNTED.equals(state) + || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state); + } + + /** + * Returns true if the external storage is writable. + */ + public static boolean isExternalStorageWriteable() { + String state = Environment.getExternalStorageState(); + return Environment.MEDIA_MOUNTED.equals(state); + } + + /** + * Returns true if the directory exists. + * + * @param dir the directory + */ + public static boolean isDirectory(File dir) { + return dir.exists() && dir.isDirectory(); + } + + /** + * Ensures the directory exists by creating it and its parents if necessary. + * + * @return whether the directory exists (either already existed or was + * successfully created) + */ + public static boolean ensureDirectoryExists(File dir) { + if (isDirectory(dir)) { + return true; + } + return dir.mkdirs(); + } + + public static File getPhotoDir() { + return new File(getPath(PICTURES_DIR)); + } + + public static File getPhotoDir(long trackId) { + return new File(getPath(PICTURES_DIR, "MyTracks" + Long.toString(trackId))); + } + + /** + * Gets the display name for a path on the external storage. + * + * @param components the components + */ + public static String getPathDisplayName(String... components) { + StringBuilder dirNameBuilder = new StringBuilder(); + dirNameBuilder.append(File.separatorChar); + dirNameBuilder.append(SDCARD_TOP_DIR); + for (String component : components) { + dirNameBuilder.append(File.separatorChar); + dirNameBuilder.append(component); + } + return dirNameBuilder.toString(); + } + + /** + * Gets a path on the external storage. + * + * @param components the components + */ + public static String getPath(String... components) { + StringBuilder dirNameBuilder = new StringBuilder(); + dirNameBuilder.append(Environment.getExternalStorageDirectory()); + dirNameBuilder.append(getPathDisplayName(components)); + return dirNameBuilder.toString(); + } + + /** + * Builds a filename with the given base name (prefix) and the given + * extension, possibly adding a suffix to ensure the file doesn't exist. + * + * @param directory the directory the file will live in + * @param fileBaseName the prefix for the file name + * @param extension the file's extension + * @return the complete file name, without the directory + */ + public static synchronized String buildUniqueFileName( + File directory, String fileBaseName, String extension) { + return buildUniqueFileName(directory, fileBaseName, extension, 0); + } + + /** + * Gets the name from a file name, without the extension. + * + * @param fileName the file name + */ + public static String getName(String fileName) { + int index = fileName.lastIndexOf('.'); + if (index == -1) { + return fileName; + } + return fileName.substring(0, index); + } + + /** + * Gets the extension from a file name. Returns null if there is no extension. + * + * @param fileName the file name + */ + public static String getExtension(String fileName) { + int index = fileName.lastIndexOf('.'); + if (index == -1) { + return null; + } + return fileName.substring(index + 1); + } + + public static void updateMediaScanner(Context context, Uri uri) { + Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); + mediaScanIntent.setData(uri); + context.sendBroadcast(mediaScanIntent); + } + + /** + * Builds a filename with the given base and the given extension, possibly + * adding a suffix to ensure the file doesn't exist. + * + * @param directory the directory the filename will be located in + * @param base the base for the filename + * @param extension the extension for the filename + * @param suffix the first numeric suffix to try to use, or 0 for none + * @return the complete filename, without the directory + */ + private static String buildUniqueFileName( + File directory, String base, String extension, int suffix) { + String suffixName = ""; + if (suffix > 0) { + suffixName += "(" + Integer.toString(suffix) + ")"; + } + suffixName += "." + extension; + + String baseName = sanitizeFileName(base); + baseName = truncateFileName(directory, baseName, suffixName); + String fullName = baseName + suffixName; + + if (!new File(directory, fullName).exists()) { + return fullName; + } + return buildUniqueFileName(directory, base, extension, suffix + 1); + } + + /** + * Sanitizes the name as a valid fat32 filename. For simplicity, fat32 + * filename characters may be any combination of letters, digits, or + * characters with code point values greater than 127. Replaces the invalid + * characters with "_" and collapses multiple "_" together. + * + * @param name name + */ + static String sanitizeFileName(String name) { + StringBuffer buffer = new StringBuffer(name.length()); + for (int i = 0; i < name.length(); i++) { + int codePoint = name.codePointAt(i); + char character = name.charAt(i); + if (Character.isLetterOrDigit(character) || codePoint > 127 || isSpecialFat32(character)) { + buffer.appendCodePoint(codePoint); + } else { + buffer.append("_"); + } + } + String result = buffer.toString(); + return result.replaceAll("_+", "_"); + } + + /** + * Returns true if it is a special FAT32 character. + * + * @param character the character + */ + private static boolean isSpecialFat32(char character) { + switch (character) { + case '$': + case '%': + case '\'': + case '-': + case '_': + case '@': + case '~': + case '`': + case '!': + case '(': + case ')': + case '{': + case '}': + case '^': + case '#': + case '&': + case '+': + case ',': + case ';': + case '=': + case '[': + case ']': + case ' ': + return true; + default: + return false; + } + } + + /** + * Truncates the name if necessary so the filename path length (directory + + * name + suffix) meets the Fat32 path limit. + * + * @param directory directory + * @param name name + * @param suffix suffix + */ + static String truncateFileName(File directory, String name, String suffix) { + // 1 at the end accounts for the FAT32 filename trailing NUL character + int requiredLength = directory.getPath().length() + suffix.length() + 1; + if (name.length() + requiredLength > MAX_FAT32_PATH_LENGTH) { + int limit = MAX_FAT32_PATH_LENGTH - requiredLength; + return name.substring(0, limit); + } else { + return name; + } + } +} diff --git a/MyTracks/myTracksLib/src/main/res/drawable-hdpi/ic_launcher_my_tracks.png b/MyTracks/myTracksLib/src/main/res/drawable-hdpi/ic_launcher_my_tracks.png new file mode 100644 index 000000000..1f70e5ba7 Binary files /dev/null and b/MyTracks/myTracksLib/src/main/res/drawable-hdpi/ic_launcher_my_tracks.png differ diff --git a/MyTracks/myTracksLib/src/main/res/drawable-mdpi/ic_launcher_my_tracks.png b/MyTracks/myTracksLib/src/main/res/drawable-mdpi/ic_launcher_my_tracks.png new file mode 100644 index 000000000..91b99dff4 Binary files /dev/null and b/MyTracks/myTracksLib/src/main/res/drawable-mdpi/ic_launcher_my_tracks.png differ diff --git a/MyTracks/myTracksLib/src/main/res/drawable-xhdpi/ic_launcher_my_tracks.png b/MyTracks/myTracksLib/src/main/res/drawable-xhdpi/ic_launcher_my_tracks.png new file mode 100644 index 000000000..0d259e059 Binary files /dev/null and b/MyTracks/myTracksLib/src/main/res/drawable-xhdpi/ic_launcher_my_tracks.png differ diff --git a/MyTracks/myTracksLib/src/main/res/drawable-xxhdpi/ic_launcher_my_tracks.png b/MyTracks/myTracksLib/src/main/res/drawable-xxhdpi/ic_launcher_my_tracks.png new file mode 100644 index 000000000..08bd7b777 Binary files /dev/null and b/MyTracks/myTracksLib/src/main/res/drawable-xxhdpi/ic_launcher_my_tracks.png differ diff --git a/MyTracks/myTracksLib/src/main/res/values/strings.xml b/MyTracks/myTracksLib/src/main/res/values/strings.xml new file mode 100644 index 000000000..3688082e4 --- /dev/null +++ b/MyTracks/myTracksLib/src/main/res/values/strings.xml @@ -0,0 +1,20 @@ + + + + + My Tracks Base Library + diff --git a/MyTracks/myTracksLib/src/main/res/values/third_party.xml b/MyTracks/myTracksLib/src/main/res/values/third_party.xml new file mode 100644 index 000000000..5831ba65c --- /dev/null +++ b/MyTracks/myTracksLib/src/main/res/values/third_party.xml @@ -0,0 +1,33 @@ + + + + + + com.google.android.apps.mytracks.TRACK_NOTIFICATIONS + com.google.android.apps.mytracks.READ_TRACK_DATA + com.google.android.apps.mytracks.WRITE_TRACK_DATA + + com.google.android.apps.mytracks.TRACK_ID + com.google.android.apps.mytracks.TRACK_PAUSED + com.google.android.apps.mytracks.TRACK_RESUMED + com.google.android.apps.mytracks.TRACK_STARTED + com.google.android.apps.mytracks.TRACK_STOPPED + com.google.android.apps.mytracks.TRACK_UPDATE + + com.google.android.apps.mytracks.services.TrackRecordingService + com.google.android.maps.mytracks + \ No newline at end of file diff --git a/MyTracks/project.properties b/MyTracks/project.properties deleted file mode 100644 index a07721686..000000000 --- a/MyTracks/project.properties +++ /dev/null @@ -1,16 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system use, -# "ant.properties", and override values to adapt the script to your -# project structure. - -# Indicates whether an apk should be generated for each density. -split.density=false -proguard.config=proguard.cfg:proguard-google-api-client.txt -# Project target. -target=android-17 -android.library.reference.1=../MyTracksLib -android.library.reference.2=../google-play-services_lib diff --git a/MyTracks/settings.gradle b/MyTracks/settings.gradle new file mode 100644 index 000000000..ef889580c --- /dev/null +++ b/MyTracks/settings.gradle @@ -0,0 +1,3 @@ +include ':myTracksLib' +include ':googleplayservices_lib' +include ':myTracks'