├── .gitignore ├── .idea ├── .name ├── caches │ ├── build_file_checksums.ser │ └── gradle_models.ser ├── codeStyles │ └── Project.xml ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── migrations.xml ├── misc.xml └── modules.xml ├── LICENSE ├── README.md ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── src └── main ├── AndroidManifest.xml ├── java ├── android │ └── UnusedStub.java └── tw │ └── kewang │ └── mapcontroller │ └── MapController.java └── res └── values └── version.xml /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/android,gradle,intellij 3 | 4 | ### Android ### 5 | # Built application files 6 | *.apk 7 | *.ap_ 8 | 9 | # Files for the Dalvik VM 10 | *.dex 11 | 12 | # Java class files 13 | *.class 14 | 15 | # Generated files 16 | bin/ 17 | gen/ 18 | out/ 19 | 20 | # Gradle files 21 | .gradle/ 22 | build/ 23 | 24 | # Local configuration file (sdk path, etc) 25 | local.properties 26 | 27 | # Proguard folder generated by Eclipse 28 | proguard/ 29 | 30 | # Log Files 31 | *.log 32 | 33 | # Android Studio Navigation editor temp files 34 | .navigation/ 35 | 36 | # Android Studio captures folder 37 | captures/ 38 | 39 | # Intellij 40 | *.iml 41 | 42 | # Keystore files 43 | *.jks 44 | 45 | ### Android Patch ### 46 | gen-external-apklibs 47 | 48 | 49 | ### Gradle ### 50 | .gradle 51 | build/ 52 | 53 | # Ignore Gradle GUI config 54 | gradle-app.setting 55 | 56 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 57 | !gradle-wrapper.jar 58 | 59 | # Cache of project 60 | .gradletasknamecache 61 | 62 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 63 | # gradle/wrapper/gradle-wrapper.properties 64 | 65 | 66 | ### Intellij ### 67 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 68 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 69 | 70 | # User-specific stuff: 71 | .idea/workspace.xml 72 | .idea/tasks.xml 73 | .idea/dictionaries 74 | .idea/vcs.xml 75 | .idea/jsLibraryMappings.xml 76 | 77 | # Sensitive or high-churn files: 78 | .idea/dataSources.ids 79 | .idea/dataSources.xml 80 | .idea/dataSources.local.xml 81 | .idea/sqlDataSources.xml 82 | .idea/dynamic.xml 83 | .idea/uiDesigner.xml 84 | 85 | # Gradle: 86 | .idea/gradle.xml 87 | .idea/libraries 88 | 89 | # Mongo Explorer plugin: 90 | .idea/mongoSettings.xml 91 | 92 | ## File-based project format: 93 | *.iws 94 | 95 | ## Plugin-specific files: 96 | 97 | # IntelliJ 98 | /out/ 99 | 100 | # mpeltonen/sbt-idea plugin 101 | .idea_modules/ 102 | 103 | # JIRA plugin 104 | atlassian-ide-plugin.xml 105 | 106 | # Crashlytics plugin (for Android Studio and IntelliJ) 107 | com_crashlytics_export_strings.xml 108 | crashlytics.properties 109 | crashlytics-build.properties 110 | fabric.properties 111 | 112 | ### Intellij Patch ### 113 | *.iml 114 | 115 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | map-controller -------------------------------------------------------------------------------- /.idea/caches/build_file_checksums.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kewang/map-controller/1a9a4dba4f0ec18510eaae7eed655ececcdb44e4/.idea/caches/build_file_checksums.ser -------------------------------------------------------------------------------- /.idea/caches/gradle_models.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kewang/map-controller/1a9a4dba4f0ec18510eaae7eed655ececcdb44e4/.idea/caches/gradle_models.ser -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 | 8 | 9 | 10 | xmlns:android 11 | 12 | ^$ 13 | 14 | 15 | 16 |
17 |
18 | 19 | 20 | 21 | xmlns:.* 22 | 23 | ^$ 24 | 25 | 26 | BY_NAME 27 | 28 |
29 |
30 | 31 | 32 | 33 | .*:id 34 | 35 | http://schemas.android.com/apk/res/android 36 | 37 | 38 | 39 |
40 |
41 | 42 | 43 | 44 | .*:name 45 | 46 | http://schemas.android.com/apk/res/android 47 | 48 | 49 | 50 |
51 |
52 | 53 | 54 | 55 | name 56 | 57 | ^$ 58 | 59 | 60 | 61 |
62 |
63 | 64 | 65 | 66 | style 67 | 68 | ^$ 69 | 70 | 71 | 72 |
73 |
74 | 75 | 76 | 77 | .* 78 | 79 | ^$ 80 | 81 | 82 | BY_NAME 83 | 84 |
85 |
86 | 87 | 88 | 89 | .* 90 | 91 | http://schemas.android.com/apk/res/android 92 | 93 | 94 | ANDROID_ATTRIBUTE_ORDER 95 | 96 |
97 |
98 | 99 | 100 | 101 | .* 102 | 103 | .* 104 | 105 | 106 | BY_NAME 107 | 108 |
109 |
110 |
111 |
112 |
113 |
-------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/migrations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 29 | 48 | 49 | 50 | 51 | 52 | 53 | 55 | 56 | 57 | 58 | 59 | 1.7 60 | 61 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Kewang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Release](https://jitpack.io/v/kewang/map-controller.svg)](https://jitpack.io/#kewang/map-controller) 2 | 3 | # map-controller 4 | 5 | Control Google Maps v2 for Android 6 | 7 | ## Samples 8 | 9 | https://github.com/kewang/map-controller-samples 10 | 11 | ## Prerequisite 12 | 13 | You must know how to set up your Maps v2 from [official article](https://developers.google.com/maps/documentation/android/start). 14 | 15 | ## Dependency 16 | 17 | ### Gradle 18 | 19 | ```gradle 20 | allprojects { 21 | repositories { 22 | maven { url "https://jitpack.io" } 23 | } 24 | } 25 | ``` 26 | 27 | ```gradle 28 | dependencies { 29 | compile 'com.github.kewang:map-controller:v2.1.0' 30 | } 31 | ``` 32 | 33 | ### Maven 34 | 35 | ```xml 36 | 37 | 38 | jitpack.io 39 | https://jitpack.io 40 | 41 | 42 | ``` 43 | 44 | ```xml 45 | 46 | com.github.kewang 47 | map-controller 48 | v2.1.0 49 | 50 | ``` 51 | 52 | ## How to use 53 | 54 | ### Initialize 55 | 56 | At first, you must use to `MapController#initialize(Context)` to initial Google Maps at `android.app.Application` and remember to update `AndroidManifest.xml`. 57 | 58 | ```java 59 | @Override 60 | public void onCreate() { 61 | super.onCreate(); 62 | 63 | try { 64 | MapController.initialize(this); 65 | } catch (GooglePlayServicesNotAvailableException e) { 66 | e.printStackTrace(); 67 | 68 | Toast.makeText(this, R.string.common_google_play_services_enable_text, Toast.Length_SHORT).show(); 69 | } 70 | } 71 | ``` 72 | 73 | ### Attach 74 | 75 | When using it, You must create an instance to attach map from `MapView` / `MapFragment`'s instance. 76 | 77 | ```java 78 | public class MainActivity extends Activity implements MapControllerReady { 79 | private MapView mv; 80 | private MapController mc; 81 | 82 | @Override 83 | protected void onCreate(Bundle savedInstanceState) { 84 | setContentView(R.layout.main); 85 | 86 | mv = (MapView) findViewById(R.id.map); 87 | 88 | mc = new MapController(mv, this); 89 | // or use below statement 90 | // new MapController(mv, this); 91 | } 92 | 93 | @Override 94 | public void already(MapController controller) { 95 | controller.moveToMyLocation(); 96 | } 97 | } 98 | ``` 99 | 100 | ### Show my location 101 | 102 | Typically, you can use `MapController#showMyLocation()` to show your location. 103 | 104 | ### Move to my location 105 | 106 | You can use `MapController#moveToMyLocation()` to move your current location. Also you can use `MapController#animateToMyLocation()` to move smoothly. 107 | 108 | ### Get my location 109 | 110 | You can use `MapController#getMyLocation()` to get your current location. 111 | 112 | ### Tracking my location 113 | 114 | If you want to track your location at runtime and do something. You can use `MapController#startTrackMyLocation()` like this: 115 | 116 | ```java 117 | mc.startTrackMyLocation(new ChangeMyLocation() { 118 | @Override 119 | public void changed(GoogleMap map, Location location, boolean lastLocation) { 120 | Toast.makeText(TrackingMyLocation.this, location.toString(), Toast.LENGTH_SHORT).show(); 121 | } 122 | }); 123 | ``` 124 | 125 | And don't forget to stop tracking `MapController#stopTrackMyLocation()` when you leave the activity or service. 126 | 127 | ### Move to specific location 128 | 129 | If you want to move to specific location, you can use `MapController#moveTo(LatLng)` or `MapController#animateTo(LatLng)` like this: 130 | 131 | ```java 132 | LatLng latLng = new LatLng(25.03338, 121.56463); 133 | 134 | mc.animateTo(latLng, new ChangePosition() { 135 | @Override 136 | public void changed(GoogleMap map, CameraPosition position) { 137 | Toast.makeText(ShowSpecificLocation.this, position.toString(), Toast.LENGTH_SHORT).show(); 138 | } 139 | }); 140 | ``` 141 | 142 | ### Add marker 143 | 144 | You can use `MapController#addMarker(MarkerOptions)` to add marker to map, like this: 145 | 146 | ```java 147 | mc.addMarker(opts, new MarkerCallback() { 148 | @Override 149 | public void invokedMarker(GoogleMap map, Marker marker) { 150 | Toast.makeText(AddMarker.this, marker.getId(), Toast.LENGTH_SHORT).show(); 151 | } 152 | }); 153 | ``` 154 | 155 | ### Add bulk markers 156 | 157 | You can also use `MapController#addMarkers(ArrayList)` to add bulk markers to map. 158 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'maven-publish' 3 | 4 | group="com.github.kewang" 5 | 6 | buildscript { 7 | repositories { 8 | google() 9 | mavenCentral() 10 | } 11 | 12 | dependencies { 13 | classpath 'com.android.tools.build:gradle:3.6.4' 14 | } 15 | } 16 | 17 | dependencies { 18 | implementation 'com.google.android.gms:play-services-location:21.2.0' 19 | implementation 'com.google.android.gms:play-services-maps:18.2.0' 20 | } 21 | 22 | android { 23 | compileSdkVersion 34 24 | buildToolsVersion "29.0.2" 25 | 26 | defaultConfig { 27 | minSdkVersion 23 28 | targetSdkVersion 34 29 | versionCode 5 30 | versionName "3.0.0" 31 | } 32 | compileOptions { 33 | sourceCompatibility JavaVersion.VERSION_1_8 34 | targetCompatibility JavaVersion.VERSION_1_8 35 | } 36 | } 37 | 38 | allprojects { 39 | repositories { 40 | google() 41 | mavenCentral() 42 | } 43 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | android.useAndroidX=true 2 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kewang/map-controller/1a9a4dba4f0ec18510eaae7eed655ececcdb44e4/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Mar 21 00:27:54 CST 2024 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.4-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | # Determine the Java command to use to start the JVM. 86 | if [ -n "$JAVA_HOME" ] ; then 87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 88 | # IBM's JDK on AIX uses strange locations for the executables 89 | JAVACMD="$JAVA_HOME/jre/sh/java" 90 | else 91 | JAVACMD="$JAVA_HOME/bin/java" 92 | fi 93 | if [ ! -x "$JAVACMD" ] ; then 94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 95 | 96 | Please set the JAVA_HOME variable in your environment to match the 97 | location of your Java installation." 98 | fi 99 | else 100 | JAVACMD="java" 101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 102 | 103 | Please set the JAVA_HOME variable in your environment to match the 104 | location of your Java installation." 105 | fi 106 | 107 | # Increase the maximum file descriptors if we can. 108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 109 | MAX_FD_LIMIT=`ulimit -H -n` 110 | if [ $? -eq 0 ] ; then 111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 112 | MAX_FD="$MAX_FD_LIMIT" 113 | fi 114 | ulimit -n $MAX_FD 115 | if [ $? -ne 0 ] ; then 116 | warn "Could not set maximum file descriptor limit: $MAX_FD" 117 | fi 118 | else 119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 120 | fi 121 | fi 122 | 123 | # For Darwin, add options to specify how the application appears in the dock 124 | if $darwin; then 125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 126 | fi 127 | 128 | # For Cygwin or MSYS, switch paths to Windows format before running java 129 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 132 | JAVACMD=`cygpath --unix "$JAVACMD"` 133 | 134 | # We build the pattern for arguments to be converted via cygpath 135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 136 | SEP="" 137 | for dir in $ROOTDIRSRAW ; do 138 | ROOTDIRS="$ROOTDIRS$SEP$dir" 139 | SEP="|" 140 | done 141 | OURCYGPATTERN="(^($ROOTDIRS))" 142 | # Add a user-defined pattern to the cygpath arguments 143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 145 | fi 146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 147 | i=0 148 | for arg in "$@" ; do 149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 151 | 152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 154 | else 155 | eval `echo args$i`="\"$arg\"" 156 | fi 157 | i=$((i+1)) 158 | done 159 | case $i in 160 | (0) set -- ;; 161 | (1) set -- "$args0" ;; 162 | (2) set -- "$args0" "$args1" ;; 163 | (3) set -- "$args0" "$args1" "$args2" ;; 164 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 165 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 166 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 167 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 168 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 169 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 170 | esac 171 | fi 172 | 173 | # Escape application args 174 | save () { 175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 176 | echo " " 177 | } 178 | APP_ARGS=$(save "$@") 179 | 180 | # Collect all arguments for the java command, following the shell quoting and substitution rules 181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 182 | 183 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 184 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 185 | cd "$(dirname "$0")" 186 | fi 187 | 188 | exec "$JAVACMD" "$@" 189 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 34 | 35 | @rem Find java.exe 36 | if defined JAVA_HOME goto findJavaFromJavaHome 37 | 38 | set JAVA_EXE=java.exe 39 | %JAVA_EXE% -version >NUL 2>&1 40 | if "%ERRORLEVEL%" == "0" goto init 41 | 42 | echo. 43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 44 | echo. 45 | echo Please set the JAVA_HOME variable in your environment to match the 46 | echo location of your Java installation. 47 | 48 | goto fail 49 | 50 | :findJavaFromJavaHome 51 | set JAVA_HOME=%JAVA_HOME:"=% 52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 53 | 54 | if exist "%JAVA_EXE%" goto init 55 | 56 | echo. 57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 58 | echo. 59 | echo Please set the JAVA_HOME variable in your environment to match the 60 | echo location of your Java installation. 61 | 62 | goto fail 63 | 64 | :init 65 | @rem Get command-line arguments, handling Windows variants 66 | 67 | if not "%OS%" == "Windows_NT" goto win9xME_args 68 | 69 | :win9xME_args 70 | @rem Slurp the command line arguments. 71 | set CMD_LINE_ARGS= 72 | set _SKIP=2 73 | 74 | :win9xME_args_slurp 75 | if "x%~1" == "x" goto execute 76 | 77 | set CMD_LINE_ARGS=%* 78 | 79 | :execute 80 | @rem Setup the command line 81 | 82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 83 | 84 | @rem Execute Gradle 85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 86 | 87 | :end 88 | @rem End local scope for the variables with windows NT shell 89 | if "%ERRORLEVEL%"=="0" goto mainEnd 90 | 91 | :fail 92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 93 | rem the _cmd.exe /c_ return code! 94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 95 | exit /b 1 96 | 97 | :mainEnd 98 | if "%OS%"=="Windows_NT" endlocal 99 | 100 | :omega 101 | -------------------------------------------------------------------------------- /src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/main/java/android/UnusedStub.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package android; 17 | 18 | // Stub java file to make inclusion into some IDE's work. 19 | public final class UnusedStub { 20 | private UnusedStub() { } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/tw/kewang/mapcontroller/MapController.java: -------------------------------------------------------------------------------- 1 | package tw.kewang.mapcontroller; 2 | 3 | import android.Manifest; 4 | import android.app.ProgressDialog; 5 | import android.content.Context; 6 | import android.content.pm.PackageManager; 7 | import android.location.Address; 8 | import android.location.Geocoder; 9 | import android.location.Location; 10 | import android.os.AsyncTask; 11 | import android.util.Log; 12 | import android.view.View; 13 | 14 | import androidx.core.app.ActivityCompat; 15 | 16 | import com.google.android.gms.location.FusedLocationProviderClient; 17 | import com.google.android.gms.location.LocationCallback; 18 | import com.google.android.gms.location.LocationRequest; 19 | import com.google.android.gms.location.LocationResult; 20 | import com.google.android.gms.location.LocationServices; 21 | import com.google.android.gms.maps.CameraUpdate; 22 | import com.google.android.gms.maps.CameraUpdateFactory; 23 | import com.google.android.gms.maps.GoogleMap; 24 | import com.google.android.gms.maps.GoogleMap.InfoWindowAdapter; 25 | import com.google.android.gms.maps.GoogleMap.OnCameraIdleListener; 26 | import com.google.android.gms.maps.GoogleMap.OnMarkerDragListener; 27 | import com.google.android.gms.maps.MapFragment; 28 | import com.google.android.gms.maps.MapView; 29 | import com.google.android.gms.maps.MapsInitializer; 30 | import com.google.android.gms.maps.model.CameraPosition; 31 | import com.google.android.gms.maps.model.LatLng; 32 | import com.google.android.gms.maps.model.LatLngBounds; 33 | import com.google.android.gms.maps.model.Marker; 34 | import com.google.android.gms.maps.model.MarkerOptions; 35 | 36 | import java.io.IOException; 37 | import java.util.ArrayList; 38 | 39 | /** 40 | * @author kewang 41 | */ 42 | public class MapController { 43 | private static final String TAG = MapController.class.getSimpleName(); 44 | 45 | private Context context; 46 | private GoogleMap map; 47 | private ArrayList markers; 48 | private OnCameraIdleListener cameraIdleListener; 49 | private FusedLocationProviderClient fusedLocationProviderClient; 50 | private LocationCallback locationCallback; 51 | 52 | /** 53 | * attach Google Maps 54 | * 55 | * @param map 56 | */ 57 | public MapController(Context context, GoogleMap map) { 58 | if (map == null) { 59 | Log.e(TAG, "GoogleMap can't not be null."); 60 | 61 | throw new RuntimeException("GoogleMap can't not be null."); 62 | } 63 | 64 | this.map = map; 65 | } 66 | 67 | public MapController(MapView mapView, MapControllerReady callback) { 68 | mapView.getMapAsync(googleMap -> { 69 | this.map = googleMap; 70 | this.context = mapView.getContext(); 71 | 72 | if (callback != null) { 73 | callback.already(this); 74 | } 75 | }); 76 | } 77 | 78 | public MapController(MapFragment mapFragment, MapControllerReady callback) { 79 | mapFragment.getMapAsync(googleMap -> { 80 | this.map = googleMap; 81 | this.context = mapFragment.getContext(); 82 | 83 | if (callback != null) { 84 | callback.already(this); 85 | } 86 | }); 87 | } 88 | 89 | private MapController() { 90 | } 91 | 92 | /** 93 | * initialize Google Maps 94 | * 95 | * @param context 96 | */ 97 | public static void initialize(Context context) { 98 | MapsInitializer.initialize(context); 99 | } 100 | 101 | /** 102 | * return map's instance 103 | * 104 | * @return 105 | */ 106 | public GoogleMap getMap() { 107 | return map; 108 | } 109 | 110 | /** 111 | * return the type of map that's currently displayed. 112 | * 113 | * @return 114 | */ 115 | public MapType getType() { 116 | return MapType.valueOf(String.valueOf(map.getMapType())); 117 | } 118 | 119 | /** 120 | * sets the type of map tiles that should be displayed 121 | * 122 | * @param type 123 | */ 124 | public void setType(MapType type) { 125 | map.setMapType(type.ordinal()); 126 | } 127 | 128 | /** 129 | * start tracking my current location 130 | * 131 | * @param map 132 | * @param interval 133 | * @param numUpdates 134 | * @param type 135 | * @param callback 136 | */ 137 | public void startTrackMyLocation(GoogleMap map, long interval, int numUpdates, TrackType type, ChangeMyLocation callback) { 138 | if (fusedLocationProviderClient == null) { 139 | fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context); 140 | } 141 | 142 | LocationRequest request = LocationRequest.create().setInterval(interval).setFastestInterval(16).setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); 143 | 144 | if (numUpdates != 0) { 145 | request.setNumUpdates(numUpdates); 146 | } 147 | 148 | locationCallback = new LocationCallback() { 149 | @Override 150 | public void onLocationResult(LocationResult locationResult) { 151 | Location location1 = locationResult.getLastLocation(); 152 | 153 | if (map != null) { 154 | CameraUpdate latLng = CameraUpdateFactory.newLatLng(new LatLng(location1.getLatitude(), location1.getLongitude())); 155 | 156 | if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { 157 | // TODO: Consider calling 158 | // ActivityCompat#requestPermissions 159 | // here to request the missing permissions, and then overriding 160 | // public void onRequestPermissionsResult(int requestCode, String[] permissions, 161 | // int[] grantResults) 162 | // to handle the case where the user grants the permission. See the documentation 163 | // for ActivityCompat#requestPermissions for more details. 164 | return; 165 | } 166 | 167 | map.setMyLocationEnabled(true); 168 | 169 | if (type == TrackType.TRACK_TYPE_MOVE) { 170 | map.moveCamera(latLng); 171 | } else if (type == TrackType.TRACK_TYPE_ANIMATE) { 172 | map.animateCamera(latLng); 173 | } 174 | } 175 | 176 | if (callback != null) { 177 | callback.changed(map, location1); 178 | } 179 | } 180 | }; 181 | 182 | fusedLocationProviderClient.requestLocationUpdates(request, locationCallback, null); 183 | } 184 | 185 | /** 186 | * start tracking my current location 187 | * 188 | * @param callback 189 | */ 190 | public void startTrackMyLocation(ChangeMyLocation callback) { 191 | startTrackMyLocation(map, 5000, 0, TrackType.TRACK_TYPE_ANIMATE, callback); 192 | } 193 | 194 | /** 195 | * start tracking my current location 196 | * 197 | * @param interval 198 | * @param numUpdates 199 | * @param callback 200 | */ 201 | public void startTrackMyLocation(long interval, int numUpdates, ChangeMyLocation callback) { 202 | startTrackMyLocation(map, interval, numUpdates, TrackType.TRACK_TYPE_ANIMATE, callback); 203 | } 204 | 205 | /** 206 | * stop tracking my current location 207 | */ 208 | public void stopTrackMyLocation() { 209 | fusedLocationProviderClient.removeLocationUpdates(locationCallback); 210 | 211 | locationCallback = null; 212 | } 213 | 214 | /** 215 | * move to my current location 216 | * 217 | * @param callback 218 | */ 219 | public void moveToMyLocation(ChangeMyLocation callback) { 220 | startTrackMyLocation(map, 5000, 1, TrackType.TRACK_TYPE_MOVE, callback); 221 | } 222 | 223 | /** 224 | * move to my current location 225 | */ 226 | public void moveToMyLocation() { 227 | moveToMyLocation(null); 228 | } 229 | 230 | /** 231 | * move to my current location 232 | * 233 | * @param callback 234 | */ 235 | public void animateToMyLocation(ChangeMyLocation callback) { 236 | startTrackMyLocation(map, 5000, 1, TrackType.TRACK_TYPE_ANIMATE, callback); 237 | } 238 | 239 | /** 240 | * move to my current location 241 | */ 242 | public void animateToMyLocation() { 243 | animateToMyLocation(null); 244 | } 245 | 246 | /** 247 | * show my current location 248 | */ 249 | public void showMyLocation() { 250 | if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { 251 | // TODO: Consider calling 252 | // ActivityCompat#requestPermissions 253 | // here to request the missing permissions, and then overriding 254 | // public void onRequestPermissionsResult(int requestCode, String[] permissions, 255 | // int[] grantResults) 256 | // to handle the case where the user grants the permission. See the documentation 257 | // for ActivityCompat#requestPermissions for more details. 258 | return; 259 | } 260 | 261 | map.setMyLocationEnabled(true); 262 | } 263 | 264 | /** 265 | * animate to specific location 266 | * 267 | * @param latLng 268 | * @param zoom 269 | * @param callback 270 | */ 271 | public void animateTo(LatLng latLng, int zoom, ChangePosition callback) { 272 | if (cameraIdleListener == null) { 273 | cameraIdleListener = () -> { 274 | map.setOnCameraIdleListener(null); 275 | 276 | cameraIdleListener = null; 277 | 278 | if (callback != null) { 279 | callback.changed(map, map.getCameraPosition()); 280 | } 281 | }; 282 | 283 | map.setOnCameraIdleListener(cameraIdleListener); 284 | } 285 | 286 | map.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, zoom)); 287 | } 288 | 289 | /** 290 | * animate to specific location 291 | * 292 | * @param latLng 293 | */ 294 | public void animateTo(LatLng latLng) { 295 | animateTo(latLng, (int) map.getCameraPosition().zoom, null); 296 | } 297 | 298 | /** 299 | * animate to specific location 300 | * 301 | * @param latLng 302 | * @param callback 303 | */ 304 | public void animateTo(LatLng latLng, ChangePosition callback) { 305 | animateTo(latLng, (int) map.getCameraPosition().zoom, callback); 306 | } 307 | 308 | /** 309 | * animate to specific location 310 | * 311 | * @param lat 312 | * @param lng 313 | * @param callback 314 | */ 315 | public void animateTo(double lat, double lng, ChangePosition callback) { 316 | animateTo(new LatLng(lat, lng), (int) map.getCameraPosition().zoom, callback); 317 | } 318 | 319 | /** 320 | * animate to specific location 321 | * 322 | * @param lat 323 | * @param lng 324 | */ 325 | public void animateTo(double lat, double lng) { 326 | animateTo(new LatLng(lat, lng), (int) map.getCameraPosition().zoom, null); 327 | } 328 | 329 | /** 330 | * animate and zoom to specific location 331 | * 332 | * @param latLng 333 | * @param zoom 334 | */ 335 | public void animateTo(LatLng latLng, int zoom) { 336 | animateTo(latLng, zoom, null); 337 | } 338 | 339 | /** 340 | * animate and zoom to specific location 341 | * 342 | * @param lat 343 | * @param lng 344 | * @param zoom 345 | */ 346 | public void animateTo(double lat, double lng, int zoom) { 347 | animateTo(new LatLng(lat, lng), zoom, null); 348 | } 349 | 350 | /** 351 | * animate and zoom to specific location 352 | * 353 | * @param lat 354 | * @param lng 355 | * @param zoom 356 | * @param callback 357 | */ 358 | public void animateTo(double lat, double lng, int zoom, ChangePosition callback) { 359 | animateTo(new LatLng(lat, lng), zoom, callback); 360 | } 361 | 362 | /** 363 | * move to specific location 364 | * 365 | * @param latLng 366 | * @param callback 367 | */ 368 | public void moveTo(LatLng latLng, int zoom, ChangePosition callback) { 369 | if (cameraIdleListener == null) { 370 | cameraIdleListener = () -> { 371 | map.setOnCameraIdleListener(null); 372 | 373 | cameraIdleListener = null; 374 | 375 | if (callback != null) { 376 | callback.changed(map, map.getCameraPosition()); 377 | } 378 | }; 379 | 380 | map.setOnCameraIdleListener(cameraIdleListener); 381 | } 382 | 383 | map.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, zoom)); 384 | } 385 | 386 | /** 387 | * move to specific location 388 | * 389 | * @param latLng 390 | */ 391 | public void moveTo(LatLng latLng) { 392 | moveTo(latLng, (int) map.getCameraPosition().zoom, null); 393 | } 394 | 395 | /** 396 | * move to specific location 397 | * 398 | * @param latLng 399 | * @param callback 400 | */ 401 | public void moveTo(LatLng latLng, ChangePosition callback) { 402 | moveTo(latLng, (int) map.getCameraPosition().zoom, callback); 403 | } 404 | 405 | /** 406 | * move to specific location 407 | * 408 | * @param lat 409 | * @param lng 410 | * @param callback 411 | */ 412 | public void moveTo(double lat, double lng, ChangePosition callback) { 413 | moveTo(new LatLng(lat, lng), (int) map.getCameraPosition().zoom, callback); 414 | } 415 | 416 | /** 417 | * move to specific location 418 | * 419 | * @param lat 420 | * @param lng 421 | */ 422 | public void moveTo(double lat, double lng) { 423 | moveTo(new LatLng(lat, lng), (int) map.getCameraPosition().zoom, null); 424 | } 425 | 426 | /** 427 | * move and zoom to specific location 428 | * 429 | * @param latLng 430 | * @param zoom 431 | */ 432 | public void moveTo(LatLng latLng, int zoom) { 433 | moveTo(latLng, zoom, null); 434 | } 435 | 436 | /** 437 | * move and zoom to specific location 438 | * 439 | * @param lat 440 | * @param lng 441 | * @param zoom 442 | */ 443 | public void moveTo(double lat, double lng, int zoom) { 444 | moveTo(new LatLng(lat, lng), zoom, null); 445 | } 446 | 447 | /** 448 | * move and zoom to specific location 449 | * 450 | * @param lat 451 | * @param lng 452 | * @param zoom 453 | * @param callback 454 | */ 455 | public void moveTo(double lat, double lng, int zoom, ChangePosition callback) { 456 | moveTo(new LatLng(lat, lng), zoom, callback); 457 | } 458 | 459 | /** 460 | * @param southwest 461 | * @param northeast 462 | * @param padding 463 | * @param smooth 464 | * @param callback 465 | */ 466 | public void setBounds(LatLng southwest, LatLng northeast, int padding, boolean smooth, ChangePosition callback) { 467 | if (cameraIdleListener == null) { 468 | cameraIdleListener = () -> { 469 | map.setOnCameraIdleListener(null); 470 | 471 | cameraIdleListener = null; 472 | 473 | if (callback != null) { 474 | callback.changed(map, map.getCameraPosition()); 475 | } 476 | }; 477 | 478 | map.setOnCameraIdleListener(cameraIdleListener); 479 | } 480 | 481 | if (smooth) { 482 | map.animateCamera(CameraUpdateFactory.newLatLngBounds(new LatLngBounds(southwest, northeast), padding)); 483 | } else { 484 | map.moveCamera(CameraUpdateFactory.newLatLngBounds(new LatLngBounds(southwest, northeast), padding)); 485 | } 486 | } 487 | 488 | /** 489 | * @param southwest 490 | * @param northeast 491 | * @param padding 492 | * @param smooth 493 | */ 494 | public void setBounds(LatLng southwest, LatLng northeast, int padding, boolean smooth) { 495 | setBounds(southwest, northeast, padding, smooth, null); 496 | } 497 | 498 | /** 499 | * @param southwest 500 | * @param northeast 501 | * @param padding 502 | */ 503 | public void setBounds(LatLng southwest, LatLng northeast, int padding) { 504 | setBounds(southwest, northeast, padding, true, null); 505 | } 506 | 507 | /** 508 | * @param swLat 509 | * @param swLng 510 | * @param neLat 511 | * @param neLng 512 | * @param padding 513 | * @param smooth 514 | */ 515 | public void setBounds(double swLat, double swLng, double neLat, double neLng, int padding, boolean smooth) { 516 | setBounds(new LatLng(swLat, swLng), new LatLng(neLat, neLng), padding, smooth, null); 517 | } 518 | 519 | /** 520 | * @param swLat 521 | * @param swLng 522 | * @param neLat 523 | * @param neLng 524 | * @param padding 525 | */ 526 | public void setBounds(double swLat, double swLng, double neLat, double neLng, int padding) { 527 | setBounds(new LatLng(swLat, swLng), new LatLng(neLat, neLng), padding, true, null); 528 | } 529 | 530 | /** 531 | * @param swLat 532 | * @param swLng 533 | * @param neLat 534 | * @param neLng 535 | * @param padding 536 | * @param callback 537 | */ 538 | public void setBounds(double swLat, double swLng, double neLat, double neLng, int padding, ChangePosition callback) { 539 | setBounds(new LatLng(swLat, swLng), new LatLng(neLat, neLng), padding, true, callback); 540 | } 541 | 542 | /** 543 | * zoom map 544 | * 545 | * @param zoom 546 | * @param smooth 547 | * @param callback 548 | */ 549 | public void zoomTo(int zoom, boolean smooth, ChangePosition callback) { 550 | if (smooth) { 551 | animateTo(map.getCameraPosition().target, zoom, callback); 552 | } else { 553 | moveTo(map.getCameraPosition().target, zoom, callback); 554 | } 555 | } 556 | 557 | /** 558 | * zoom map 559 | * 560 | * @param zoom 561 | */ 562 | public void zoomTo(int zoom) { 563 | zoomTo(zoom, true, null); 564 | } 565 | 566 | /** 567 | * zoom map 568 | * 569 | * @param zoom 570 | * @param callback 571 | */ 572 | public void zoomTo(int zoom, ChangePosition callback) { 573 | zoomTo(zoom, true, callback); 574 | } 575 | 576 | /** 577 | * zoom map 578 | * 579 | * @param zoom 580 | * @param smooth 581 | */ 582 | public void zoomTo(int zoom, boolean smooth) { 583 | zoomTo(zoom, smooth, null); 584 | } 585 | 586 | /** 587 | * zoom map in 588 | */ 589 | public void zoomIn() { 590 | zoomTo((int) (map.getCameraPosition().zoom + 1), true, null); 591 | } 592 | 593 | /** 594 | * zoom map in 595 | * 596 | * @param callback 597 | */ 598 | public void zoomIn(ChangePosition callback) { 599 | zoomTo((int) (map.getCameraPosition().zoom + 1), true, callback); 600 | } 601 | 602 | /** 603 | * zoom map in 604 | * 605 | * @param smooth 606 | * @param callback 607 | */ 608 | public void zoomIn(boolean smooth, ChangePosition callback) { 609 | zoomTo((int) (map.getCameraPosition().zoom + 1), smooth, callback); 610 | } 611 | 612 | /** 613 | * zoom map out 614 | */ 615 | public void zoomOut() { 616 | zoomTo((int) (map.getCameraPosition().zoom - 1), true, null); 617 | } 618 | 619 | /** 620 | * zoom map out 621 | * 622 | * @param callback 623 | */ 624 | public void zoomOut(ChangePosition callback) { 625 | zoomTo((int) (map.getCameraPosition().zoom - 1), true, callback); 626 | } 627 | 628 | /** 629 | * zoom map out 630 | * 631 | * @param smooth 632 | * @param callback 633 | */ 634 | public void zoomOut(boolean smooth, ChangePosition callback) { 635 | zoomTo((int) (map.getCameraPosition().zoom - 1), smooth, callback); 636 | } 637 | 638 | /** 639 | * replace the default info-window 640 | * 641 | * @param v 642 | * @see #setInfoWindowAdapter(InfoWindowAdapter) 643 | * @deprecated please use to 644 | * {@link #setInfoWindowAdapter(InfoWindowAdapter)} 645 | */ 646 | @Deprecated 647 | public void setInfoWindow(View v) { 648 | map.setInfoWindowAdapter(new InfoWindowAdapter() { 649 | @Override 650 | public View getInfoWindow(Marker marker) { 651 | return v; 652 | } 653 | 654 | @Override 655 | public View getInfoContents(Marker marker) { 656 | return null; 657 | } 658 | }); 659 | } 660 | 661 | /** 662 | * replace the info-window contents 663 | * 664 | * @param v 665 | * @see #setInfoWindowAdapter(InfoWindowAdapter) 666 | * @deprecated please use to 667 | * {@link #setInfoWindowAdapter(InfoWindowAdapter)} 668 | */ 669 | @Deprecated 670 | public void setInfoContents(View v) { 671 | map.setInfoWindowAdapter(new InfoWindowAdapter() { 672 | @Override 673 | public View getInfoWindow(Marker marker) { 674 | return null; 675 | } 676 | 677 | @Override 678 | public View getInfoContents(Marker marker) { 679 | return v; 680 | } 681 | }); 682 | } 683 | 684 | /** 685 | * set the info-window adapter 686 | * 687 | * @param adapter 688 | */ 689 | public void setInfoWindowAdapter(InfoWindowAdapter adapter) { 690 | map.setInfoWindowAdapter(adapter); 691 | } 692 | 693 | /** 694 | * when map is clicked 695 | * 696 | * @param callback 697 | */ 698 | public void whenMapClick(final ClickCallback callback) { 699 | map.setOnMapClickListener(latLng -> callback.clicked(map, latLng)); 700 | } 701 | 702 | /** 703 | * when map is long clicked 704 | * 705 | * @param callback 706 | */ 707 | public void whenMapLongClick(final ClickCallback callback) { 708 | map.setOnMapLongClickListener(latLng -> callback.clicked(map, latLng)); 709 | } 710 | 711 | /** 712 | * when info window is clicked 713 | * 714 | * @param callback 715 | */ 716 | public void whenInfoWindowClick(final MarkerCallback callback) { 717 | map.setOnInfoWindowClickListener(marker -> callback.invokedMarker(map, marker)); 718 | } 719 | 720 | /** 721 | * when marker is clicked 722 | * 723 | * @param callback 724 | */ 725 | public void whenMarkerClick(final MarkerCallback callback) { 726 | map.setOnMarkerClickListener(marker -> { 727 | callback.invokedMarker(map, marker); 728 | 729 | return true; 730 | }); 731 | } 732 | 733 | /** 734 | * when marker is dragged 735 | * 736 | * @param callback 737 | */ 738 | public void whenMarkerDrag(MarkerDrag callback) { 739 | map.setOnMarkerDragListener(new OnMarkerDragListener() { 740 | @Override 741 | public void onMarkerDragStart(Marker marker) { 742 | callback.markerDragStart(map, marker); 743 | } 744 | 745 | @Override 746 | public void onMarkerDrag(Marker marker) { 747 | callback.markerDrag(map, marker); 748 | } 749 | 750 | @Override 751 | public void onMarkerDragEnd(Marker marker) { 752 | callback.markerDragEnd(map, marker); 753 | } 754 | }); 755 | } 756 | 757 | /** 758 | * add marker to map 759 | * 760 | * @param opts 761 | * @param callback 762 | * @return 763 | */ 764 | public Marker addMarker(MarkerOptions opts, MarkerCallback callback) { 765 | Marker marker = map.addMarker(opts); 766 | 767 | if (markers == null) { 768 | markers = new ArrayList<>(); 769 | } 770 | 771 | markers.add(marker); 772 | 773 | if (callback != null) { 774 | callback.invokedMarker(map, marker); 775 | } 776 | 777 | return marker; 778 | } 779 | 780 | /** 781 | * add marker to map 782 | * 783 | * @param opts 784 | * @return 785 | */ 786 | public Marker addMarker(MarkerOptions opts) { 787 | return addMarker(opts, null); 788 | } 789 | 790 | /** 791 | * add marker to map 792 | * 793 | * @param latLng 794 | * @param opts 795 | * @return 796 | */ 797 | public Marker addMarker(LatLng latLng, MarkerOptions opts) { 798 | return addMarker(opts.position(latLng), null); 799 | } 800 | 801 | /** 802 | * add marker to map 803 | * 804 | * @param lat 805 | * @param lng 806 | * @param opts 807 | * @return 808 | */ 809 | public Marker addMarker(double lat, double lng, MarkerOptions opts) { 810 | return addMarker(opts.position(new LatLng(lat, lng)), null); 811 | } 812 | 813 | /** 814 | * add marker to map 815 | * 816 | * @param latLng 817 | * @return 818 | */ 819 | public Marker addMarker(LatLng latLng) { 820 | return addMarker(new MarkerOptions().position(latLng), null); 821 | } 822 | 823 | /** 824 | * add marker to map 825 | * 826 | * @param lat 827 | * @param lng 828 | * @return 829 | */ 830 | public Marker addMarker(double lat, double lng) { 831 | return addMarker(new MarkerOptions().position(new LatLng(lat, lng)), null); 832 | } 833 | 834 | /** 835 | * add marker to map 836 | * 837 | * @param latLng 838 | * @param opts 839 | * @param callback 840 | * @return 841 | */ 842 | public Marker addMarker(LatLng latLng, MarkerOptions opts, MarkerCallback callback) { 843 | return addMarker(opts.position(latLng), callback); 844 | } 845 | 846 | /** 847 | * add marker to map 848 | * 849 | * @param lat 850 | * @param lng 851 | * @param opts 852 | * @param callback 853 | * @return 854 | */ 855 | public Marker addMarker(double lat, double lng, MarkerOptions opts, MarkerCallback callback) { 856 | return addMarker(opts.position(new LatLng(lat, lng)), callback); 857 | } 858 | 859 | /** 860 | * add marker to map 861 | * 862 | * @param latLng 863 | * @param callback 864 | * @return 865 | */ 866 | public Marker addMarker(LatLng latLng, MarkerCallback callback) { 867 | return addMarker(new MarkerOptions().position(latLng), callback); 868 | } 869 | 870 | /** 871 | * add marker to map 872 | * 873 | * @param lat 874 | * @param lng 875 | * @param callback 876 | * @return 877 | */ 878 | public Marker addMarker(double lat, double lng, MarkerCallback callback) { 879 | return addMarker(new MarkerOptions().position(new LatLng(lat, lng)), callback); 880 | } 881 | 882 | /** 883 | * add all markers to map 884 | * 885 | * @param allOpts 886 | * @param callback 887 | */ 888 | public void addMarkers(ArrayList allOpts, MarkerCallback callback) { 889 | if (markers == null) { 890 | markers = new ArrayList<>(); 891 | } 892 | 893 | for (MarkerOptions opts : allOpts) { 894 | Marker marker = map.addMarker(opts); 895 | 896 | markers.add(marker); 897 | 898 | if (callback != null) { 899 | callback.invokedMarker(map, marker); 900 | } 901 | } 902 | } 903 | 904 | /** 905 | * add all markers to map 906 | * 907 | * @param allOpts 908 | */ 909 | public void addMarkers(ArrayList allOpts) { 910 | addMarkers(allOpts, null); 911 | } 912 | 913 | /** 914 | * return all markers 915 | * 916 | * @return 917 | */ 918 | public ArrayList getMarkers() { 919 | return markers; 920 | } 921 | 922 | /** 923 | * return specific marker 924 | * 925 | * @param index 926 | * @return 927 | */ 928 | public Marker getMarker(int index) { 929 | return markers.get(index); 930 | } 931 | 932 | /** 933 | * clear all markers 934 | */ 935 | public void clearMarkers() { 936 | map.clear(); 937 | 938 | if (markers != null) { 939 | markers.clear(); 940 | } 941 | } 942 | 943 | /** 944 | * show traffic layer 945 | * 946 | * @param enabled 947 | */ 948 | public void showTraffic(boolean enabled) { 949 | map.setTrafficEnabled(enabled); 950 | } 951 | 952 | /** 953 | * show indoor layer 954 | * 955 | * @param enabled 956 | */ 957 | public void showIndoor(boolean enabled) { 958 | map.setIndoorEnabled(enabled); 959 | } 960 | 961 | /** 962 | * find specific location 963 | * 964 | * @param location 965 | * @param callback 966 | */ 967 | public void find(String location, FindResult callback) { 968 | Geocoder geocoder = new Geocoder(context); 969 | ArrayList
addresses = new ArrayList<>(); 970 | 971 | try { 972 | addresses = (ArrayList
) geocoder.getFromLocationName(location, 5); 973 | } catch (IOException e) { 974 | Log.e(TAG, e.getMessage()); 975 | } 976 | 977 | findCallback(callback, addresses); 978 | } 979 | 980 | /** 981 | * find specific location 982 | * 983 | * @param location 984 | */ 985 | public void find(String location) { 986 | find(location, null); 987 | } 988 | 989 | /** 990 | * find specific location 991 | * 992 | * @param location 993 | * @param callback 994 | */ 995 | public void findAsync(final String location, final FindResult callback) { 996 | new AsyncTask() { 997 | private ProgressDialog dialog; 998 | private ArrayList
addresses; 999 | 1000 | @Override 1001 | protected void onPreExecute() { 1002 | dialog = new ProgressDialog(context); 1003 | 1004 | dialog.setMessage("Loading..."); 1005 | dialog.setCancelable(false); 1006 | dialog.show(); 1007 | } 1008 | 1009 | @Override 1010 | protected Void doInBackground(Void... params) { 1011 | Geocoder geocoder = new Geocoder(context); 1012 | 1013 | try { 1014 | addresses = (ArrayList
) geocoder.getFromLocationName(location, 5); 1015 | } catch (IOException e) { 1016 | Log.e(TAG, e.getMessage()); 1017 | } 1018 | 1019 | return null; 1020 | } 1021 | 1022 | @Override 1023 | protected void onPostExecute(Void result) { 1024 | if (dialog.isShowing()) { 1025 | dialog.dismiss(); 1026 | } 1027 | 1028 | findCallback(callback, addresses); 1029 | } 1030 | }.execute(); 1031 | } 1032 | 1033 | /** 1034 | * find specific location 1035 | * 1036 | * @param location 1037 | */ 1038 | public void findAsync(String location) { 1039 | findAsync(location, null); 1040 | } 1041 | 1042 | private void findCallback(FindResult callback, ArrayList
addresses) { 1043 | if (callback != null) { 1044 | callback.found(map, addresses); 1045 | } else { 1046 | for (Address address : addresses) { 1047 | MarkerOptions opts = new MarkerOptions(); 1048 | LatLng latLng = new LatLng(address.getLatitude(), address.getLongitude()); 1049 | 1050 | opts.position(latLng); 1051 | opts.title(address.toString()); 1052 | opts.snippet(latLng.toString()); 1053 | 1054 | addMarker(opts); 1055 | } 1056 | 1057 | animateTo(new LatLng(addresses.get(0).getLatitude(), addresses.get(0).getLongitude())); 1058 | } 1059 | } 1060 | 1061 | public enum MapType { 1062 | MAP_TYPE_NONE, MAP_TYPE_NORMAL, MAP_TYPE_SATELLITE, MAP_TYPE_TERRAIN, MAP_TYPE_HYBRID 1063 | } 1064 | 1065 | public enum TrackType { 1066 | TRACK_TYPE_MOVE, TRACK_TYPE_ANIMATE, TRACK_TYPE_NONE 1067 | } 1068 | 1069 | public interface MapControllerReady { 1070 | void already(MapController controller); 1071 | } 1072 | 1073 | public interface ChangeMyLocation { 1074 | void changed(GoogleMap map, Location location); 1075 | } 1076 | 1077 | public interface ChangePosition { 1078 | void changed(GoogleMap map, CameraPosition position); 1079 | } 1080 | 1081 | public interface ClickCallback { 1082 | void clicked(GoogleMap map, LatLng latLng); 1083 | } 1084 | 1085 | public interface MarkerCallback { 1086 | void invokedMarker(GoogleMap map, Marker marker); 1087 | } 1088 | 1089 | public interface MarkerDrag { 1090 | void markerDragStart(GoogleMap map, Marker marker); 1091 | 1092 | void markerDrag(GoogleMap map, Marker marker); 1093 | 1094 | void markerDragEnd(GoogleMap map, Marker marker); 1095 | } 1096 | 1097 | public interface FindResult { 1098 | void found(GoogleMap map, ArrayList
addresses); 1099 | } 1100 | } -------------------------------------------------------------------------------- /src/main/res/values/version.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12451000 4 | --------------------------------------------------------------------------------