├── .gitignore
├── .travis.yml
├── LICENSE.md
├── README.md
├── build.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── library
├── build.gradle
├── ic_launcher-web.png
├── proguard-project.txt
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── com
│ └── directions
│ └── route
│ ├── AbstractRouting.java
│ ├── GoogleParser.java
│ ├── Parser.java
│ ├── Route.java
│ ├── RouteException.java
│ ├── Routing.java
│ ├── RoutingListener.java
│ ├── Segment.java
│ └── XMLParser.java
├── sample
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── directions
│ │ └── sample
│ │ ├── MainActivity.java
│ │ ├── PlaceAutoCompleteAdapter.java
│ │ └── Util.java
│ └── res
│ ├── drawable-xhdpi
│ ├── Thumbs.db
│ ├── end_green.png
│ ├── ic_send_grey600_48dp.png
│ ├── pushpin.png
│ └── start_blue.png
│ ├── drawable
│ ├── Thumbs.db
│ └── dotted.xml
│ ├── layout
│ └── activity_main.xml
│ ├── menu
│ └── menu_main.xml
│ ├── mipmap-hdpi
│ └── ic_launcher.png
│ ├── mipmap-mdpi
│ └── ic_launcher.png
│ ├── mipmap-xhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxxhdpi
│ └── ic_launcher.png
│ ├── values-w820dp
│ └── dimens.xml
│ └── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── screenshots
├── Thumbs.db
├── device-2015-06-30-095135.png
├── device-2015-06-30-095241.png
├── device-2015-06-30-095323.png
└── device-2015-06-30-100949.png
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | # built application files
2 | *.apk
3 | *.ap_
4 |
5 | # files for the dex VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # generated files
12 | bin/
13 | gen/
14 |
15 |
16 | # Local configuration file (sdk path, etc)
17 | local.properties
18 |
19 | # Eclipse project files
20 | .classpath
21 | .project
22 |
23 | # Proguard folder generated by Eclipse
24 | proguard/
25 |
26 | # Intellij project files
27 | *.iml
28 | *.ipr
29 | *.iws
30 | .idea/
31 | build
32 |
33 | # Stupid MAC
34 | .DS_STORE
35 |
36 | # gradle
37 | .gradle
38 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | before_install:
2 | - chmod +x gradlew
3 |
4 | language: android
5 | android:
6 | components:
7 | - build-tools-22.0.1
8 | - android-22
9 | - extra
10 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013 Joel Dean
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | this software and associated documentation files (the "Software"), to deal in
5 | the Software without restriction, including without limitation the rights to
6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | of the Software, and to permit persons to whom the Software is furnished to do
8 | so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Google-Directions-Android
2 | =========================
3 | [](https://maven-badges.herokuapp.com/maven-central/com.github.jd-alexander/library/) [](https://android-arsenal.com/details/1/2090) [](https://travis-ci.org/jd-alexander/Google-Directions-Android)
4 |
5 | This project allows you to calculate the direction between two locations and display the route on a Google Map using the Google Directions API - This project isn't actively been maintained.
6 |
7 |
8 |
9 | ![Example Image][1]
10 |
11 | Sample
12 | ------------
13 |
14 | The sample makes use of the Google Places API for Android in order to provide a real life example of how the library can be used.[You can check it out on the store.](https://play.google.com/store/apps/details?id=com.directions.sample)
15 |
16 | Download
17 | --------
18 |
19 |
20 | Grab via Maven:
21 | ```xml
22 |
23 | com.github.jd-alexander
24 | library
25 | 1.1.0
26 |
27 | ```
28 | or Gradle:
29 | ```groovy
30 | compile 'com.github.jd-alexander:library:1.1.0'
31 | ```
32 |
33 | Usage
34 | -----
35 |
36 | To calculate the route you simply instantiate a Routing object and trigger the execute function.
37 |
38 |
39 | *You can execute the task in this manner. ( See the example for more details on the exact implementation)
40 |
41 |
42 |
43 | ``` java
44 |
45 | Routing routing = new Routing.Builder()
46 | .travelMode(/* Travel Mode */)
47 | .withListener(/* Listener that delivers routing results.*/)
48 | .waypoints(/*waypoints*/)
49 | .key(/*api key for quota management*/)
50 | .build();
51 | routing.execute();
52 |
53 | ```
54 |
55 |
56 |
57 | actual code
58 | ``` java
59 | start = new LatLng(18.015365, -77.499382);
60 | waypoint= new LatLng(18.01455, -77.499333);
61 | end = new LatLng(18.012590, -77.500659);
62 |
63 | Routing routing = new Routing.Builder()
64 | .travelMode(Routing.TravelMode.WALKING)
65 | .withListener(this)
66 | .waypoints(start, waypoint, end)
67 | .build();
68 | routing.execute();
69 |
70 | .....
71 |
72 | @Override
73 | public void onRoutingSuccess(ArrayList route, int shortestRouteIndex)
74 | {
75 | //code to add route to map here. See sample app for more details.
76 | }
77 | ```
78 |
79 | Demostration
80 | ------------
81 | * https://www.youtube.com/watch?v=58AxNh2cWRU
82 |
83 | Demo App
84 | ------------
85 | * https://github.com/hamza-ameer/GoogleMaps-Find-Routes/tree/Updated
86 |
87 |
88 | Known Issues
89 | ------------
90 | * If the AutoComplete TextView/Map of the sample app isnt working then probably the API key hasn't been set in the manifest.
91 |
92 | * If the route is not being displayed then type "Routing" in your log cat to see the potential error messages from the library.
93 |
94 |
95 | Contribution
96 | ------------
97 |
98 | Please fork repository and contribute using pull requests.
99 |
100 | Any contributions, large or small, major features, bug fixes, additional language translations, unit/integration tests are welcomed and appreciated but will be thoroughly reviewed and discussed.
101 |
102 | Contributors
103 | ------------
104 | * [Cyrille Berliat](https://github.com/licryle)
105 | * [Felipe Duarte](https://github.com/fcduarte)
106 | * [Kedar Sarmalkar](https://github.com/ksarmalkar)
107 | * [Fernando Gil](https://github.com/fgil)
108 | * [Furkan Tektas](https://github.com/furkantektas)
109 | * [João Pedro Nardari dos Santos](https://github.com/joaopedronardari)
110 | * [Hesham Saeed](https://github.com/HeshamSaeed)
111 |
112 | License
113 | --------
114 |
115 | Copyright 2016 Joel Dean
116 |
117 | Licensed under the Apache License, Version 2.0 (the "License");
118 | you may not use this file except in compliance with the License.
119 | You may obtain a copy of the License at
120 |
121 | http://www.apache.org/licenses/LICENSE-2.0
122 |
123 | Unless required by applicable law or agreed to in writing, software
124 | distributed under the License is distributed on an "AS IS" BASIS,
125 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
126 | See the License for the specific language governing permissions and
127 | limitations under the License.
128 |
129 |
130 |
131 |
132 |
133 |
134 | [1]:http://i57.tinypic.com/2m7j04x.png
135 |
136 |
137 |
138 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | jcenter()
4 | }
5 | dependencies {
6 | classpath 'com.android.tools.build:gradle:1.1.2'
7 | classpath 'com.github.dcendents:android-maven-plugin:1.2'
8 | classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:1.1"
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jd-alexander/Google-Directions-Android/1020635df008737b2e4b956109e1b44693af95c6/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Jan 26 22:38:14 EST 2014
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/library/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'com.github.dcendents.android-maven'
3 | apply plugin: "com.jfrog.bintray"
4 |
5 |
6 | dependencies {
7 | compile fileTree(dir: 'libs', include: '*.jar')
8 | compile 'com.google.android.gms:play-services-maps:8.4.0'
9 | }
10 | // This is the library version used when deploying the artifact
11 | version = "1.0.9"
12 |
13 | android {
14 | compileSdkVersion 22
15 | buildToolsVersion "22.0.1"
16 |
17 | defaultConfig {
18 | minSdkVersion 10
19 | targetSdkVersion 22
20 | }
21 | }
22 |
23 |
24 |
25 | def siteUrl = 'https://github.com/jd-alexander/Google-Directions-Android' // Homepage URL of the library
26 | def gitUrl = 'https://github.com/jd-alexander/Google-Directions-Android.git' // Git repository URL
27 | group = "com.github.jd-alexander" // Maven Group ID for the artifact
28 |
29 |
30 | install {
31 | repositories.mavenInstaller {
32 | // This generates POM.xml with proper parameters
33 | pom {
34 | project {
35 | packaging 'aar'
36 |
37 | // Add your description here
38 | name 'Google Directions Android'
39 | description = 'This project allows you to calculate the route between two locations and displays it on a map.'
40 |
41 | url siteUrl
42 |
43 | // Set your license
44 | licenses {
45 | license {
46 | name 'The Apache Software License, Version 2.0'
47 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
48 | }
49 | }
50 | developers {
51 | developer {
52 | id 'com.github.jd-alexander '
53 | name 'Joel Dean'
54 | email 'jdeanjj1000@gmail.com'
55 | }
56 | }
57 | scm {
58 | connection gitUrl
59 | developerConnection gitUrl
60 | url siteUrl
61 |
62 | }
63 | }
64 | }
65 | }
66 | }
67 |
68 |
69 |
70 | //Only necessary to push to bintray. Causes Travis CI builds to fail.
71 | /*
72 | Properties properties = new Properties()
73 | properties.load(project.rootProject.file('local.properties').newDataInputStream())
74 |
75 |
76 | // https://github.com/bintray/gradle-bintray-plugin
77 | bintray {
78 | user = properties.getProperty("bintray.user")
79 | key = properties.getProperty("bintray.apikey")
80 |
81 | configurations = ['archives']
82 | pkg {
83 | repo = "maven"
84 | // it is the name that appears in bintray when logged
85 | name = "Google-Directions-Android"
86 | websiteUrl = siteUrl
87 | vcsUrl = gitUrl
88 | licenses = ["Apache-2.0"]
89 | publish = true
90 | version {
91 | gpg {
92 | sign = true //Determines whether to GPG sign the files. The default is false
93 | passphrase = properties.getProperty("bintray.gpg.password")
94 | //Optional. The passphrase for GPG signing'
95 | }
96 | mavenCentralSync {
97 | sync = true
98 | //Optional (true by default). Determines whether to sync the version to Maven Central.
99 | user = properties.getProperty("bintray.oss.user") //OSS user token
100 | password = properties.getProperty("bintray.oss.password") //OSS user password
101 | close = '1'
102 | //Optional property. By default the staging repository is closed and artifacts are released to Maven Central. You can optionally turn this behaviour off (by puting 0 as value) and release the version manually.
103 | }
104 | }
105 | }
106 |
107 |
108 | }
109 | */
110 |
--------------------------------------------------------------------------------
/library/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jd-alexander/Google-Directions-Android/1020635df008737b2e4b956109e1b44693af95c6/library/ic_launcher-web.png
--------------------------------------------------------------------------------
/library/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/library/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/library/src/main/java/com/directions/route/AbstractRouting.java:
--------------------------------------------------------------------------------
1 | package com.directions.route;
2 |
3 | /**
4 | * Async Task to access the Google Direction API and return the routing data
5 | * which is then parsed and converting to a route overlay using some classes created by Hesham Saeed.
6 | * @author Joel Dean
7 | * @author Furkan Tektas
8 | * Requires an instance of the map activity and the application's current context for the progress dialog.
9 | *
10 | */
11 |
12 | import android.os.AsyncTask;
13 |
14 | import com.google.android.gms.maps.model.LatLng;
15 | import com.google.android.gms.maps.model.PolylineOptions;
16 |
17 | import java.util.ArrayList;
18 | import java.util.List;
19 |
20 |
21 | public abstract class AbstractRouting extends AsyncTask> {
22 | protected List alisteners;
23 |
24 | protected static final String DIRECTIONS_API_URL = "https://maps.googleapis.com/maps/api/directions/json?";
25 |
26 | /* Private member variable that will hold the RouteException instance created in the background thread */
27 | private RouteException mException = null;
28 |
29 | public enum TravelMode {
30 | BIKING("bicycling"),
31 | DRIVING("driving"),
32 | WALKING("walking"),
33 | TRANSIT("transit");
34 |
35 | protected String sValue;
36 |
37 | TravelMode(String sValue) {
38 | this.sValue = sValue;
39 | }
40 |
41 | protected String getValue() {
42 | return sValue;
43 | }
44 | }
45 |
46 | public enum AvoidKind {
47 | TOLLS (1, "tolls"),
48 | HIGHWAYS (1 << 1, "highways"),
49 | FERRIES (1 << 2, "ferries");
50 |
51 | private final String sRequestParam;
52 | private final int sBitValue;
53 |
54 | AvoidKind(int bit, String param) {
55 | this.sBitValue = bit;
56 | this.sRequestParam = param;
57 | }
58 |
59 | protected int getBitValue () {
60 | return sBitValue;
61 | }
62 |
63 | protected static String getRequestParam (int bit) {
64 | StringBuilder ret = new StringBuilder();
65 | for (AvoidKind kind : AvoidKind.values()) {
66 | if ((bit & kind.sBitValue) == kind.sBitValue) {
67 | ret.append(kind.sRequestParam).append('|');
68 | }
69 | }
70 | return ret.toString();
71 | }
72 | }
73 |
74 | protected AbstractRouting (RoutingListener listener) {
75 | this.alisteners = new ArrayList();
76 | registerListener(listener);
77 | }
78 |
79 | public void registerListener(RoutingListener mListener) {
80 | if (mListener != null) {
81 | alisteners.add(mListener);
82 | }
83 | }
84 |
85 | protected void dispatchOnStart() {
86 | for (RoutingListener mListener : alisteners) {
87 | mListener.onRoutingStart();
88 | }
89 | }
90 |
91 | protected void dispatchOnFailure(RouteException exception) {
92 | for (RoutingListener mListener : alisteners) {
93 | mListener.onRoutingFailure(exception);
94 | }
95 | }
96 |
97 | protected void dispatchOnSuccess(List route, int shortestRouteIndex) {
98 | for (RoutingListener mListener : alisteners) {
99 | mListener.onRoutingSuccess(route, shortestRouteIndex);
100 | }
101 | }
102 |
103 | private void dispatchOnCancelled() {
104 | for (RoutingListener mListener : alisteners) {
105 | mListener.onRoutingCancelled();
106 | }
107 | }
108 |
109 | /**
110 | * Performs the call to the google maps API to acquire routing data and
111 | * deserializes it to a format the map can display.
112 | *
113 | * @return an array list containing the routes
114 | */
115 | @Override
116 | protected List doInBackground(Void... voids) {
117 | List result = new ArrayList();
118 | try {
119 | result = new GoogleParser(constructURL()).parse();
120 | }catch(RouteException e){
121 | mException = e;
122 | }
123 | return result;
124 | }
125 |
126 | protected abstract String constructURL();
127 |
128 | @Override
129 | protected void onPreExecute() {
130 | dispatchOnStart();
131 | }
132 |
133 | @Override
134 | protected void onPostExecute(List result) {
135 | if (!result.isEmpty()) {
136 | int shortestRouteIndex = 0;
137 | int minDistance = Integer.MAX_VALUE;
138 |
139 | for (int i = 0; i < result.size(); i++) {
140 | PolylineOptions mOptions = new PolylineOptions();
141 | Route route = result.get(i);
142 |
143 | //Find the shortest route index
144 | if (route.getLength() < minDistance) {
145 | shortestRouteIndex = i;
146 | minDistance = route.getLength();
147 | }
148 |
149 | for (LatLng point : route.getPoints()) {
150 | mOptions.add(point);
151 | }
152 | result.get(i).setPolyOptions(mOptions);
153 | }
154 | dispatchOnSuccess(result, shortestRouteIndex);
155 | } else {
156 | dispatchOnFailure(mException);
157 | }
158 | }//end onPostExecute method
159 |
160 | @Override
161 | protected void onCancelled() {
162 | dispatchOnCancelled();
163 | }
164 |
165 | }
166 |
--------------------------------------------------------------------------------
/library/src/main/java/com/directions/route/GoogleParser.java:
--------------------------------------------------------------------------------
1 | package com.directions.route;
2 |
3 | import android.util.Log;
4 |
5 | import com.google.android.gms.maps.model.LatLng;
6 |
7 | import org.json.JSONArray;
8 | import org.json.JSONException;
9 | import org.json.JSONObject;
10 |
11 | import java.io.BufferedReader;
12 | import java.io.IOException;
13 | import java.io.InputStream;
14 | import java.io.InputStreamReader;
15 | import java.util.ArrayList;
16 | import java.util.List;
17 |
18 | public class GoogleParser extends XMLParser implements Parser {
19 |
20 | private static final String VALUE = "value";
21 | private static final String DISTANCE = "distance";
22 | /**
23 | * Distance covered. *
24 | */
25 | private int distance;
26 |
27 | /* Status code returned when the request succeeded */
28 | private static final String OK = "OK";
29 |
30 | public GoogleParser(String feedUrl) {
31 | super(feedUrl);
32 | }
33 |
34 | /**
35 | * Parses a url pointing to a Google JSON object to a Route object.
36 | *
37 | * @return a Route object based on the JSON object by Haseem Saheed
38 | */
39 |
40 | public final List parse() throws RouteException {
41 | List routes = new ArrayList<>();
42 |
43 | // turn the stream into a string
44 | final String result = convertStreamToString(this.getInputStream());
45 | if (result == null) {
46 | throw new RouteException("Result is null");
47 | }
48 |
49 | try {
50 | //Tranform the string into a json object
51 | final JSONObject json = new JSONObject(result);
52 | //Get the route object
53 |
54 | if(!json.getString("status").equals(OK)){
55 | throw new RouteException(json);
56 | }
57 |
58 | JSONArray jsonRoutes = json.getJSONArray("routes");
59 |
60 | for (int i = 0; i < jsonRoutes.length(); i++) {
61 | Route route = new Route();
62 | //Create an empty segment
63 | Segment segment = new Segment();
64 |
65 | JSONObject jsonRoute = jsonRoutes.getJSONObject(i);
66 | //Get the bounds - northeast and southwest
67 | final JSONObject jsonBounds = jsonRoute.getJSONObject("bounds");
68 | final JSONObject jsonNortheast = jsonBounds.getJSONObject("northeast");
69 | final JSONObject jsonSouthwest = jsonBounds.getJSONObject("southwest");
70 |
71 | route.setLatLgnBounds(new LatLng(jsonNortheast.getDouble("lat"), jsonNortheast.getDouble("lng")), new LatLng(jsonSouthwest.getDouble("lat"), jsonSouthwest.getDouble("lng")));
72 |
73 | //Get the leg, only one leg as we don't support waypoints
74 | final JSONObject leg = jsonRoute.getJSONArray("legs").getJSONObject(0);
75 | //Get the steps for this leg
76 | final JSONArray steps = leg.getJSONArray("steps");
77 | //Number of steps for use in for loop
78 | final int numSteps = steps.length();
79 | //Set the name of this route using the start & end addresses
80 | route.setName(leg.getString("start_address") + " to " + leg.getString("end_address"));
81 | //Get google's copyright notice (tos requirement)
82 | route.setCopyright(jsonRoute.getString("copyrights"));
83 | //Get distance and time estimation
84 | route.setDurationText(leg.getJSONObject("duration").getString("text"));
85 | route.setDurationValue(leg.getJSONObject("duration").getInt(VALUE));
86 | route.setDistanceText(leg.getJSONObject(DISTANCE).getString("text"));
87 | route.setDistanceValue(leg.getJSONObject(DISTANCE).getInt(VALUE));
88 | route.setEndAddressText(leg.getString("end_address"));
89 | //Get the total length of the route.
90 | route.setLength(leg.getJSONObject(DISTANCE).getInt(VALUE));
91 | //Get any warnings provided (tos requirement)
92 | if (!jsonRoute.getJSONArray("warnings").isNull(0)) {
93 | route.setWarning(jsonRoute.getJSONArray("warnings").getString(0));
94 | }
95 |
96 | /* Loop through the steps, creating a segment for each one and
97 | * decoding any polylines found as we go to add to the route object's
98 | * map array. Using an explicit for loop because it is faster!
99 | */
100 | for (int y = 0; y < numSteps; y++) {
101 | //Get the individual step
102 | final JSONObject step = steps.getJSONObject(y);
103 | //Get the start position for this step and set it on the segment
104 | final JSONObject start = step.getJSONObject("start_location");
105 | final LatLng position = new LatLng(start.getDouble("lat"),
106 | start.getDouble("lng"));
107 | segment.setPoint(position);
108 | //Set the length of this segment in metres
109 | final int length = step.getJSONObject(DISTANCE).getInt(VALUE);
110 | distance += length;
111 | segment.setLength(length);
112 | segment.setDistance((double)distance / (double)1000);
113 | //Strip html from google directions and set as turn instruction
114 | segment.setInstruction(step.getString("html_instructions").replaceAll("<(.*?)*>", ""));
115 |
116 | if(step.has("maneuver"))
117 | segment.setManeuver(step.getString("maneuver"));
118 |
119 | //Retrieve & decode this segment's polyline and add it to the route.
120 | route.addPoints(decodePolyLine(step.getJSONObject("polyline").getString("points")));
121 | //Push a copy of the segment to the route
122 | route.addSegment(segment.copy());
123 | }
124 |
125 | routes.add(route);
126 | }
127 |
128 | } catch (JSONException e) {
129 | throw new RouteException("JSONException. Msg: "+e.getMessage());
130 | }
131 | return routes;
132 | }
133 |
134 | /**
135 | * Convert an inputstream to a string.
136 | *
137 | * @param input inputstream to convert.
138 | * @return a String of the inputstream.
139 | */
140 |
141 | private static String convertStreamToString(final InputStream input) {
142 | if (input == null) return null;
143 |
144 | final BufferedReader reader = new BufferedReader(new InputStreamReader(input));
145 | final StringBuilder sBuf = new StringBuilder();
146 |
147 | String line;
148 | try {
149 | while ((line = reader.readLine()) != null) {
150 | sBuf.append(line);
151 | }
152 | } catch (IOException e) {
153 | Log.e("Routing Error", e.getMessage());
154 | } finally {
155 | try {
156 | input.close();
157 | reader.close();
158 | } catch (IOException e) {
159 | Log.e("Routing Error", e.getMessage());
160 | }
161 | }
162 | return sBuf.toString();
163 | }
164 |
165 | /**
166 | * Decode a polyline string into a list of GeoPoints.
167 | *
168 | * @param poly polyline encoded string to decode.
169 | * @return the list of GeoPoints represented by this polystring.
170 | */
171 |
172 | private List decodePolyLine(final String poly) {
173 | int len = poly.length();
174 | int index = 0;
175 | List decoded = new ArrayList();
176 | int lat = 0;
177 | int lng = 0;
178 |
179 | while (index < len) {
180 | int b;
181 | int shift = 0;
182 | int result = 0;
183 | do {
184 | b = poly.charAt(index++) - 63;
185 | result |= (b & 0x1f) << shift;
186 | shift += 5;
187 | } while (b >= 0x20);
188 | int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
189 | lat += dlat;
190 |
191 | shift = 0;
192 | result = 0;
193 | do {
194 | b = poly.charAt(index++) - 63;
195 | result |= (b & 0x1f) << shift;
196 | shift += 5;
197 | } while (b >= 0x20);
198 | int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
199 | lng += dlng;
200 |
201 | decoded.add(new LatLng(
202 | lat / 100000d, lng / 100000d
203 | ));
204 | }
205 |
206 | return decoded;
207 | }
208 | }
209 |
--------------------------------------------------------------------------------
/library/src/main/java/com/directions/route/Parser.java:
--------------------------------------------------------------------------------
1 | package com.directions.route;
2 |
3 | import java.util.List;
4 |
5 | //. by Haseem Saheed
6 | public interface Parser {
7 | List parse() throws RouteException;
8 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/directions/route/Route.java:
--------------------------------------------------------------------------------
1 | package com.directions.route;
2 | //by Haseem Saheed
3 |
4 | import android.os.Parcel;
5 | import android.os.Parcelable;
6 |
7 | import com.google.android.gms.maps.model.LatLng;
8 | import com.google.android.gms.maps.model.LatLngBounds;
9 | import com.google.android.gms.maps.model.PolylineOptions;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 |
14 | public class Route implements Parcelable {
15 | private String name;
16 | private final List points;
17 | private List segments;
18 | private String copyright;
19 | private String warning;
20 | private String country;
21 | private LatLngBounds latLgnBounds;
22 | private int length;
23 | private String polyline;
24 | private String durationText;
25 | private int durationValue;
26 | private String distanceText;
27 | private int distanceValue;
28 | private String endAddressText;
29 | private PolylineOptions polyOptions;
30 |
31 | public Route() {
32 | points = new ArrayList<>();
33 | segments = new ArrayList<>();
34 | }
35 |
36 | private Route(Parcel in) {
37 | name = in.readString();
38 |
39 | // points
40 | if (in.readInt() == 1) {
41 | points = new ArrayList<>();
42 | in.readList(points, LatLng.class.getClassLoader());
43 | } else {
44 | points = null;
45 | }
46 |
47 | // segments
48 | if (in.readInt() == 1) {
49 | segments = new ArrayList<>();
50 | in.readList(segments, Segment.class.getClassLoader());
51 | } else {
52 | segments = null;
53 | }
54 |
55 | copyright = in.readString();
56 | warning = in.readString();
57 | country = in.readString();
58 | latLgnBounds = in.readParcelable(LatLngBounds.class.getClassLoader());
59 | length = in.readInt();
60 | polyline = in.readString();
61 | durationText = in.readString();
62 | durationValue = in.readInt();
63 | distanceText = in.readString();
64 | distanceValue = in.readInt();
65 | endAddressText = in.readString();
66 | polyOptions = in.readParcelable(PolylineOptions.class.getClassLoader());
67 | }
68 |
69 | public PolylineOptions getPolyOptions() {
70 | return polyOptions;
71 | }
72 |
73 | public void setPolyOptions(PolylineOptions polyOptions) {
74 | this.polyOptions = polyOptions;
75 | }
76 |
77 | public String getEndAddressText() {
78 | return endAddressText;
79 | }
80 |
81 | public void setEndAddressText(String endAddressText) {
82 | this.endAddressText = endAddressText;
83 | }
84 |
85 | public String getDurationText() {
86 | return durationText;
87 | }
88 |
89 | public void setDurationText(String durationText) {
90 | this.durationText = durationText;
91 | }
92 |
93 | public String getDistanceText() {
94 | return distanceText;
95 | }
96 |
97 | public void setDistanceText(String distanceText) {
98 | this.distanceText = distanceText;
99 | }
100 |
101 | public int getDurationValue() {
102 | return durationValue;
103 | }
104 |
105 | public void setDurationValue(int durationValue) {
106 | this.durationValue = durationValue;
107 | }
108 |
109 | public int getDistanceValue() {
110 | return distanceValue;
111 | }
112 |
113 | public void setDistanceValue(int distanceValue) {
114 | this.distanceValue = distanceValue;
115 | }
116 |
117 | public void setSegments(List segments) {
118 | this.segments = segments;
119 | }
120 |
121 | public void addPoint(final LatLng p) {
122 | points.add(p);
123 | }
124 |
125 | public void addPoints(final List points) {
126 | this.points.addAll(points);
127 | }
128 |
129 | public List getPoints() {
130 | return points;
131 | }
132 |
133 | public void addSegment(final Segment s) {
134 | segments.add(s);
135 | }
136 |
137 | public List getSegments() {
138 | return segments;
139 | }
140 |
141 | /**
142 | * @param name the name to set
143 | */
144 | public void setName(final String name) {
145 | this.name = name;
146 | }
147 |
148 | /**
149 | * @return the name
150 | */
151 | public String getName() {
152 | return name;
153 | }
154 |
155 | /**
156 | * @param copyright the copyright to set
157 | */
158 | public void setCopyright(String copyright) {
159 | this.copyright = copyright;
160 | }
161 |
162 | /**
163 | * @return the copyright
164 | */
165 | public String getCopyright() {
166 | return copyright;
167 | }
168 |
169 | /**
170 | * @param warning the warning to set
171 | */
172 | public void setWarning(String warning) {
173 | this.warning = warning;
174 | }
175 |
176 | /**
177 | * @return the warning
178 | */
179 | public String getWarning() {
180 | return warning;
181 | }
182 |
183 | /**
184 | * @param country the country to set
185 | */
186 | public void setCountry(String country) {
187 | this.country = country;
188 | }
189 |
190 | /**
191 | * @return the country
192 | */
193 | public String getCountry() {
194 | return country;
195 | }
196 |
197 | /**
198 | * @param length the length to set
199 | */
200 | public void setLength(int length) {
201 | this.length = length;
202 | }
203 |
204 | /**
205 | * @return the length
206 | */
207 | public int getLength() {
208 | return length;
209 | }
210 |
211 | /**
212 | * @param polyline the polyline to set
213 | */
214 | public void setPolyline(String polyline) {
215 | this.polyline = polyline;
216 | }
217 |
218 | /**
219 | * @return the polyline
220 | */
221 | public String getPolyline() {
222 | return polyline;
223 | }
224 |
225 | /**
226 | * @return the LatLngBounds object to map camera
227 | */
228 | public LatLngBounds getLatLgnBounds() {
229 | return latLgnBounds;
230 | }
231 |
232 | public void setLatLgnBounds(LatLng northeast, LatLng southwest) {
233 | LatLngBounds.Builder builder = new LatLngBounds.Builder();
234 | builder.include(northeast);
235 | builder.include(southwest);
236 | this.latLgnBounds = builder.build();
237 | }
238 |
239 | @Override
240 | public int describeContents() {
241 | return hashCode();
242 | }
243 |
244 | @Override
245 | public void writeToParcel(Parcel dest, int flags) {
246 | dest.writeString(name);
247 |
248 | // points
249 | if (points == null) {
250 | dest.writeInt(0);
251 | } else {
252 | dest.writeInt(1);
253 | dest.writeList(points);
254 | }
255 |
256 | // segments
257 | if (segments == null) {
258 | dest.writeInt(0);
259 | } else {
260 | dest.writeInt(1);
261 | dest.writeList(segments);
262 | }
263 |
264 | dest.writeString(copyright);
265 | dest.writeString(warning);
266 | dest.writeString(country);
267 | dest.writeParcelable(latLgnBounds, flags);
268 | dest.writeInt(length);
269 | dest.writeString(polyline);
270 | dest.writeString(durationText);
271 | dest.writeInt(durationValue);
272 | dest.writeString(distanceText);
273 | dest.writeInt(distanceValue);
274 | dest.writeString(endAddressText);
275 | dest.writeParcelable(polyOptions, flags);
276 | }
277 |
278 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
279 | @Override
280 | public Route createFromParcel(Parcel in) {
281 | return new Route(in);
282 | }
283 |
284 | @Override
285 | public Route[] newArray(int size) {
286 | return new Route[size];
287 | }
288 | };
289 | }
290 |
291 |
--------------------------------------------------------------------------------
/library/src/main/java/com/directions/route/RouteException.java:
--------------------------------------------------------------------------------
1 | package com.directions.route;
2 |
3 | import android.util.Log;
4 |
5 | import org.json.JSONException;
6 | import org.json.JSONObject;
7 |
8 | /**
9 | * Created by nelson on 1/13/16.
10 | */
11 | public class RouteException extends Exception {
12 | private static final String TAG = "RouteException";
13 | private static final String KEY_STATUS = "status";
14 | private static final String KEY_MESSAGE = "error_message";
15 |
16 | private String statusCode;
17 | private String message;
18 |
19 | public RouteException(JSONObject json){
20 | if(json == null){
21 | statusCode = "";
22 | message = "Parsing error";
23 | return;
24 | }
25 | try {
26 | statusCode = json.getString(KEY_STATUS);
27 | message = json.getString(KEY_MESSAGE);
28 | } catch (JSONException e) {
29 | Log.e(TAG, "JSONException while parsing RouteException argument. Msg: " + e.getMessage());
30 | }
31 | }
32 |
33 | public RouteException(String msg){
34 | message = msg;
35 | }
36 |
37 | @Override
38 | public String getMessage() {
39 | return message;
40 | }
41 |
42 | public String getStatusCode() {
43 | return statusCode;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/library/src/main/java/com/directions/route/Routing.java:
--------------------------------------------------------------------------------
1 | package com.directions.route;
2 |
3 | import com.google.android.gms.maps.model.LatLng;
4 |
5 | import java.util.ArrayList;
6 | import java.util.Collections;
7 | import java.util.List;
8 |
9 | /**
10 | * Async Task to access the Google Direction API and return the routing data.
11 | * Created by Furkan Tektas on 10/14/14.
12 | */
13 | public class Routing extends AbstractRouting {
14 |
15 | private final TravelMode travelMode;
16 | private final boolean alternativeRoutes;
17 | private final List waypoints;
18 | private final int avoidKinds;
19 | private final boolean optimize;
20 | private final String language;
21 | private final String key;
22 |
23 | private Routing(Builder builder) {
24 | super(builder.listener);
25 | this.travelMode = builder.travelMode;
26 | this.waypoints = builder.waypoints;
27 | this.avoidKinds = builder.avoidKinds;
28 | this.optimize = builder.optimize;
29 | this.alternativeRoutes = builder.alternativeRoutes;
30 | this.language = builder.language;
31 | this.key = builder.key;
32 | }
33 |
34 | protected String constructURL () {
35 | final StringBuilder stringBuilder = new StringBuilder(AbstractRouting.DIRECTIONS_API_URL);
36 |
37 | // origin
38 | final LatLng origin = waypoints.get(0);
39 | stringBuilder.append("origin=")
40 | .append(origin.latitude)
41 | .append(',')
42 | .append(origin.longitude);
43 |
44 | // destination
45 | final LatLng destination = waypoints.get(waypoints.size() - 1);
46 | stringBuilder.append("&destination=")
47 | .append(destination.latitude)
48 | .append(',')
49 | .append(destination.longitude);
50 |
51 | // travel
52 | stringBuilder.append("&mode=").append(travelMode.getValue());
53 |
54 | // waypoints
55 | if (waypoints.size() > 2) {
56 | stringBuilder.append("&waypoints=");
57 | if(optimize)
58 | stringBuilder.append("optimize:true|");
59 | for (int i = 1; i < waypoints.size() - 1; i++) {
60 | final LatLng p = waypoints.get(i);
61 | stringBuilder.append("via:"); // we don't want to parse the resulting JSON for 'legs'.
62 | stringBuilder.append(p.latitude);
63 | stringBuilder.append(',');
64 | stringBuilder.append(p.longitude);
65 | stringBuilder.append('|');
66 | }
67 | }
68 |
69 | // avoid
70 | if (avoidKinds > 0) {
71 | stringBuilder.append("&avoid=");
72 | stringBuilder.append(AvoidKind.getRequestParam(avoidKinds));
73 | }
74 |
75 | if (alternativeRoutes) {
76 | stringBuilder.append("&alternatives=true");
77 | }
78 |
79 | // sensor
80 | stringBuilder.append("&sensor=true");
81 |
82 | // language
83 | if (language != null) {
84 | stringBuilder.append("&language=").append(language);
85 | }
86 |
87 | // API key
88 | if(key != null) {
89 | stringBuilder.append("&key=").append(key);
90 | }
91 | return stringBuilder.toString();
92 | }
93 |
94 | public static class Builder {
95 |
96 | private TravelMode travelMode;
97 | private boolean alternativeRoutes;
98 | private List waypoints;
99 | private int avoidKinds;
100 | private RoutingListener listener;
101 | private boolean optimize;
102 | private String language;
103 | private String key;
104 |
105 | public Builder () {
106 | this.travelMode = TravelMode.DRIVING;
107 | this.alternativeRoutes = false;
108 | this.waypoints = new ArrayList<>();
109 | this.avoidKinds = 0;
110 | this.listener = null;
111 | this.optimize = false;
112 | this.language = null;
113 | this.key = null;
114 | }
115 |
116 | public Builder travelMode (TravelMode travelMode) {
117 | this.travelMode = travelMode;
118 | return this;
119 | }
120 |
121 | public Builder alternativeRoutes (boolean alternativeRoutes) {
122 | this.alternativeRoutes = alternativeRoutes;
123 | return this;
124 | }
125 |
126 | public Builder waypoints (LatLng... points) {
127 | waypoints.clear();
128 | Collections.addAll(waypoints, points);
129 | return this;
130 | }
131 |
132 | public Builder waypoints (List waypoints) {
133 | this.waypoints = new ArrayList<>(waypoints);
134 | return this;
135 | }
136 |
137 | public Builder optimize(boolean optimize) {
138 | this.optimize = optimize;
139 | return this;
140 | }
141 |
142 | public Builder avoid (AvoidKind... avoids) {
143 | for (AvoidKind avoidKind : avoids) {
144 | this.avoidKinds |= avoidKind.getBitValue();
145 | }
146 | return this;
147 | }
148 |
149 | public Builder language (String language) {
150 | this.language = language;
151 | return this;
152 | }
153 |
154 | public Builder key(String key) {
155 | this.key = key;
156 | return this;
157 | }
158 |
159 | public Builder withListener (RoutingListener listener) {
160 | this.listener = listener;
161 | return this;
162 | }
163 |
164 | public Routing build () {
165 | if (this.waypoints.size() < 2) {
166 | throw new IllegalArgumentException("Must supply at least two waypoints to route between.");
167 | }
168 | if (this.waypoints.size() <= 2 && this.optimize) {
169 | throw new IllegalArgumentException("You need at least three waypoints to enable optimize");
170 | }
171 | return new Routing(this);
172 | }
173 |
174 | }
175 |
176 | }
177 |
--------------------------------------------------------------------------------
/library/src/main/java/com/directions/route/RoutingListener.java:
--------------------------------------------------------------------------------
1 | package com.directions.route;
2 |
3 | import java.util.List;
4 |
5 | public interface RoutingListener {
6 | void onRoutingFailure(RouteException e);
7 |
8 | void onRoutingStart();
9 |
10 | void onRoutingSuccess(List route, int shortestRouteIndex);
11 |
12 | void onRoutingCancelled();
13 | }
14 |
--------------------------------------------------------------------------------
/library/src/main/java/com/directions/route/Segment.java:
--------------------------------------------------------------------------------
1 | package com.directions.route;
2 | //by Haseem Saheed
3 |
4 | import android.os.Parcel;
5 | import android.os.Parcelable;
6 |
7 | import com.google.android.gms.maps.model.LatLng;
8 |
9 | public class Segment implements Parcelable {
10 | /**
11 | * Points in this segment. *
12 | */
13 | private LatLng start;
14 | /**
15 | * Turn instruction to reach next segment. *
16 | */
17 | private String instruction;
18 | /**
19 | * Length of segment. *
20 | */
21 | private int length;
22 | /**
23 | * Distance covered. *
24 | */
25 | private double distance;
26 |
27 | /* Maneuver instructions */
28 | private String maneuver;
29 |
30 | /**
31 | * Create an empty segment.
32 | */
33 |
34 | public Segment() {
35 | }
36 |
37 | private Segment(Parcel in) {
38 | start = in.readParcelable(LatLng.class.getClassLoader());
39 | instruction = in.readString();
40 | length = in.readInt();
41 | distance = in.readDouble();
42 | maneuver = in.readString();
43 | }
44 |
45 | /**
46 | * Set the turn instruction.
47 | *
48 | * @param turn Turn instruction string.
49 | */
50 |
51 | public void setInstruction(final String turn) {
52 | this.instruction = turn;
53 | }
54 |
55 | /**
56 | * Get the turn instruction to reach next segment.
57 | *
58 | * @return a String of the turn instruction.
59 | */
60 |
61 | public String getInstruction() {
62 | return instruction;
63 | }
64 |
65 | /**
66 | * Add a point to this segment.
67 | *
68 | * @param point GeoPoint to add.
69 | */
70 |
71 | public void setPoint(final LatLng point) {
72 | start = point;
73 | }
74 |
75 | /**
76 | * Get the starting point of this
77 | * segment.
78 | *
79 | * @return a GeoPoint
80 | */
81 |
82 | public LatLng startPoint() {
83 | return start;
84 | }
85 |
86 | /**
87 | * Creates a segment which is a copy of this one.
88 | *
89 | * @return a Segment that is a copy of this one.
90 | */
91 |
92 | public Segment copy() {
93 | final Segment copy = new Segment();
94 | copy.start = start;
95 | copy.instruction = instruction;
96 | copy.length = length;
97 | copy.distance = distance;
98 | copy.maneuver = maneuver;
99 | return copy;
100 | }
101 |
102 | /**
103 | * @param length the length to set
104 | */
105 | public void setLength(final int length) {
106 | this.length = length;
107 | }
108 |
109 | /**
110 | * @return the length
111 | */
112 | public int getLength() {
113 | return length;
114 | }
115 |
116 | /**
117 | * @param distance the distance to set
118 | */
119 | public void setDistance(double distance) {
120 | this.distance = distance;
121 | }
122 |
123 | /**
124 | * @return the distance
125 | */
126 | public double getDistance() {
127 | return distance;
128 | }
129 |
130 | public void setManeuver(String man) {
131 | maneuver = man;
132 | }
133 |
134 | public String getManeuver() {
135 | return maneuver;
136 | }
137 |
138 | @Override
139 | public int describeContents() {
140 | return hashCode();
141 | }
142 |
143 | @Override
144 | public void writeToParcel(Parcel dest, int flags) {
145 | dest.writeParcelable(start, flags);
146 | dest.writeString(instruction);
147 | dest.writeInt(length);
148 | dest.writeDouble(distance);
149 | dest.writeString(maneuver);
150 | }
151 |
152 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
153 | @Override
154 | public Segment createFromParcel(Parcel in) {
155 | return new Segment(in);
156 | }
157 |
158 | @Override
159 | public Segment[] newArray(int size) {
160 | return new Segment[size];
161 | }
162 | };
163 | }
164 |
--------------------------------------------------------------------------------
/library/src/main/java/com/directions/route/XMLParser.java:
--------------------------------------------------------------------------------
1 | package com.directions.route;
2 | //by Haseem Saheed
3 |
4 | import android.util.Log;
5 |
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 | import java.net.MalformedURLException;
9 | import java.net.URL;
10 |
11 | public class XMLParser {
12 | // names of the XML tags
13 | protected static final String MARKERS = "markers";
14 | protected static final String MARKER = "marker";
15 |
16 | protected URL feedUrl;
17 |
18 | protected XMLParser(final String feedUrl) {
19 | try {
20 | this.feedUrl = new URL(feedUrl);
21 | } catch (MalformedURLException e) {
22 | Log.e("Routing Error", e.getMessage());
23 | }
24 | }
25 |
26 | protected InputStream getInputStream() {
27 | try {
28 | return feedUrl.openConnection().getInputStream();
29 | } catch (IOException e) {
30 | Log.e("Routing Error", "Exception: " + e.getMessage());
31 | return null;
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/sample/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/sample/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 22
5 | buildToolsVersion "22.0.1"
6 |
7 | defaultConfig {
8 | applicationId "com.directions.sample"
9 | minSdkVersion 15
10 | targetSdkVersion 22
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | compile 'com.android.support:appcompat-v7:22.2.0'
25 | compile project(':library')
26 | compile "com.google.android.gms:play-services-location:7.5.0"
27 | compile 'com.android.support:cardview-v7:21.0.2'
28 | compile 'com.jakewharton:butterknife:6.1.0'
29 | }
30 |
--------------------------------------------------------------------------------
/sample/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\Users\Joel\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/sample/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
23 |
26 |
27 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/directions/sample/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.directions.sample;
2 |
3 | import android.app.ProgressDialog;
4 | import android.location.Location;
5 | import android.location.LocationListener;
6 | import android.location.LocationManager;
7 | import android.os.Bundle;
8 | import android.support.v7.app.AppCompatActivity;
9 | import android.text.Editable;
10 | import android.text.TextWatcher;
11 | import android.util.Log;
12 | import android.view.View;
13 | import android.widget.AdapterView;
14 | import android.widget.AutoCompleteTextView;
15 | import android.widget.ImageView;
16 | import android.widget.Toast;
17 |
18 | import com.directions.route.AbstractRouting;
19 | import com.directions.route.Route;
20 | import com.directions.route.RouteException;
21 | import com.directions.route.Routing;
22 | import com.directions.route.RoutingListener;
23 | import com.google.android.gms.common.ConnectionResult;
24 | import com.google.android.gms.common.api.GoogleApiClient;
25 | import com.google.android.gms.common.api.PendingResult;
26 | import com.google.android.gms.common.api.ResultCallback;
27 | import com.google.android.gms.location.places.Place;
28 | import com.google.android.gms.location.places.PlaceBuffer;
29 | import com.google.android.gms.location.places.Places;
30 | import com.google.android.gms.maps.CameraUpdate;
31 | import com.google.android.gms.maps.CameraUpdateFactory;
32 | import com.google.android.gms.maps.GoogleMap;
33 | import com.google.android.gms.maps.MapsInitializer;
34 | import com.google.android.gms.maps.SupportMapFragment;
35 | import com.google.android.gms.maps.model.BitmapDescriptorFactory;
36 | import com.google.android.gms.maps.model.CameraPosition;
37 | import com.google.android.gms.maps.model.LatLng;
38 | import com.google.android.gms.maps.model.LatLngBounds;
39 | import com.google.android.gms.maps.model.MarkerOptions;
40 | import com.google.android.gms.maps.model.Polyline;
41 | import com.google.android.gms.maps.model.PolylineOptions;
42 |
43 | import java.util.ArrayList;
44 | import java.util.List;
45 |
46 | import butterknife.ButterKnife;
47 | import butterknife.InjectView;
48 | import butterknife.OnClick;
49 |
50 | public class MainActivity extends AppCompatActivity implements RoutingListener, GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks {
51 | protected GoogleMap map;
52 | protected LatLng start;
53 | protected LatLng end;
54 | @InjectView(R.id.start)
55 | AutoCompleteTextView starting;
56 | @InjectView(R.id.destination)
57 | AutoCompleteTextView destination;
58 | @InjectView(R.id.send)
59 | ImageView send;
60 | private static final String LOG_TAG = "MyActivity";
61 | protected GoogleApiClient mGoogleApiClient;
62 | private PlaceAutoCompleteAdapter mAdapter;
63 | private ProgressDialog progressDialog;
64 | private List polylines;
65 | private static final int[] COLORS = new int[]{R.color.primary_dark,R.color.primary,R.color.primary_light,R.color.accent,R.color.primary_dark_material_light};
66 |
67 |
68 | private static final LatLngBounds BOUNDS_JAMAICA= new LatLngBounds(new LatLng(-57.965341647205726, 144.9987719580531),
69 | new LatLng(72.77492067739843, -9.998857788741589));
70 |
71 | /**
72 | * This activity loads a map and then displays the route and pushpins on it.
73 | */
74 | @Override
75 | public void onCreate(Bundle savedInstanceState) {
76 | super.onCreate(savedInstanceState);
77 | setContentView(R.layout.activity_main);
78 | ButterKnife.inject(this);
79 | getSupportActionBar().setDisplayShowHomeEnabled(true);
80 |
81 | polylines = new ArrayList<>();
82 | mGoogleApiClient = new GoogleApiClient.Builder(this)
83 | .addApi(Places.GEO_DATA_API)
84 | .addConnectionCallbacks(this)
85 | .addOnConnectionFailedListener(this)
86 | .build();
87 | MapsInitializer.initialize(this);
88 | mGoogleApiClient.connect();
89 |
90 | SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
91 |
92 | if (mapFragment == null) {
93 | mapFragment = SupportMapFragment.newInstance();
94 | getSupportFragmentManager().beginTransaction().replace(R.id.map, mapFragment).commit();
95 | }
96 | map = mapFragment.getMap();
97 |
98 | mAdapter = new PlaceAutoCompleteAdapter(this, android.R.layout.simple_list_item_1,
99 | mGoogleApiClient, BOUNDS_JAMAICA, null);
100 |
101 |
102 | /*
103 | * Updates the bounds being used by the auto complete adapter based on the position of the
104 | * map.
105 | * */
106 | map.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
107 | @Override
108 | public void onCameraChange(CameraPosition position) {
109 | LatLngBounds bounds = map.getProjection().getVisibleRegion().latLngBounds;
110 | mAdapter.setBounds(bounds);
111 | }
112 | });
113 |
114 |
115 | CameraUpdate center = CameraUpdateFactory.newLatLng(new LatLng(18.013610, -77.498803));
116 | CameraUpdate zoom = CameraUpdateFactory.zoomTo(16);
117 |
118 | map.moveCamera(center);
119 | map.animateCamera(zoom);
120 |
121 | LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
122 |
123 | locationManager.requestLocationUpdates(
124 | LocationManager.NETWORK_PROVIDER, 5000, 0,
125 | new LocationListener() {
126 | @Override
127 | public void onLocationChanged(Location location) {
128 |
129 | CameraUpdate center = CameraUpdateFactory.newLatLng(new LatLng(location.getLatitude(),location.getLongitude()));
130 | CameraUpdate zoom = CameraUpdateFactory.zoomTo(16);
131 |
132 | map.moveCamera(center);
133 | map.animateCamera(zoom);
134 | }
135 |
136 | @Override
137 | public void onStatusChanged(String provider, int status, Bundle extras) {
138 |
139 | }
140 |
141 | @Override
142 | public void onProviderEnabled(String provider) {
143 |
144 | }
145 |
146 | @Override
147 | public void onProviderDisabled(String provider) {
148 |
149 | }
150 | });
151 |
152 |
153 | locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
154 | 3000, 0, new LocationListener() {
155 | @Override
156 | public void onLocationChanged(Location location) {
157 | CameraUpdate center = CameraUpdateFactory.newLatLng(new LatLng(location.getLatitude(),location.getLongitude()));
158 | CameraUpdate zoom = CameraUpdateFactory.zoomTo(16);
159 |
160 | map.moveCamera(center);
161 | map.animateCamera(zoom);
162 |
163 | }
164 |
165 | @Override
166 | public void onStatusChanged(String provider, int status, Bundle extras) {
167 |
168 | }
169 |
170 | @Override
171 | public void onProviderEnabled(String provider) {
172 |
173 | }
174 |
175 | @Override
176 | public void onProviderDisabled(String provider) {
177 |
178 | }
179 | });
180 |
181 |
182 |
183 | /*
184 | * Adds auto complete adapter to both auto complete
185 | * text views.
186 | * */
187 | starting.setAdapter(mAdapter);
188 | destination.setAdapter(mAdapter);
189 |
190 |
191 | /*
192 | * Sets the start and destination points based on the values selected
193 | * from the autocomplete text views.
194 | * */
195 |
196 | starting.setOnItemClickListener(new AdapterView.OnItemClickListener() {
197 | @Override
198 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
199 |
200 | final PlaceAutoCompleteAdapter.PlaceAutocomplete item = mAdapter.getItem(position);
201 | final String placeId = String.valueOf(item.placeId);
202 | Log.i(LOG_TAG, "Autocomplete item selected: " + item.description);
203 |
204 | /*
205 | Issue a request to the Places Geo Data API to retrieve a Place object with additional
206 | details about the place.
207 | */
208 | PendingResult placeResult = Places.GeoDataApi
209 | .getPlaceById(mGoogleApiClient, placeId);
210 | placeResult.setResultCallback(new ResultCallback() {
211 | @Override
212 | public void onResult(PlaceBuffer places) {
213 | if (!places.getStatus().isSuccess()) {
214 | // Request did not complete successfully
215 | Log.e(LOG_TAG, "Place query did not complete. Error: " + places.getStatus().toString());
216 | places.release();
217 | return;
218 | }
219 | // Get the Place object from the buffer.
220 | final Place place = places.get(0);
221 |
222 | start=place.getLatLng();
223 | }
224 | });
225 |
226 | }
227 | });
228 | destination.setOnItemClickListener(new AdapterView.OnItemClickListener() {
229 | @Override
230 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
231 |
232 | final PlaceAutoCompleteAdapter.PlaceAutocomplete item = mAdapter.getItem(position);
233 | final String placeId = String.valueOf(item.placeId);
234 | Log.i(LOG_TAG, "Autocomplete item selected: " + item.description);
235 |
236 | /*
237 | Issue a request to the Places Geo Data API to retrieve a Place object with additional
238 | details about the place.
239 | */
240 | PendingResult placeResult = Places.GeoDataApi
241 | .getPlaceById(mGoogleApiClient, placeId);
242 | placeResult.setResultCallback(new ResultCallback() {
243 | @Override
244 | public void onResult(PlaceBuffer places) {
245 | if (!places.getStatus().isSuccess()) {
246 | // Request did not complete successfully
247 | Log.e(LOG_TAG, "Place query did not complete. Error: " + places.getStatus().toString());
248 | places.release();
249 | return;
250 | }
251 | // Get the Place object from the buffer.
252 | final Place place = places.get(0);
253 |
254 | end=place.getLatLng();
255 | }
256 | });
257 |
258 | }
259 | });
260 |
261 | /*
262 | These text watchers set the start and end points to null because once there's
263 | * a change after a value has been selected from the dropdown
264 | * then the value has to reselected from dropdown to get
265 | * the correct location.
266 | * */
267 | starting.addTextChangedListener(new TextWatcher() {
268 | @Override
269 | public void beforeTextChanged(CharSequence s, int start, int count, int after) {
270 |
271 | }
272 |
273 | @Override
274 | public void onTextChanged(CharSequence s, int startNum, int before, int count) {
275 | if (start != null) {
276 | start = null;
277 | }
278 | }
279 |
280 | @Override
281 | public void afterTextChanged(Editable s) {
282 |
283 | }
284 | });
285 |
286 | destination.addTextChangedListener(new TextWatcher() {
287 | @Override
288 | public void beforeTextChanged(CharSequence s, int start, int count, int after) {
289 |
290 | }
291 |
292 | @Override
293 | public void onTextChanged(CharSequence s, int start, int before, int count) {
294 |
295 |
296 | if(end!=null)
297 | {
298 | end=null;
299 | }
300 | }
301 |
302 | @Override
303 | public void afterTextChanged(Editable s) {
304 |
305 | }
306 | });
307 |
308 | }
309 |
310 | @OnClick(R.id.send)
311 | public void sendRequest()
312 | {
313 | if(Util.Operations.isOnline(this))
314 | {
315 | route();
316 | }
317 | else
318 | {
319 | Toast.makeText(this,"No internet connectivity",Toast.LENGTH_SHORT).show();
320 | }
321 | }
322 |
323 | public void route()
324 | {
325 | if(start==null || end==null)
326 | {
327 | if(start==null)
328 | {
329 | if(starting.getText().length()>0)
330 | {
331 | starting.setError("Choose location from dropdown.");
332 | }
333 | else
334 | {
335 | Toast.makeText(this,"Please choose a starting point.",Toast.LENGTH_SHORT).show();
336 | }
337 | }
338 | if(end==null)
339 | {
340 | if(destination.getText().length()>0)
341 | {
342 | destination.setError("Choose location from dropdown.");
343 | }
344 | else
345 | {
346 | Toast.makeText(this,"Please choose a destination.",Toast.LENGTH_SHORT).show();
347 | }
348 | }
349 | }
350 | else
351 | {
352 | progressDialog = ProgressDialog.show(this, "Please wait.",
353 | "Fetching route information.", true);
354 | Routing routing = new Routing.Builder()
355 | .travelMode(AbstractRouting.TravelMode.DRIVING)
356 | .withListener(this)
357 | .alternativeRoutes(true)
358 | .waypoints(start, end)
359 | .build();
360 | routing.execute();
361 | }
362 | }
363 |
364 |
365 | @Override
366 | public void onRoutingFailure(RouteException e) {
367 | // The Routing request failed
368 | progressDialog.dismiss();
369 | if(e != null) {
370 | Toast.makeText(this, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
371 | }else {
372 | Toast.makeText(this, "Something went wrong, Try again", Toast.LENGTH_SHORT).show();
373 | }
374 | }
375 |
376 | @Override
377 | public void onRoutingStart() {
378 | // The Routing Request starts
379 | }
380 |
381 | @Override
382 | public void onRoutingSuccess(List route, int shortestRouteIndex)
383 | {
384 | progressDialog.dismiss();
385 | CameraUpdate center = CameraUpdateFactory.newLatLng(start);
386 | CameraUpdate zoom = CameraUpdateFactory.zoomTo(16);
387 |
388 | map.moveCamera(center);
389 |
390 |
391 | if(polylines.size()>0) {
392 | for (Polyline poly : polylines) {
393 | poly.remove();
394 | }
395 | }
396 |
397 | polylines = new ArrayList<>();
398 | //add route(s) to the map.
399 | for (int i = 0; i
46 | * objects
47 | * that contain both the Place ID and the text description from the autocomplete query.
48 | *
49 | * Note that this adapter requires a valid {@link GoogleApiClient}.
50 | * The API client must be maintained in the encapsulating Activity, including all lifecycle and
51 | * connection states. The API client must be connected with the {@link Places#GEO_DATA_API} API.
52 | */
53 | public class PlaceAutoCompleteAdapter
54 | extends ArrayAdapter implements Filterable {
55 |
56 | private static final String TAG = "PlaceAutocomplete";
57 | /**
58 | * Current results returned by this adapter.
59 | */
60 | private ArrayList mResultList;
61 |
62 | /**
63 | * Handles autocomplete requests.
64 | */
65 | private final GoogleApiClient mGoogleApiClient;
66 |
67 | /**
68 | * The bounds used for Places Geo Data autocomplete API requests.
69 | */
70 | private LatLngBounds mBounds;
71 |
72 | /**
73 | * The autocomplete filter used to restrict queries to a specific set of place types.
74 | */
75 | private final AutocompleteFilter mPlaceFilter;
76 |
77 | /**
78 | * Initializes with a resource for text rows and autocomplete query bounds.
79 | *
80 | * @see ArrayAdapter#ArrayAdapter(Context, int)
81 | */
82 | public PlaceAutoCompleteAdapter(Context context, int resource, GoogleApiClient googleApiClient,
83 | LatLngBounds bounds, AutocompleteFilter filter) {
84 | super(context, resource);
85 | mGoogleApiClient = googleApiClient;
86 | mBounds = bounds;
87 | mPlaceFilter = filter;
88 | }
89 |
90 | /**
91 | * Sets the bounds for all subsequent queries.
92 | */
93 | public void setBounds(LatLngBounds bounds) {
94 | mBounds = bounds;
95 | }
96 |
97 | /**
98 | * Returns the number of results received in the last autocomplete query.
99 | */
100 | @Override
101 | public int getCount() {
102 | return mResultList.size();
103 | }
104 |
105 | /**
106 | * Returns an item from the last autocomplete query.
107 | */
108 | @Override
109 | public PlaceAutocomplete getItem(int position) {
110 | return mResultList.get(position);
111 | }
112 |
113 | /**
114 | * Returns the filter for the current set of autocomplete results.
115 | */
116 | @Override
117 | public Filter getFilter() {
118 | Filter filter = new Filter() {
119 | @Override
120 | protected FilterResults performFiltering(CharSequence constraint) {
121 | FilterResults results = new FilterResults();
122 | // Skip the autocomplete query if no constraints are given.
123 | if (constraint != null) {
124 | // Query the autocomplete API for the (constraint) search string.
125 | mResultList = getAutocomplete(constraint);
126 | if (mResultList != null) {
127 | // The API successfully returned results.
128 | results.values = mResultList;
129 | results.count = mResultList.size();
130 | }
131 | }
132 | return results;
133 | }
134 |
135 | @Override
136 | protected void publishResults(CharSequence constraint, FilterResults results) {
137 | if (results != null && results.count > 0) {
138 | // The API returned at least one result, update the data.
139 | notifyDataSetChanged();
140 | } else {
141 | // The API did not return any results, invalidate the data set.
142 | notifyDataSetInvalidated();
143 | }
144 | }
145 | };
146 | return filter;
147 | }
148 |
149 | /**
150 | * Submits an autocomplete query to the Places Geo Data Autocomplete API.
151 | *
152 | * objects to store the Place ID and description that the API returns.
153 | * Returns an empty list if no results were found.
154 | * Returns null if the API client is not available or the query did not complete
155 | * successfully.
156 | * This method MUST be called off the main UI thread, as it will block until data is returned
157 | * from the API, which may include a network request.
158 | *
159 | * @param constraint Autocomplete query string
160 | * @return Results from the autocomplete API or null if the query was not successful.
161 | * @see Places#GEO_DATA_API#getAutocomplete(CharSequence)
162 | */
163 | private ArrayList getAutocomplete(CharSequence constraint) {
164 | if (mGoogleApiClient.isConnected()) {
165 | Log.i(TAG, "Starting autocomplete query for: " + constraint);
166 |
167 | // Submit the query to the autocomplete API and retrieve a PendingResult that will
168 | // contain the results when the query completes.
169 | PendingResult results =
170 | Places.GeoDataApi
171 | .getAutocompletePredictions(mGoogleApiClient, constraint.toString(),
172 | mBounds, mPlaceFilter);
173 |
174 | // This method should have been called off the main UI thread. Block and wait for at most 60s
175 | // for a result from the API.
176 | AutocompletePredictionBuffer autocompletePredictions = results
177 | .await(60, TimeUnit.SECONDS);
178 |
179 | // Confirm that the query completed successfully, otherwise return null
180 | final Status status = autocompletePredictions.getStatus();
181 | if (!status.isSuccess()) {
182 | Toast.makeText(getContext(), "Error contacting API: " + status.toString(),
183 | Toast.LENGTH_SHORT).show();
184 | Log.e(TAG, "Error getting autocomplete prediction API call: " + status.getStatusMessage()+status.getStatus().getStatusMessage());
185 | autocompletePredictions.release();
186 | return null;
187 | }
188 |
189 | Log.i(TAG, "Query completed. Received " + autocompletePredictions.getCount()
190 | + " predictions.");
191 |
192 | // Copy the results into our own data structure, because we can't hold onto the buffer.
193 | // AutocompletePrediction objects encapsulate the API response (place ID and description).
194 |
195 | Iterator iterator = autocompletePredictions.iterator();
196 | ArrayList resultList = new ArrayList<>(autocompletePredictions.getCount());
197 | while (iterator.hasNext()) {
198 | AutocompletePrediction prediction = iterator.next();
199 | // Get the details of this prediction and copy it into a new PlaceAutocomplete object.
200 | resultList.add(new PlaceAutocomplete(prediction.getPlaceId(),
201 | prediction.getDescription()));
202 | }
203 |
204 | // Release the buffer now that all data has been copied.
205 | autocompletePredictions.release();
206 |
207 | return resultList;
208 | }
209 | Log.e(TAG, "Google API client is not connected for autocomplete query.");
210 | return null;
211 | }
212 |
213 | /**
214 | * Holder for Places Geo Data Autocomplete API results.
215 | */
216 | class PlaceAutocomplete {
217 |
218 | public CharSequence placeId;
219 | public CharSequence description;
220 |
221 | PlaceAutocomplete(CharSequence placeId, CharSequence description) {
222 | this.placeId = placeId;
223 | this.description = description;
224 | }
225 |
226 | @Override
227 | public String toString() {
228 | return description.toString();
229 | }
230 |
231 |
232 | }
233 |
234 | }
--------------------------------------------------------------------------------
/sample/src/main/java/com/directions/sample/Util.java:
--------------------------------------------------------------------------------
1 | package com.directions.sample;
2 |
3 | import android.content.Context;
4 | import android.net.ConnectivityManager;
5 | import android.net.NetworkInfo;
6 |
7 | /**
8 | * Created by Joel on 30/06/2015.
9 | */
10 | public final class Util {
11 | public static final class Operations {
12 | private Operations() throws InstantiationException {
13 | throw new InstantiationException("This class is not for instantiation");
14 | }
15 | /**
16 | * Checks to see if the device is online before carrying out any operations.
17 | *
18 | * @return
19 | */
20 | public static boolean isOnline(Context context) {
21 | ConnectivityManager cm =
22 | (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
23 | NetworkInfo netInfo = cm.getActiveNetworkInfo();
24 | if (netInfo != null && netInfo.isConnectedOrConnecting()) {
25 | return true;
26 | }
27 | return false;
28 | }
29 | }
30 | private Util() throws InstantiationException {
31 | throw new InstantiationException("This class is not for instantiation");
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xhdpi/Thumbs.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jd-alexander/Google-Directions-Android/1020635df008737b2e4b956109e1b44693af95c6/sample/src/main/res/drawable-xhdpi/Thumbs.db
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xhdpi/end_green.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jd-alexander/Google-Directions-Android/1020635df008737b2e4b956109e1b44693af95c6/sample/src/main/res/drawable-xhdpi/end_green.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xhdpi/ic_send_grey600_48dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jd-alexander/Google-Directions-Android/1020635df008737b2e4b956109e1b44693af95c6/sample/src/main/res/drawable-xhdpi/ic_send_grey600_48dp.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xhdpi/pushpin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jd-alexander/Google-Directions-Android/1020635df008737b2e4b956109e1b44693af95c6/sample/src/main/res/drawable-xhdpi/pushpin.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xhdpi/start_blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jd-alexander/Google-Directions-Android/1020635df008737b2e4b956109e1b44693af95c6/sample/src/main/res/drawable-xhdpi/start_blue.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable/Thumbs.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jd-alexander/Google-Directions-Android/1020635df008737b2e4b956109e1b44693af95c6/sample/src/main/res/drawable/Thumbs.db
--------------------------------------------------------------------------------
/sample/src/main/res/drawable/dotted.xml:
--------------------------------------------------------------------------------
1 |
2 | -
7 |
8 |
9 |
14 |
15 |
16 |
17 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
25 |
26 |
30 |
31 |
36 |
37 |
44 |
45 |
52 |
53 |
59 |
60 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/sample/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jd-alexander/Google-Directions-Android/1020635df008737b2e4b956109e1b44693af95c6/sample/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jd-alexander/Google-Directions-Android/1020635df008737b2e4b956109e1b44693af95c6/sample/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jd-alexander/Google-Directions-Android/1020635df008737b2e4b956109e1b44693af95c6/sample/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jd-alexander/Google-Directions-Android/1020635df008737b2e4b956109e1b44693af95c6/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jd-alexander/Google-Directions-Android/1020635df008737b2e4b956109e1b44693af95c6/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #00BCD4
4 | #0097A7
5 | #B2EBF2
6 | #607D8B
7 | #212121
8 | #727272
9 | #FFFFFF
10 | #B6B6B6
11 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Google Directions Sample
3 |
4 | Hello world!
5 | Settings
6 |
7 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/screenshots/Thumbs.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jd-alexander/Google-Directions-Android/1020635df008737b2e4b956109e1b44693af95c6/screenshots/Thumbs.db
--------------------------------------------------------------------------------
/screenshots/device-2015-06-30-095135.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jd-alexander/Google-Directions-Android/1020635df008737b2e4b956109e1b44693af95c6/screenshots/device-2015-06-30-095135.png
--------------------------------------------------------------------------------
/screenshots/device-2015-06-30-095241.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jd-alexander/Google-Directions-Android/1020635df008737b2e4b956109e1b44693af95c6/screenshots/device-2015-06-30-095241.png
--------------------------------------------------------------------------------
/screenshots/device-2015-06-30-095323.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jd-alexander/Google-Directions-Android/1020635df008737b2e4b956109e1b44693af95c6/screenshots/device-2015-06-30-095323.png
--------------------------------------------------------------------------------
/screenshots/device-2015-06-30-100949.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jd-alexander/Google-Directions-Android/1020635df008737b2e4b956109e1b44693af95c6/screenshots/device-2015-06-30-100949.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':library', ':sample'
--------------------------------------------------------------------------------