diff --git a/ui/watch/LICENSE b/ui/watch/LICENSE
new file mode 100644
index 00000000000..e5a134f7fb6
--- /dev/null
+++ b/ui/watch/LICENSE
@@ -0,0 +1,429 @@
+[AndroidWearSampleJp]
+
+The MIT License (MIT)
+
+Copyright (c) 2014 Takahiro "Poly" Horikawa
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+[wear-datalayer-sample]
+Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2014 bati11
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+[MapDemoApp]
+Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright (C) 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/ui/watch/README.md b/ui/watch/README.md
new file mode 100644
index 00000000000..309f0d79aee
--- /dev/null
+++ b/ui/watch/README.md
@@ -0,0 +1,31 @@
+## Voice:音声入力アプリ
+
+下記のアプリの一部を利用した。
+https://github.com/thorikawa/AndroidWearSampleJp
+
+mobileモジュールをスマートフォンにインストールすることで音声入力部分は利用可能。
+「VoiceMobile」アプリを起動し、「Notification」→「Notification with voice reply」を選択することでスマートウォッチに通知が送信される。
+wear側では通知を右にスワイプして返信を選ぶことで返信ができる。
+「お話しください」と表示されている状態で音声入力することで、話した音声を文字列に変換してスマートフォンに送信する。
+スマートフォンでは受信したメッセージを表示する。
+
+
+## mapdemo:地図アプリ
+mobileモジュールでは下記のアプリをの一部を利用した。
+https://github.com/bati11/wear-datalayer-sample
+appモジュールでは下記のアプリを一部編集して利用した。
+https://github.com/lantian699/MapDemoApp
+
+mobileモジュールをスマートフォンに、appモジュールをスマートウォッチにインストールする。
+
+スマートフォンでは「mapdemo」アプリを起動(USB接続している状態でないと起動出来なかった)、「Message」を選択し、InputMessageと表示されている状態で待機する。
+
+スマートウォッチでは、「GoogleMapsAPIDemos」アプリを起動、「Basic Map」を選択すると地図が表示される。
+タップすることでマーカーが設置され、その地点の緯度と経度をスマートフォン側で表示する。
+ロングタップすることで現在位置を表示、非表示にする。
+表示状態のときに左のボタンを押すことで表示位置を現在地まで移動する。
+
+
+-----------------
+作成者 平岡 祥
+show@sqlab.jp
diff --git a/ui/watch/Voice/.gitignore b/ui/watch/Voice/.gitignore
new file mode 100644
index 00000000000..9c4de5825b1
--- /dev/null
+++ b/ui/watch/Voice/.gitignore
@@ -0,0 +1,7 @@
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
diff --git a/ui/watch/Voice/Voice.iml b/ui/watch/Voice/Voice.iml
new file mode 100644
index 00000000000..b79a55fdf0a
--- /dev/null
+++ b/ui/watch/Voice/Voice.iml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ui/watch/Voice/build.gradle b/ui/watch/Voice/build.gradle
new file mode 100644
index 00000000000..9405f3fd18b
--- /dev/null
+++ b/ui/watch/Voice/build.gradle
@@ -0,0 +1,19 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:1.2.3'
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ }
+}
diff --git a/ui/watch/Voice/gradle.properties b/ui/watch/Voice/gradle.properties
new file mode 100644
index 00000000000..1d3591c8a4c
--- /dev/null
+++ b/ui/watch/Voice/gradle.properties
@@ -0,0 +1,18 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
\ No newline at end of file
diff --git a/ui/watch/Voice/gradle/wrapper/gradle-wrapper.jar b/ui/watch/Voice/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000000..8c0fb64a869
Binary files /dev/null and b/ui/watch/Voice/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/ui/watch/Voice/gradle/wrapper/gradle-wrapper.properties b/ui/watch/Voice/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000000..0c71e760dc9
--- /dev/null
+++ b/ui/watch/Voice/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Apr 10 15:27:10 PDT 2013
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
diff --git a/ui/watch/Voice/gradlew b/ui/watch/Voice/gradlew
new file mode 100644
index 00000000000..91a7e269e19
--- /dev/null
+++ b/ui/watch/Voice/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/ui/watch/Voice/gradlew.bat b/ui/watch/Voice/gradlew.bat
new file mode 100644
index 00000000000..8a0b282aa68
--- /dev/null
+++ b/ui/watch/Voice/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/ui/watch/Voice/mobile/.gitignore b/ui/watch/Voice/mobile/.gitignore
new file mode 100644
index 00000000000..796b96d1c40
--- /dev/null
+++ b/ui/watch/Voice/mobile/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/ui/watch/Voice/mobile/build.gradle b/ui/watch/Voice/mobile/build.gradle
new file mode 100644
index 00000000000..0fe960dd8e6
--- /dev/null
+++ b/ui/watch/Voice/mobile/build.gradle
@@ -0,0 +1,27 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 22
+ buildToolsVersion "23.0.0 rc3"
+
+ defaultConfig {
+ applicationId "com.example.show.voice"
+ minSdkVersion 19
+ targetSdkVersion 22
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ wearApp project(':wear')
+ compile 'com.android.support:appcompat-v7:22.2.0'
+ compile 'com.google.android.gms:play-services:7.5.0'
+}
diff --git a/ui/watch/Voice/mobile/mobile.iml b/ui/watch/Voice/mobile/mobile.iml
new file mode 100644
index 00000000000..99ee9009856
--- /dev/null
+++ b/ui/watch/Voice/mobile/mobile.iml
@@ -0,0 +1,139 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ui/watch/Voice/mobile/proguard-rules.pro b/ui/watch/Voice/mobile/proguard-rules.pro
new file mode 100644
index 00000000000..e93e140e0cd
--- /dev/null
+++ b/ui/watch/Voice/mobile/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in C:\Users\Show\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/ui/watch/Voice/mobile/src/androidTest/java/com/example/show/voice/ApplicationTest.java b/ui/watch/Voice/mobile/src/androidTest/java/com/example/show/voice/ApplicationTest.java
new file mode 100644
index 00000000000..e217b17c16d
--- /dev/null
+++ b/ui/watch/Voice/mobile/src/androidTest/java/com/example/show/voice/ApplicationTest.java
@@ -0,0 +1,13 @@
+package com.example.show.voice;
+
+import android.app.Application;
+import android.test.ApplicationTestCase;
+
+/**
+ * Testing Fundamentals
+ */
+public class ApplicationTest extends ApplicationTestCase {
+ public ApplicationTest() {
+ super(Application.class);
+ }
+}
\ No newline at end of file
diff --git a/ui/watch/Voice/mobile/src/main/AndroidManifest.xml b/ui/watch/Voice/mobile/src/main/AndroidManifest.xml
new file mode 100644
index 00000000000..71c8304c26e
--- /dev/null
+++ b/ui/watch/Voice/mobile/src/main/AndroidManifest.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/Voice/mobile/src/main/java/com/example/show/voice/DataActivity.java b/ui/watch/Voice/mobile/src/main/java/com/example/show/voice/DataActivity.java
new file mode 100644
index 00000000000..30ad209e85a
--- /dev/null
+++ b/ui/watch/Voice/mobile/src/main/java/com/example/show/voice/DataActivity.java
@@ -0,0 +1,155 @@
+package com.example.show.voice;
+
+import android.app.Activity;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+
+import com.google.android.gms.common.api.GoogleApiClient;
+import com.google.android.gms.common.api.PendingResult;
+import com.google.android.gms.common.api.ResultCallback;
+import com.google.android.gms.wearable.DataApi;
+import com.google.android.gms.wearable.DataItem;
+import com.google.android.gms.wearable.DataMap;
+import com.google.android.gms.wearable.DataMapItem;
+import com.google.android.gms.wearable.MessageApi;
+import com.google.android.gms.wearable.Node;
+import com.google.android.gms.wearable.NodeApi;
+import com.google.android.gms.wearable.PutDataMapRequest;
+import com.google.android.gms.wearable.PutDataRequest;
+import com.google.android.gms.wearable.Wearable;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+
+
+public class DataActivity extends Activity {
+
+ private static final String TAG = "TEST";
+ private static final String COUNT_KEY = "COUNT_KEY";
+ private static final String COUNT_PATH = "/count";
+ private static final String START_ACTIVITY_PATH = "/start/MainActivity";
+
+ private int count = 0;
+ private GoogleApiClient mGoogleApiClient;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_data);
+
+ ((Button) findViewById(R.id.button_send_count)).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ sendCount();
+ }
+ });
+
+ ((Button) findViewById(R.id.button_open_wear_activity)).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ new AsyncTask() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ sendMessageToStartActivity();
+ return null;
+ }
+ }.execute();
+ }
+ });
+
+ mGoogleApiClient = new GoogleApiClient.Builder(this)
+ .addApi(Wearable.API)
+ .addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
+ @Override
+ public void onConnected(Bundle bundle) {
+ Log.d(TAG, "Google Api Client connected");
+ new AsyncTask() {
+ @Override
+ protected Void doInBackground(Void... voids) {
+ restoreCurrentCount();
+ return null;
+ }
+ }.execute();
+ }
+
+ @Override
+ public void onConnectionSuspended(int i) {
+ }
+ }).build();
+ mGoogleApiClient.connect();
+
+ }
+
+ private String getLocalNodeId() {
+ NodeApi.GetLocalNodeResult nodeResult = Wearable.NodeApi.getLocalNode(mGoogleApiClient).await();
+ return nodeResult.getNode().getId();
+ }
+
+ private void sendCount() {
+ PutDataMapRequest dataMap = PutDataMapRequest.create(COUNT_PATH);
+ dataMap.getDataMap().putInt(COUNT_KEY, ++count);
+ PutDataRequest request = dataMap.asPutDataRequest();
+ PendingResult pendingResult = Wearable.DataApi
+ .putDataItem(mGoogleApiClient, request);
+ pendingResult.setResultCallback(new ResultCallback() {
+ @Override
+ public void onResult(DataApi.DataItemResult dataItemResult) {
+ Log.d(TAG, "count updated:" + count);
+ }
+ });
+ }
+
+ private void restoreCurrentCount() {
+ String localNodeId = getLocalNodeId();
+ Uri uri = new Uri.Builder().scheme(PutDataRequest.WEAR_URI_SCHEME).authority(localNodeId).path(COUNT_PATH).build();
+ Wearable.DataApi.getDataItem(mGoogleApiClient, uri).setResultCallback(new ResultCallback() {
+ @Override
+ public void onResult(DataApi.DataItemResult dataItemResult) {
+ DataItem dataItem = dataItemResult.getDataItem();
+ if (dataItem != null) {
+ DataMap dataMap = DataMapItem.fromDataItem(dataItemResult.getDataItem()).getDataMap();
+ count = dataMap.getInt(COUNT_KEY);
+ Log.d(TAG, "restored count:" + count);
+ }
+ }
+ });
+ }
+
+ private void sendMessageToStartActivity() {
+ Collection nodes = getNodes();
+ for (String node : nodes) {
+ MessageApi.SendMessageResult result =
+ Wearable.MessageApi.sendMessage(mGoogleApiClient, node, START_ACTIVITY_PATH, null).await();
+ if (!result.getStatus().isSuccess()) {
+ Log.e(TAG, "ERROR: failed to send Message: " + result.getStatus());
+ }
+ }
+ }
+
+ private String getRemoteNodeId() {
+ HashSet results = new HashSet();
+ NodeApi.GetConnectedNodesResult nodesResult =
+ Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).await();
+ List nodes = nodesResult.getNodes();
+ if (nodes.size() > 0) {
+ return nodes.get(0).getId();
+ }
+ return null;
+ }
+
+ private Collection getNodes() {
+ HashSet results = new HashSet();
+ NodeApi.GetConnectedNodesResult nodes =
+ Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).await();
+ for (Node node : nodes.getNodes()) {
+ results.add(node.getId());
+ }
+ return results;
+ }
+
+}
diff --git a/ui/watch/Voice/mobile/src/main/java/com/example/show/voice/MainActivity.java b/ui/watch/Voice/mobile/src/main/java/com/example/show/voice/MainActivity.java
new file mode 100644
index 00000000000..30c8343aa37
--- /dev/null
+++ b/ui/watch/Voice/mobile/src/main/java/com/example/show/voice/MainActivity.java
@@ -0,0 +1,41 @@
+package com.example.show.voice;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+public class MainActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ final ListView listView = (ListView) findViewById(R.id.list_menu);
+ String[] statesList = {"Notification", "Data API and Message API"};
+ ArrayAdapter adapter = new ArrayAdapter(this,
+ android.R.layout.simple_list_item_1, android.R.id.text1, statesList);
+ listView.setAdapter(adapter);
+ listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> parent, View view,
+ int position, long id) {
+ Class activityClass = null;
+ switch (position) {
+ case 0:
+ activityClass = NotificationActivity.class;
+ break;
+ case 1:
+ activityClass = DataActivity.class;
+ break;
+ }
+ Intent intent = new Intent(MainActivity.this, activityClass);
+ startActivity(intent);
+ }
+ });
+ }
+}
diff --git a/ui/watch/Voice/mobile/src/main/java/com/example/show/voice/NotificationActivity.java b/ui/watch/Voice/mobile/src/main/java/com/example/show/voice/NotificationActivity.java
new file mode 100644
index 00000000000..aab85dfcffb
--- /dev/null
+++ b/ui/watch/Voice/mobile/src/main/java/com/example/show/voice/NotificationActivity.java
@@ -0,0 +1,154 @@
+package com.example.show.voice;
+
+import android.app.Activity;
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v4.app.NotificationCompat;
+import android.support.v4.app.NotificationManagerCompat;
+import android.support.v4.app.RemoteInput;
+import android.view.View;
+
+public class NotificationActivity extends Activity {
+
+ public static final String EXTRA_VOICE_REPLY = "extra_voice_realy";
+ private static final String GROUP_KEY = "com.polysfactory.androidwearsamplejp.notification.group";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ final Context context = this;
+ setContentView(R.layout.activity_notification);
+ findViewById(R.id.basic_notification).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ sendBasicNotification(context);
+ }
+ });
+ findViewById(R.id.stacking_notification).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ sendStackingNotification(context);
+ }
+ });
+ findViewById(R.id.voice_input_notification).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ sendNotificationWithVoiceInputAction(context);
+ }
+ });
+ findViewById(R.id.page_notification).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ sendNotificationWithPages(context);
+ }
+ });
+ }
+
+ private void sendBasicNotification(Context context) {
+ Intent intent = new Intent(context, NotificationLandingActivity.class);
+ PendingIntent pIntent = PendingIntent.getActivity(context, 0, intent, 0);
+ // build notification
+ // the addAction re-use the same intent to keep the example short
+ Notification n = new NotificationCompat.Builder(context)
+ .setContentTitle("新着メッセージがあります")
+ .setContentText("xxさんからメッセージが届いています")
+ .setSmallIcon(R.drawable.ic_launcher)
+ .setContentIntent(pIntent)
+ .addAction(R.drawable.ic_launcher, "返信", pIntent)
+ .addAction(R.drawable.ic_launcher, "転送", pIntent)
+ .build();
+
+
+ NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
+ notificationManager.notify(0, n);
+ }
+
+ private void sendStackingNotification(Context context) {
+ NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
+
+ Notification card1 = new NotificationCompat.Builder(context)
+ .setContentText("何してますか?")
+ .setSmallIcon(R.drawable.ic_launcher)
+ .setGroup(GROUP_KEY)
+ .setSortKey("0")
+ .build();
+ notificationManager.notify(101, card1);
+
+ Notification card2 = new NotificationCompat.Builder(context)
+ .setContentText("手伝ってもらってもいいですか?")
+ .setSmallIcon(R.drawable.ic_launcher)
+ .setGroup(GROUP_KEY)
+ .setSortKey("1")
+ .build();
+ notificationManager.notify(102, card2);
+
+ Notification card3 = new NotificationCompat.Builder(context)
+ .setContentText("近くのコンビニエンスストアでweb moneyを買うのを手伝ってもらえますか?")
+ .setSmallIcon(R.drawable.ic_launcher)
+ .setGroup(GROUP_KEY)
+ .setSortKey("2")
+ .build();
+ notificationManager.notify(103, card3);
+
+ Notification summary = new NotificationCompat.Builder(context)
+ .setContentTitle("新着メッセージ3件")
+ .setSmallIcon(R.drawable.ic_launcher)
+ .setGroup(GROUP_KEY)
+ .setGroupSummary(true)
+ .build();
+ notificationManager.notify(100, summary);
+ }
+
+ private void sendNotificationWithVoiceInputAction(Context context) {
+ String replyLabel = "返信してください";
+ String[] replyChoices = {"はい", "いいえ", "たぶん"};
+
+ RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
+ .setLabel(replyLabel)
+ .setChoices(replyChoices)
+ .build();
+
+ Intent replyIntent = new Intent(this, VoiceInputReceiverActivity.class);
+ PendingIntent replyPendingIntent =
+ PendingIntent.getActivity(this, 0, replyIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT);
+
+ NotificationCompat.Action action =
+ new NotificationCompat.Action.Builder(R.drawable.ic_launcher, "返信", replyPendingIntent)
+ .addRemoteInput(remoteInput)
+ .build();
+
+ Notification notification =
+ new NotificationCompat.Builder(context)
+ .setSmallIcon(R.drawable.ic_launcher)
+ .setContentTitle("返信")
+ .setContentText("返信して下さい")
+ .extend(new NotificationCompat.WearableExtender().addAction(action))
+ .build();
+
+ NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
+ notificationManager.notify(200, notification);
+ }
+
+ private void sendNotificationWithPages(Context context) {
+ Notification page =
+ new NotificationCompat.Builder(context)
+ .setStyle(new NotificationCompat.BigTextStyle().bigText("メンチカツ定食 $7.99"))
+ .build();
+
+ Notification notification =
+ new NotificationCompat.Builder(context)
+ .setSmallIcon(R.drawable.ic_launcher)
+ .setContentTitle("xxレストラン通信")
+ .setContentText("本日の日替わりランチ")
+ .extend(new NotificationCompat.WearableExtender().addPage(page))
+ .build();
+
+ NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
+ notificationManager.notify(300, notification);
+ }
+
+}
diff --git a/ui/watch/Voice/mobile/src/main/java/com/example/show/voice/NotificationLandingActivity.java b/ui/watch/Voice/mobile/src/main/java/com/example/show/voice/NotificationLandingActivity.java
new file mode 100644
index 00000000000..85aa8ee16ff
--- /dev/null
+++ b/ui/watch/Voice/mobile/src/main/java/com/example/show/voice/NotificationLandingActivity.java
@@ -0,0 +1,14 @@
+package com.example.show.voice;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class NotificationLandingActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_notification_landing);
+ }
+
+}
diff --git a/ui/watch/Voice/mobile/src/main/java/com/example/show/voice/VoiceInputReceiverActivity.java b/ui/watch/Voice/mobile/src/main/java/com/example/show/voice/VoiceInputReceiverActivity.java
new file mode 100644
index 00000000000..7edeed253b1
--- /dev/null
+++ b/ui/watch/Voice/mobile/src/main/java/com/example/show/voice/VoiceInputReceiverActivity.java
@@ -0,0 +1,19 @@
+package com.example.show.voice;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.support.v4.app.RemoteInput;
+import android.widget.TextView;
+
+public class VoiceInputReceiverActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_voice_input_receiver);
+ Bundle remoteInput = RemoteInput.getResultsFromIntent(getIntent());
+ CharSequence message = remoteInput.getCharSequence(NotificationActivity.EXTRA_VOICE_REPLY);
+ ((TextView) findViewById(R.id.message)).setText(String.format("入力メッセージは「%s」です。", message));
+ }
+
+}
diff --git a/ui/watch/Voice/mobile/src/main/res/drawable-hdpi/ic_launcher.png b/ui/watch/Voice/mobile/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 00000000000..96a442e5b8e
Binary files /dev/null and b/ui/watch/Voice/mobile/src/main/res/drawable-hdpi/ic_launcher.png differ
diff --git a/ui/watch/Voice/mobile/src/main/res/drawable-mdpi/ic_launcher.png b/ui/watch/Voice/mobile/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 00000000000..359047dfa4e
Binary files /dev/null and b/ui/watch/Voice/mobile/src/main/res/drawable-mdpi/ic_launcher.png differ
diff --git a/ui/watch/Voice/mobile/src/main/res/drawable-xhdpi/ic_launcher.png b/ui/watch/Voice/mobile/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 00000000000..71c6d760f05
Binary files /dev/null and b/ui/watch/Voice/mobile/src/main/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/ui/watch/Voice/mobile/src/main/res/drawable-xxhdpi/ic_launcher.png b/ui/watch/Voice/mobile/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000000..4df18946442
Binary files /dev/null and b/ui/watch/Voice/mobile/src/main/res/drawable-xxhdpi/ic_launcher.png differ
diff --git a/ui/watch/Voice/mobile/src/main/res/layout/activity_data.xml b/ui/watch/Voice/mobile/src/main/res/layout/activity_data.xml
new file mode 100644
index 00000000000..e0cf502d3d9
--- /dev/null
+++ b/ui/watch/Voice/mobile/src/main/res/layout/activity_data.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
diff --git a/ui/watch/Voice/mobile/src/main/res/layout/activity_main.xml b/ui/watch/Voice/mobile/src/main/res/layout/activity_main.xml
new file mode 100644
index 00000000000..1445797a909
--- /dev/null
+++ b/ui/watch/Voice/mobile/src/main/res/layout/activity_main.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/ui/watch/Voice/mobile/src/main/res/layout/activity_notification.xml b/ui/watch/Voice/mobile/src/main/res/layout/activity_notification.xml
new file mode 100644
index 00000000000..a4d1b9dd214
--- /dev/null
+++ b/ui/watch/Voice/mobile/src/main/res/layout/activity_notification.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/Voice/mobile/src/main/res/layout/activity_notification_landing.xml b/ui/watch/Voice/mobile/src/main/res/layout/activity_notification_landing.xml
new file mode 100644
index 00000000000..852d9bba8f3
--- /dev/null
+++ b/ui/watch/Voice/mobile/src/main/res/layout/activity_notification_landing.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
diff --git a/ui/watch/Voice/mobile/src/main/res/layout/activity_voice_input_receiver.xml b/ui/watch/Voice/mobile/src/main/res/layout/activity_voice_input_receiver.xml
new file mode 100644
index 00000000000..12c460a0343
--- /dev/null
+++ b/ui/watch/Voice/mobile/src/main/res/layout/activity_voice_input_receiver.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
diff --git a/ui/watch/Voice/mobile/src/main/res/menu/main.xml b/ui/watch/Voice/mobile/src/main/res/menu/main.xml
new file mode 100644
index 00000000000..0368d5722fb
--- /dev/null
+++ b/ui/watch/Voice/mobile/src/main/res/menu/main.xml
@@ -0,0 +1,15 @@
+
diff --git a/ui/watch/Voice/mobile/src/main/res/menu/menu_main.xml b/ui/watch/Voice/mobile/src/main/res/menu/menu_main.xml
new file mode 100644
index 00000000000..b1cb90811d7
--- /dev/null
+++ b/ui/watch/Voice/mobile/src/main/res/menu/menu_main.xml
@@ -0,0 +1,6 @@
+
diff --git a/ui/watch/Voice/mobile/src/main/res/menu/my.xml b/ui/watch/Voice/mobile/src/main/res/menu/my.xml
new file mode 100644
index 00000000000..f1fa1552e1f
--- /dev/null
+++ b/ui/watch/Voice/mobile/src/main/res/menu/my.xml
@@ -0,0 +1,9 @@
+
diff --git a/ui/watch/Voice/mobile/src/main/res/mipmap-hdpi/ic_launcher.png b/ui/watch/Voice/mobile/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 00000000000..cde69bcccec
Binary files /dev/null and b/ui/watch/Voice/mobile/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/ui/watch/Voice/mobile/src/main/res/mipmap-mdpi/ic_launcher.png b/ui/watch/Voice/mobile/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 00000000000..c133a0cbd37
Binary files /dev/null and b/ui/watch/Voice/mobile/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/ui/watch/Voice/mobile/src/main/res/mipmap-xhdpi/ic_launcher.png b/ui/watch/Voice/mobile/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 00000000000..bfa42f0e7b9
Binary files /dev/null and b/ui/watch/Voice/mobile/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/ui/watch/Voice/mobile/src/main/res/mipmap-xxhdpi/ic_launcher.png b/ui/watch/Voice/mobile/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000000..324e72cdd74
Binary files /dev/null and b/ui/watch/Voice/mobile/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/ui/watch/Voice/mobile/src/main/res/values-w820dp/dimens.xml b/ui/watch/Voice/mobile/src/main/res/values-w820dp/dimens.xml
new file mode 100644
index 00000000000..63fc8164446
--- /dev/null
+++ b/ui/watch/Voice/mobile/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 64dp
+
diff --git a/ui/watch/Voice/mobile/src/main/res/values/dimens.xml b/ui/watch/Voice/mobile/src/main/res/values/dimens.xml
new file mode 100644
index 00000000000..47c82246738
--- /dev/null
+++ b/ui/watch/Voice/mobile/src/main/res/values/dimens.xml
@@ -0,0 +1,5 @@
+
+
+ 16dp
+ 16dp
+
diff --git a/ui/watch/Voice/mobile/src/main/res/values/strings.xml b/ui/watch/Voice/mobile/src/main/res/values/strings.xml
new file mode 100644
index 00000000000..dbf2972fce5
--- /dev/null
+++ b/ui/watch/Voice/mobile/src/main/res/values/strings.xml
@@ -0,0 +1,10 @@
+
+ VoiceMobile
+ Hello world!
+ Settings
+ NotificationActivity
+ NotificationLandingActivity
+ VoiceReplyActivity
+ MainActivity
+ DataActivity
+
diff --git a/ui/watch/Voice/mobile/src/main/res/values/styles.xml b/ui/watch/Voice/mobile/src/main/res/values/styles.xml
new file mode 100644
index 00000000000..766ab993048
--- /dev/null
+++ b/ui/watch/Voice/mobile/src/main/res/values/styles.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/ui/watch/Voice/settings.gradle b/ui/watch/Voice/settings.gradle
new file mode 100644
index 00000000000..6a4e79fc9b3
--- /dev/null
+++ b/ui/watch/Voice/settings.gradle
@@ -0,0 +1 @@
+include ':mobile', ':wear'
diff --git a/ui/watch/Voice/wear/.gitignore b/ui/watch/Voice/wear/.gitignore
new file mode 100644
index 00000000000..796b96d1c40
--- /dev/null
+++ b/ui/watch/Voice/wear/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/ui/watch/Voice/wear/build.gradle b/ui/watch/Voice/wear/build.gradle
new file mode 100644
index 00000000000..81676cbe03a
--- /dev/null
+++ b/ui/watch/Voice/wear/build.gradle
@@ -0,0 +1,27 @@
+apply plugin: 'com.android.application'
+
+
+android {
+ compileSdkVersion 22
+ buildToolsVersion "23.0.0 rc3"
+
+ defaultConfig {
+ applicationId "com.example.show.voice"
+ minSdkVersion 21
+ targetSdkVersion 22
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ compile 'com.google.android.support:wearable:1.2.0'
+ compile 'com.google.android.gms:play-services-wearable:7.5.0'
+}
diff --git a/ui/watch/Voice/wear/proguard-rules.pro b/ui/watch/Voice/wear/proguard-rules.pro
new file mode 100644
index 00000000000..e93e140e0cd
--- /dev/null
+++ b/ui/watch/Voice/wear/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in C:\Users\Show\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/ui/watch/Voice/wear/src/main/AndroidManifest.xml b/ui/watch/Voice/wear/src/main/AndroidManifest.xml
new file mode 100644
index 00000000000..e969a88a887
--- /dev/null
+++ b/ui/watch/Voice/wear/src/main/AndroidManifest.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/Voice/wear/src/main/java/com/example/show/voice/DataLayerListenerService.java b/ui/watch/Voice/wear/src/main/java/com/example/show/voice/DataLayerListenerService.java
new file mode 100644
index 00000000000..a5d430683cf
--- /dev/null
+++ b/ui/watch/Voice/wear/src/main/java/com/example/show/voice/DataLayerListenerService.java
@@ -0,0 +1,65 @@
+package com.example.show.voice;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Intent;
+
+import com.google.android.gms.wearable.DataEvent;
+import com.google.android.gms.wearable.DataEventBuffer;
+import com.google.android.gms.wearable.DataItem;
+import com.google.android.gms.wearable.DataMap;
+import com.google.android.gms.wearable.DataMapItem;
+import com.google.android.gms.wearable.MessageEvent;
+import com.google.android.gms.wearable.WearableListenerService;
+
+/**
+ * Created by poly on 7/6/14.
+ */
+public class DataLayerListenerService extends WearableListenerService {
+ private static final String TAG = "DataLayerListenerService";
+ private static final String COUNT_PATH = "/count";
+ private static final String COUNT_KEY = "COUNT_KEY";
+ private static final String START_ACTIVITY_PATH = "/start/MainActivity";
+
+ @Override
+ public void onMessageReceived(MessageEvent messageEvent) {
+ if (START_ACTIVITY_PATH.equals(messageEvent.getPath())) {
+ Intent intent = new Intent(this, WatchActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
+ return;
+ }
+ }
+
+ @Override
+ public void onDataChanged(DataEventBuffer dataEvents) {
+ for (DataEvent event : dataEvents) {
+ DataItem dataItem = event.getDataItem();
+ if (COUNT_PATH.equals(dataItem.getUri().getPath())) {
+ DataMap dataMap = DataMapItem.fromDataItem(dataItem).getDataMap();
+ int count = dataMap.getInt(COUNT_KEY);
+
+ // android:allowEmbedded="true" is required for target activity
+ Intent intent = new Intent(this, NotificationEmbeddedActivity.class);
+ intent.putExtra(NotificationEmbeddedActivity.EXTRA_KEY_COUNT, count);
+ PendingIntent pendingIntent =
+ PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+
+ Notification notification = new Notification.Builder(this)
+ .setSmallIcon(R.drawable.ic_launcher)
+ .extend(
+ new Notification.WearableExtender()
+ .setHintHideIcon(true)
+ .setDisplayIntent(pendingIntent)
+ )
+ .build();
+
+ NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
+ notificationManager.notify(1000, notification);
+
+ break;
+ }
+ }
+ }
+}
diff --git a/ui/watch/Voice/wear/src/main/java/com/example/show/voice/NotificationEmbeddedActivity.java b/ui/watch/Voice/wear/src/main/java/com/example/show/voice/NotificationEmbeddedActivity.java
new file mode 100644
index 00000000000..b9340c409f5
--- /dev/null
+++ b/ui/watch/Voice/wear/src/main/java/com/example/show/voice/NotificationEmbeddedActivity.java
@@ -0,0 +1,26 @@
+package com.example.show.voice;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.widget.TextView;
+
+public class NotificationEmbeddedActivity extends Activity {
+
+ public static final String EXTRA_KEY_COUNT = "extra_key_count";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_notification);
+
+ TextView textView = (TextView) findViewById(R.id.text);
+ Intent intent = getIntent();
+ int count = intent.getIntExtra(EXTRA_KEY_COUNT, -1);
+ if (count >= 0) {
+ textView.setText(String.format("count is %d", count));
+ } else {
+ textView.setText(String.format("Hello world!"));
+ }
+ }
+}
diff --git a/ui/watch/Voice/wear/src/main/java/com/example/show/voice/WatchActivity.java b/ui/watch/Voice/wear/src/main/java/com/example/show/voice/WatchActivity.java
new file mode 100644
index 00000000000..2c340df652b
--- /dev/null
+++ b/ui/watch/Voice/wear/src/main/java/com/example/show/voice/WatchActivity.java
@@ -0,0 +1,78 @@
+package com.example.show.voice;
+
+import android.app.Activity;
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v4.app.NotificationCompat;
+import android.support.v4.app.NotificationManagerCompat;
+import android.support.wearable.view.WatchViewStub;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+public class WatchActivity extends Activity {
+
+ private TextView mTextView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_watch);
+ final Context context = this;
+ final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
+ stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
+ @Override
+ public void onLayoutInflated(WatchViewStub stub) {
+ mTextView = (TextView) stub.findViewById(R.id.text);
+ ((Button) findViewById(R.id.button_notification_to_open_activity)).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ sendNotificationToOpenCustomActivity(context);
+ }
+ });
+ ((Button) findViewById(R.id.button_notification_display_intent)).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ sendNotificationWithDisplayIntent(context);
+ }
+ });
+ }
+ });
+ }
+
+ private void sendNotificationToOpenCustomActivity(Context context) {
+ Intent viewIntent = new Intent(context, WatchActivity.class);
+ PendingIntent pendingViewIntent = PendingIntent.getActivity(context, 0, viewIntent, 0);
+
+ Notification notification = new NotificationCompat.Builder(context)
+ .setSmallIcon(R.drawable.ic_launcher)
+ .setContentTitle("Wearableから送信")
+ .setContentText("Wearableから送信したNotificationです")
+ .addAction(R.drawable.ic_launcher, "Open", pendingViewIntent)
+ .setLocalOnly(true)
+ .extend(new NotificationCompat.WearableExtender().setContentAction(0).setHintHideIcon(true))
+ .build();
+
+ NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
+ notificationManager.notify(3000, notification);
+ }
+
+ private void sendNotificationWithDisplayIntent(Context context) {
+ Intent viewIntent = new Intent(context, NotificationEmbeddedActivity.class);
+ PendingIntent pendingViewIntent = PendingIntent.getActivity(context, 0, viewIntent, 0);
+
+ Notification notification = new NotificationCompat.Builder(context)
+ .setSmallIcon(R.drawable.ic_launcher)
+ .setContentTitle("Wearableから送信")
+ .setContentText("Wearableから送信したNotificationです")
+ .setLocalOnly(true)
+ .extend(new NotificationCompat.WearableExtender().setDisplayIntent(pendingViewIntent))
+ .build();
+
+ NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
+ notificationManager.notify(4000, notification);
+ }
+}
diff --git a/ui/watch/Voice/wear/src/main/res/drawable-hdpi/ic_launcher.png b/ui/watch/Voice/wear/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 00000000000..55621cc1074
Binary files /dev/null and b/ui/watch/Voice/wear/src/main/res/drawable-hdpi/ic_launcher.png differ
diff --git a/ui/watch/Voice/wear/src/main/res/drawable-mdpi/ic_launcher.png b/ui/watch/Voice/wear/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 00000000000..11ec2068be1
Binary files /dev/null and b/ui/watch/Voice/wear/src/main/res/drawable-mdpi/ic_launcher.png differ
diff --git a/ui/watch/Voice/wear/src/main/res/drawable-xhdpi/ic_launcher.png b/ui/watch/Voice/wear/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 00000000000..7c02b784aa5
Binary files /dev/null and b/ui/watch/Voice/wear/src/main/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/ui/watch/Voice/wear/src/main/res/drawable-xxhdpi/ic_launcher.png b/ui/watch/Voice/wear/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000000..915d9144134
Binary files /dev/null and b/ui/watch/Voice/wear/src/main/res/drawable-xxhdpi/ic_launcher.png differ
diff --git a/ui/watch/Voice/wear/src/main/res/layout/activity_notification.xml b/ui/watch/Voice/wear/src/main/res/layout/activity_notification.xml
new file mode 100644
index 00000000000..b4ee174c419
--- /dev/null
+++ b/ui/watch/Voice/wear/src/main/res/layout/activity_notification.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/ui/watch/Voice/wear/src/main/res/layout/activity_watch.xml b/ui/watch/Voice/wear/src/main/res/layout/activity_watch.xml
new file mode 100644
index 00000000000..009e5caae3a
--- /dev/null
+++ b/ui/watch/Voice/wear/src/main/res/layout/activity_watch.xml
@@ -0,0 +1,13 @@
+
+
+
diff --git a/ui/watch/Voice/wear/src/main/res/layout/rect_activity_watch.xml b/ui/watch/Voice/wear/src/main/res/layout/rect_activity_watch.xml
new file mode 100644
index 00000000000..f6cfc3359b9
--- /dev/null
+++ b/ui/watch/Voice/wear/src/main/res/layout/rect_activity_watch.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/Voice/wear/src/main/res/layout/round_activity_watch.xml b/ui/watch/Voice/wear/src/main/res/layout/round_activity_watch.xml
new file mode 100644
index 00000000000..5d355a55af8
--- /dev/null
+++ b/ui/watch/Voice/wear/src/main/res/layout/round_activity_watch.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/Voice/wear/src/main/res/mipmap-hdpi/ic_launcher.png b/ui/watch/Voice/wear/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 00000000000..cde69bcccec
Binary files /dev/null and b/ui/watch/Voice/wear/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/ui/watch/Voice/wear/src/main/res/mipmap-mdpi/ic_launcher.png b/ui/watch/Voice/wear/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 00000000000..c133a0cbd37
Binary files /dev/null and b/ui/watch/Voice/wear/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/ui/watch/Voice/wear/src/main/res/mipmap-xhdpi/ic_launcher.png b/ui/watch/Voice/wear/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 00000000000..bfa42f0e7b9
Binary files /dev/null and b/ui/watch/Voice/wear/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/ui/watch/Voice/wear/src/main/res/mipmap-xxhdpi/ic_launcher.png b/ui/watch/Voice/wear/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000000..324e72cdd74
Binary files /dev/null and b/ui/watch/Voice/wear/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/ui/watch/Voice/wear/src/main/res/values/strings.xml b/ui/watch/Voice/wear/src/main/res/values/strings.xml
new file mode 100644
index 00000000000..9cdd06d9056
--- /dev/null
+++ b/ui/watch/Voice/wear/src/main/res/values/strings.xml
@@ -0,0 +1,8 @@
+
+
+
+ VoiceWear
+ Hello Round World!
+ Hello Square World!
+
+
diff --git a/ui/watch/Voice/wear/wear.iml b/ui/watch/Voice/wear/wear.iml
new file mode 100644
index 00000000000..a4c64053a40
--- /dev/null
+++ b/ui/watch/Voice/wear/wear.iml
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ui/watch/mapdemo/.gitignore b/ui/watch/mapdemo/.gitignore
new file mode 100644
index 00000000000..9c4de5825b1
--- /dev/null
+++ b/ui/watch/mapdemo/.gitignore
@@ -0,0 +1,7 @@
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
diff --git a/ui/watch/mapdemo/app/.gitignore b/ui/watch/mapdemo/app/.gitignore
new file mode 100644
index 00000000000..796b96d1c40
--- /dev/null
+++ b/ui/watch/mapdemo/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/ui/watch/mapdemo/app/app.iml b/ui/watch/mapdemo/app/app.iml
new file mode 100644
index 00000000000..b09d738c016
--- /dev/null
+++ b/ui/watch/mapdemo/app/app.iml
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ui/watch/mapdemo/app/build.gradle b/ui/watch/mapdemo/app/build.gradle
new file mode 100644
index 00000000000..a30904a10b4
--- /dev/null
+++ b/ui/watch/mapdemo/app/build.gradle
@@ -0,0 +1,29 @@
+apply plugin: 'com.android.application'
+
+
+android {
+ compileSdkVersion 22
+ buildToolsVersion "23.0.0 rc3"
+
+ defaultConfig {
+ applicationId "com.example.mapdemo"
+ minSdkVersion 21
+ targetSdkVersion 22
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ compile 'com.google.android.support:wearable:1.2.0'
+ compile 'com.google.android.gms:play-services-wearable:7.5.0'
+ compile 'com.google.android.gms:play-services-maps:7.5.0'
+ compile 'com.google.android.gms:play-services-location:7.5.0'
+}
diff --git a/ui/watch/mapdemo/app/proguard-rules.pro b/ui/watch/mapdemo/app/proguard-rules.pro
new file mode 100644
index 00000000000..e93e140e0cd
--- /dev/null
+++ b/ui/watch/mapdemo/app/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in C:\Users\Show\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/ui/watch/mapdemo/app/src/main/AndroidManifest.xml b/ui/watch/mapdemo/app/src/main/AndroidManifest.xml
new file mode 100644
index 00000000000..01a16db92fc
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/AndroidManifest.xml
@@ -0,0 +1,142 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/BasicMapDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/BasicMapDemoActivity.java
new file mode 100644
index 00000000000..072f2280408
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/BasicMapDemoActivity.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+//first source
+/**
+ * This shows how to create a simple activity with a map and a marker on the map.
+ */
+//public class BasicMapDemoActivity extends FragmentActivity implements OnMapReadyCallback{
+//
+// @Override
+// protected void onCreate(Bundle savedInstanceState) {
+// super.onCreate(savedInstanceState);
+// setContentView(R.layout.basic_demo);
+//
+// SupportMapFragment mapFragment =
+// (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
+// mapFragment.getMapAsync(this);
+// }
+//
+// /**
+// * This is where we can add markers or lines, add listeners or move the camera. In this case, we
+// * just add a marker near Africa.
+// */
+// @Override
+// public void onMapReady(GoogleMap map) {
+// map.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
+// }
+//}
+
+//public class BasicMapDemoActivity extends FragmentActivity implements OnMapReadyCallback{
+// //GoogleMap.OnMapClickListener, GoogleMap.OnMapLongClickListener {
+//
+// private static final LatLng SYDNEY = new LatLng(-33.85704, 151.21522);
+// private GoogleMap mMap;
+//
+// @Override
+// protected void onCreate(Bundle savedInstanceState) {
+// super.onCreate(savedInstanceState);
+// setContentView(R.layout.basic_demo);
+//
+// SupportMapFragment mapFragment =
+// (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
+// mapFragment.getMapAsync(this);
+// }
+//
+// /**
+// * This is where we can add markers or lines, add listeners or move the camera. In this case, we
+// * just add a marker near Africa.
+// */
+// @Override
+// public void onMapReady(GoogleMap map) {
+// mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
+// mMap = map;
+// mMap.addMarker(new MarkerOptions().position(SYDNEY)
+// .title("Sydney Opera House"));
+// mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(SYDNEY, 10));
+// mMap.setOnMapLongClickListener(this);
+// }
+//
+//}
+
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.support.wearable.view.DismissOverlayView;
+import android.util.Log;
+import android.view.View;
+import android.view.WindowInsets;
+import android.widget.FrameLayout;
+
+import com.google.android.gms.common.ConnectionResult;
+import com.google.android.gms.common.api.GoogleApiClient;
+import com.google.android.gms.common.api.PendingResult;
+import com.google.android.gms.common.api.ResultCallback;
+import com.google.android.gms.common.api.Status;
+import com.google.android.gms.maps.CameraUpdateFactory;
+import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.OnMapReadyCallback;
+import com.google.android.gms.maps.SupportMapFragment;
+import com.google.android.gms.maps.model.LatLng;
+import com.google.android.gms.maps.model.MarkerOptions;
+import com.google.android.gms.wearable.MessageApi;
+import com.google.android.gms.wearable.Node;
+import com.google.android.gms.wearable.NodeApi;
+import com.google.android.gms.wearable.Wearable;
+
+/**
+ * Sample that shows how to set up a basic Google Map on Android Wear.
+ */
+public class BasicMapDemoActivity extends FragmentActivity implements OnMapReadyCallback,
+ GoogleMap.OnMapLongClickListener ,GoogleMap.OnMapClickListener,
+ GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,
+ GoogleMap.OnMyLocationButtonClickListener{
+
+ // private static final LatLng SYDNEY = new LatLng(-33.85704, 151.21522);
+ private static final LatLng SYDNEY = new LatLng(35.154979234025994,136.96567112207416); //Nagoya
+ private DismissOverlayView mDismissOverlay;
+ private GoogleMap mMap;
+ private boolean myLocation;
+ private GoogleApiClient mGoogleApiClient;
+
+ public void onCreate(Bundle savedState) {
+ super.onCreate(savedState);
+
+ mGoogleApiClient = new GoogleApiClient
+ .Builder(this)
+ .addConnectionCallbacks(this)
+ .addApi(Wearable.API)
+ .build();
+
+ myLocation = false;
+
+ // Set the layout. It only contains a SupportMapFragment and a DismissOverlay.
+ setContentView(R.layout.basic_demo);
+
+ // Retrieve the containers for the root of the layout and the map. Margins will need to be
+ // set on them to account for the system window insets.
+ final FrameLayout topFrameLayout = (FrameLayout) findViewById(R.id.root_container);
+ final FrameLayout mapFrameLayout = (FrameLayout) findViewById(R.id.map_container);
+
+ // Set the system view insets on the containers when they become available.
+ topFrameLayout.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
+ @Override
+ public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
+ // Call through to super implementation and apply insets
+ insets = topFrameLayout.onApplyWindowInsets(insets);
+
+ FrameLayout.LayoutParams params =
+ (FrameLayout.LayoutParams) mapFrameLayout.getLayoutParams();
+
+ // Add Wearable insets to FrameLayout container holding map as margins
+ params.setMargins(
+ insets.getSystemWindowInsetLeft(),
+ insets.getSystemWindowInsetTop(),
+ insets.getSystemWindowInsetRight(),
+ insets.getSystemWindowInsetBottom());
+ mapFrameLayout.setLayoutParams(params);
+
+ return insets;
+ }
+ });
+
+ // Obtain the DismissOverlayView and display the intro help text.
+ mDismissOverlay = (DismissOverlayView) findViewById(R.id.dismiss_overlay);
+ // mDismissOverlay.setIntroText(R.string.intro_text);
+ mDismissOverlay.showIntroIfNecessary();
+
+ // Obtain the MapFragment and set the async listener to be notified when the map is ready.
+ SupportMapFragment mapFragment =
+ (SupportMapFragment) getSupportFragmentManager()
+ .findFragmentById(R.id.map);
+ mapFragment.getMapAsync(this);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mGoogleApiClient.connect();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
+ mGoogleApiClient.disconnect();
+ }
+ }
+
+ @Override
+ public void onConnected(Bundle bundle) {
+ Log.d("TAG", "onConnected");
+ }
+
+ @Override
+ public void onConnectionSuspended(int i) {
+ Log.d("TAG", "onConnectionSuspended");
+ }
+
+ @Override
+ public void onConnectionFailed(ConnectionResult connectionResult) {
+ Log.e("TAG", "onConnectionFailed: " + connectionResult);
+ }
+
+ public void sendMessage(String str) {
+ final String message = str;
+ PendingResult nodes =
+ Wearable.NodeApi.getConnectedNodes(mGoogleApiClient);
+ nodes.setResultCallback(new ResultCallback() {
+ @Override
+ public void onResult(NodeApi.GetConnectedNodesResult result) {
+ //String messagePayload = "latitude:" + lng.latitude + "\nlongitude:" + lng.longitude;
+ for (Node node : result.getNodes()) {
+ final byte[] bs = (message/* + " " + node.getId()*/).getBytes();
+ PendingResult messageResult =
+ Wearable.MessageApi.sendMessage(mGoogleApiClient, node.getId(), "/messagesample", bs);
+ messageResult.setResultCallback(new ResultCallback() {
+ @Override
+ public void onResult(MessageApi.SendMessageResult sendMessageResult) {
+ Status status = sendMessageResult.getStatus();
+ Log.d("TAG", "Status: " + status.toString());
+ }
+ });
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onMapReady(GoogleMap googleMap) {
+ // Map is ready to be used.
+ mMap = googleMap;
+
+ // Set the long click listener as a way to exit the map.
+ mMap.setOnMapLongClickListener(this);
+
+ // Set the click listener as a way to exit the map.
+ mMap.setOnMapClickListener(this);
+
+ // Add a marker with a title that is shown in its info window.
+ // mMap.addMarker(new MarkerOptions().position(SYDNEY)
+ // .title("Sydney Opera House"));
+
+ // Move the camera to show the marker.
+ mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(SYDNEY, 10));
+ }
+
+ @Override
+ public void onMapLongClick(LatLng latLng) {
+ //Long tap: View my location.
+// mDismissOverlay.show(); //finish appli button
+ myLocation = !myLocation;
+ mMap.setMyLocationEnabled(myLocation);
+}
+
+ @Override
+ public void onMapClick(LatLng latLng) {
+ //Tap: Put marker and send this location to mobile.
+ mMap.clear();
+ mMap.addMarker(new MarkerOptions().position(latLng).title("Click Point"));
+ String message = " latitude : " + latLng.latitude + "\nlongitude : " + latLng.longitude;
+ sendMessage(message);
+ }
+
+ @Override
+ public boolean onMyLocationButtonClick() {
+ //Toast.makeText(this, "MyLocation button clicked", Toast.LENGTH_SHORT).show();
+ // Return false so that we don't consume the event and the default behavior still occurs
+ // (the camera animates to the user's current position).
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/CameraDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/CameraDemoActivity.java
new file mode 100644
index 00000000000..c8bb6c59795
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/CameraDemoActivity.java
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.CameraUpdate;
+import com.google.android.gms.maps.CameraUpdateFactory;
+import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.GoogleMap.CancelableCallback;
+import com.google.android.gms.maps.OnMapReadyCallback;
+import com.google.android.gms.maps.SupportMapFragment;
+import com.google.android.gms.maps.model.CameraPosition;
+import com.google.android.gms.maps.model.LatLng;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.view.View;
+import android.widget.CompoundButton;
+import android.widget.SeekBar;
+import android.widget.Toast;
+
+/**
+ * This shows how to change the camera position for the map.
+ */
+public class CameraDemoActivity extends FragmentActivity implements OnMapReadyCallback {
+
+ /**
+ * The amount by which to scroll the camera. Note that this amount is in raw pixels, not dp
+ * (density-independent pixels).
+ */
+ private static final int SCROLL_BY_PX = 100;
+
+ public static final CameraPosition BONDI =
+ new CameraPosition.Builder().target(new LatLng(-33.891614, 151.276417))
+ .zoom(15.5f)
+ .bearing(300)
+ .tilt(50)
+ .build();
+
+ public static final CameraPosition SYDNEY =
+ new CameraPosition.Builder().target(new LatLng(-33.87365, 151.20689))
+ .zoom(15.5f)
+ .bearing(0)
+ .tilt(25)
+ .build();
+
+ private GoogleMap mMap;
+
+ private CompoundButton mAnimateToggle;
+ private CompoundButton mCustomDurationToggle;
+ private SeekBar mCustomDurationBar;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.camera_demo);
+
+ mAnimateToggle = (CompoundButton) findViewById(R.id.animate);
+ mCustomDurationToggle = (CompoundButton) findViewById(R.id.duration_toggle);
+ mCustomDurationBar = (SeekBar) findViewById(R.id.duration_bar);
+
+ updateEnabledState();
+
+ SupportMapFragment mapFragment =
+ (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
+ mapFragment.getMapAsync(this);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ updateEnabledState();
+ }
+
+ @Override
+ public void onMapReady(GoogleMap map) {
+ mMap = map;
+
+ // We will provide our own zoom controls.
+ mMap.getUiSettings().setZoomControlsEnabled(false);
+
+ // Show Sydney
+ mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(-33.87365, 151.20689), 10));
+ }
+
+ /**
+ * When the map is not ready the CameraUpdateFactory cannot be used. This should be called on
+ * all entry points that call methods on the Google Maps API.
+ */
+ private boolean checkReady() {
+ if (mMap == null) {
+ Toast.makeText(this, R.string.map_not_ready, Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Called when the Go To Bondi button is clicked.
+ */
+ public void onGoToBondi(View view) {
+ if (!checkReady()) {
+ return;
+ }
+
+ changeCamera(CameraUpdateFactory.newCameraPosition(BONDI));
+ }
+
+ /**
+ * Called when the Animate To Sydney button is clicked.
+ */
+ public void onGoToSydney(View view) {
+ if (!checkReady()) {
+ return;
+ }
+
+ changeCamera(CameraUpdateFactory.newCameraPosition(SYDNEY), new CancelableCallback() {
+ @Override
+ public void onFinish() {
+ Toast.makeText(getBaseContext(), "Animation to Sydney complete", Toast.LENGTH_SHORT)
+ .show();
+ }
+
+ @Override
+ public void onCancel() {
+ Toast.makeText(getBaseContext(), "Animation to Sydney canceled", Toast.LENGTH_SHORT)
+ .show();
+ }
+ });
+ }
+
+ /**
+ * Called when the stop button is clicked.
+ */
+ public void onStopAnimation(View view) {
+ if (!checkReady()) {
+ return;
+ }
+
+ mMap.stopAnimation();
+ }
+
+ /**
+ * Called when the zoom in button (the one with the +) is clicked.
+ */
+ public void onZoomIn(View view) {
+ if (!checkReady()) {
+ return;
+ }
+
+ changeCamera(CameraUpdateFactory.zoomIn());
+ }
+
+ /**
+ * Called when the zoom out button (the one with the -) is clicked.
+ */
+ public void onZoomOut(View view) {
+ if (!checkReady()) {
+ return;
+ }
+
+ changeCamera(CameraUpdateFactory.zoomOut());
+ }
+
+ /**
+ * Called when the tilt more button (the one with the /) is clicked.
+ */
+ public void onTiltMore(View view) {
+ if (!checkReady()) {
+ return;
+ }
+
+ CameraPosition currentCameraPosition = mMap.getCameraPosition();
+ float currentTilt = currentCameraPosition.tilt;
+ float newTilt = currentTilt + 10;
+
+ newTilt = (newTilt > 90) ? 90 : newTilt;
+
+ CameraPosition cameraPosition = new CameraPosition.Builder(currentCameraPosition)
+ .tilt(newTilt).build();
+
+ changeCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
+ }
+
+ /**
+ * Called when the tilt less button (the one with the \) is clicked.
+ */
+ public void onTiltLess(View view) {
+ if (!checkReady()) {
+ return;
+ }
+
+ CameraPosition currentCameraPosition = mMap.getCameraPosition();
+
+ float currentTilt = currentCameraPosition.tilt;
+
+ float newTilt = currentTilt - 10;
+ newTilt = (newTilt > 0) ? newTilt : 0;
+
+ CameraPosition cameraPosition = new CameraPosition.Builder(currentCameraPosition)
+ .tilt(newTilt).build();
+
+ changeCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
+ }
+
+ /**
+ * Called when the left arrow button is clicked. This causes the camera to move to the left
+ */
+ public void onScrollLeft(View view) {
+ if (!checkReady()) {
+ return;
+ }
+
+ changeCamera(CameraUpdateFactory.scrollBy(-SCROLL_BY_PX, 0));
+ }
+
+ /**
+ * Called when the right arrow button is clicked. This causes the camera to move to the right.
+ */
+ public void onScrollRight(View view) {
+ if (!checkReady()) {
+ return;
+ }
+
+ changeCamera(CameraUpdateFactory.scrollBy(SCROLL_BY_PX, 0));
+ }
+
+ /**
+ * Called when the up arrow button is clicked. The causes the camera to move up.
+ */
+ public void onScrollUp(View view) {
+ if (!checkReady()) {
+ return;
+ }
+
+ changeCamera(CameraUpdateFactory.scrollBy(0, -SCROLL_BY_PX));
+ }
+
+ /**
+ * Called when the down arrow button is clicked. This causes the camera to move down.
+ */
+ public void onScrollDown(View view) {
+ if (!checkReady()) {
+ return;
+ }
+
+ changeCamera(CameraUpdateFactory.scrollBy(0, SCROLL_BY_PX));
+ }
+
+ /**
+ * Called when the animate button is toggled
+ */
+ public void onToggleAnimate(View view) {
+ updateEnabledState();
+ }
+
+ /**
+ * Called when the custom duration checkbox is toggled
+ */
+ public void onToggleCustomDuration(View view) {
+ updateEnabledState();
+ }
+
+ /**
+ * Update the enabled state of the custom duration controls.
+ */
+ private void updateEnabledState() {
+ mCustomDurationToggle.setEnabled(mAnimateToggle.isChecked());
+ mCustomDurationBar
+ .setEnabled(mAnimateToggle.isChecked() && mCustomDurationToggle.isChecked());
+ }
+
+ private void changeCamera(CameraUpdate update) {
+ changeCamera(update, null);
+ }
+
+ /**
+ * Change the camera position by moving or animating the camera depending on the state of the
+ * animate toggle button.
+ */
+ private void changeCamera(CameraUpdate update, CancelableCallback callback) {
+ if (mAnimateToggle.isChecked()) {
+ if (mCustomDurationToggle.isChecked()) {
+ int duration = mCustomDurationBar.getProgress();
+ // The duration must be strictly positive so we make it at least 1.
+ mMap.animateCamera(update, Math.max(duration, 1), callback);
+ } else {
+ mMap.animateCamera(update, callback);
+ }
+ } else {
+ mMap.moveCamera(update);
+ }
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/CircleDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/CircleDemoActivity.java
new file mode 100644
index 00000000000..fd08c3a77a5
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/CircleDemoActivity.java
@@ -0,0 +1,246 @@
+/* Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.CameraUpdateFactory;
+import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.GoogleMap.OnMapLongClickListener;
+import com.google.android.gms.maps.GoogleMap.OnMarkerDragListener;
+import com.google.android.gms.maps.OnMapReadyCallback;
+import com.google.android.gms.maps.SupportMapFragment;
+import com.google.android.gms.maps.model.BitmapDescriptorFactory;
+import com.google.android.gms.maps.model.Circle;
+import com.google.android.gms.maps.model.CircleOptions;
+import com.google.android.gms.maps.model.LatLng;
+import com.google.android.gms.maps.model.Marker;
+import com.google.android.gms.maps.model.MarkerOptions;
+
+import android.graphics.Color;
+import android.graphics.Point;
+import android.location.Location;
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.view.View;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * This shows how to draw circles on a map.
+ */
+public class CircleDemoActivity extends FragmentActivity implements OnSeekBarChangeListener,
+ OnMarkerDragListener, OnMapLongClickListener, OnMapReadyCallback {
+ private static final LatLng SYDNEY = new LatLng(-33.87365, 151.20689);
+ private static final double DEFAULT_RADIUS = 1000000;
+ public static final double RADIUS_OF_EARTH_METERS = 6371009;
+
+ private static final int WIDTH_MAX = 50;
+ private static final int HUE_MAX = 360;
+ private static final int ALPHA_MAX = 255;
+
+ private GoogleMap mMap;
+
+ private List mCircles = new ArrayList(1);
+
+ private SeekBar mColorBar;
+ private SeekBar mAlphaBar;
+ private SeekBar mWidthBar;
+ private int mStrokeColor;
+ private int mFillColor;
+
+ private class DraggableCircle {
+ private final Marker centerMarker;
+ private final Marker radiusMarker;
+ private final Circle circle;
+ private double radius;
+ public DraggableCircle(LatLng center, double radius) {
+ this.radius = radius;
+ centerMarker = mMap.addMarker(new MarkerOptions()
+ .position(center)
+ .draggable(true));
+ radiusMarker = mMap.addMarker(new MarkerOptions()
+ .position(toRadiusLatLng(center, radius))
+ .draggable(true)
+ .icon(BitmapDescriptorFactory.defaultMarker(
+ BitmapDescriptorFactory.HUE_AZURE)));
+ circle = mMap.addCircle(new CircleOptions()
+ .center(center)
+ .radius(radius)
+ .strokeWidth(mWidthBar.getProgress())
+ .strokeColor(mStrokeColor)
+ .fillColor(mFillColor));
+ }
+ public DraggableCircle(LatLng center, LatLng radiusLatLng) {
+ this.radius = toRadiusMeters(center, radiusLatLng);
+ centerMarker = mMap.addMarker(new MarkerOptions()
+ .position(center)
+ .draggable(true));
+ radiusMarker = mMap.addMarker(new MarkerOptions()
+ .position(radiusLatLng)
+ .draggable(true)
+ .icon(BitmapDescriptorFactory.defaultMarker(
+ BitmapDescriptorFactory.HUE_AZURE)));
+ circle = mMap.addCircle(new CircleOptions()
+ .center(center)
+ .radius(radius)
+ .strokeWidth(mWidthBar.getProgress())
+ .strokeColor(mStrokeColor)
+ .fillColor(mFillColor));
+ }
+ public boolean onMarkerMoved(Marker marker) {
+ if (marker.equals(centerMarker)) {
+ circle.setCenter(marker.getPosition());
+ radiusMarker.setPosition(toRadiusLatLng(marker.getPosition(), radius));
+ return true;
+ }
+ if (marker.equals(radiusMarker)) {
+ radius = toRadiusMeters(centerMarker.getPosition(), radiusMarker.getPosition());
+ circle.setRadius(radius);
+ return true;
+ }
+ return false;
+ }
+ public void onStyleChange() {
+ circle.setStrokeWidth(mWidthBar.getProgress());
+ circle.setFillColor(mFillColor);
+ circle.setStrokeColor(mStrokeColor);
+ }
+ }
+
+ /** Generate LatLng of radius marker */
+ private static LatLng toRadiusLatLng(LatLng center, double radius) {
+ double radiusAngle = Math.toDegrees(radius / RADIUS_OF_EARTH_METERS) /
+ Math.cos(Math.toRadians(center.latitude));
+ return new LatLng(center.latitude, center.longitude + radiusAngle);
+ }
+
+ private static double toRadiusMeters(LatLng center, LatLng radius) {
+ float[] result = new float[1];
+ Location.distanceBetween(center.latitude, center.longitude,
+ radius.latitude, radius.longitude, result);
+ return result[0];
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.circle_demo);
+
+ mColorBar = (SeekBar) findViewById(R.id.hueSeekBar);
+ mColorBar.setMax(HUE_MAX);
+ mColorBar.setProgress(0);
+
+ mAlphaBar = (SeekBar) findViewById(R.id.alphaSeekBar);
+ mAlphaBar.setMax(ALPHA_MAX);
+ mAlphaBar.setProgress(127);
+
+ mWidthBar = (SeekBar) findViewById(R.id.widthSeekBar);
+ mWidthBar.setMax(WIDTH_MAX);
+ mWidthBar.setProgress(10);
+
+ SupportMapFragment mapFragment =
+ (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
+ mapFragment.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(GoogleMap map) {
+ mMap = map;
+
+ // Override the default content description on the view, for accessibility mode.
+ // Ideally this string would be localised.
+ map.setContentDescription("Google Map with circles.");
+
+ mColorBar.setOnSeekBarChangeListener(this);
+ mAlphaBar.setOnSeekBarChangeListener(this);
+ mWidthBar.setOnSeekBarChangeListener(this);
+ mMap.setOnMarkerDragListener(this);
+ mMap.setOnMapLongClickListener(this);
+
+ mFillColor = Color.HSVToColor(
+ mAlphaBar.getProgress(), new float[] {mColorBar.getProgress(), 1, 1});
+ mStrokeColor = Color.BLACK;
+
+ DraggableCircle circle = new DraggableCircle(SYDNEY, DEFAULT_RADIUS);
+ mCircles.add(circle);
+
+ // Move the map so that it is centered on the initial circle
+ mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(SYDNEY, 4.0f));
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ // Don't do anything here.
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // Don't do anything here.
+ }
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ if (seekBar == mColorBar) {
+ mFillColor = Color.HSVToColor(Color.alpha(mFillColor), new float[] {progress, 1, 1});
+ } else if (seekBar == mAlphaBar) {
+ mFillColor = Color.argb(progress, Color.red(mFillColor), Color.green(mFillColor),
+ Color.blue(mFillColor));
+ }
+
+ for (DraggableCircle draggableCircle : mCircles) {
+ draggableCircle.onStyleChange();
+ }
+ }
+
+ @Override
+ public void onMarkerDragStart(Marker marker) {
+ onMarkerMoved(marker);
+ }
+
+ @Override
+ public void onMarkerDragEnd(Marker marker) {
+ onMarkerMoved(marker);
+ }
+
+ @Override
+ public void onMarkerDrag(Marker marker) {
+ onMarkerMoved(marker);
+ }
+
+ private void onMarkerMoved(Marker marker) {
+ for (DraggableCircle draggableCircle : mCircles) {
+ if (draggableCircle.onMarkerMoved(marker)) {
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void onMapLongClick(LatLng point) {
+ // We know the center, let's place the outline at a point 3/4 along the view.
+ View view = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
+ .getView();
+ LatLng radiusLatLng = mMap.getProjection().fromScreenLocation(new Point(
+ view.getHeight() * 3 / 4, view.getWidth() * 3 / 4));
+
+ // ok create it
+ DraggableCircle circle = new DraggableCircle(point, radiusLatLng);
+ mCircles.add(circle);
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/DemoDetails.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/DemoDetails.java
new file mode 100644
index 00000000000..eadf5e257f3
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/DemoDetails.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import android.support.v4.app.FragmentActivity;
+
+/**
+ * A simple POJO that holds the details about the demo that are used by the List Adapter.
+ */
+public class DemoDetails {
+ /**
+ * The resource id of the title of the demo.
+ */
+ public final int titleId;
+
+ /**
+ * The resources id of the description of the demo.
+ */
+ public final int descriptionId;
+
+ /**
+ * The demo activity's class.
+ */
+ public final Class extends FragmentActivity> activityClass;
+
+ public DemoDetails(
+ int titleId, int descriptionId, Class extends FragmentActivity> activityClass) {
+ this.titleId = titleId;
+ this.descriptionId = descriptionId;
+ this.activityClass = activityClass;
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/DemoDetailsList.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/DemoDetailsList.java
new file mode 100644
index 00000000000..0fbddb2bc4c
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/DemoDetailsList.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+/**
+ * A list of all the demos we have available.
+ */
+public final class DemoDetailsList {
+
+ /** This class should not be instantiated. */
+ private DemoDetailsList() {}
+
+ public static final DemoDetails[] DEMOS = {
+ new DemoDetails(R.string.basic_map_demo_label,
+ R.string.basic_map_demo_description,
+ BasicMapDemoActivity.class),
+ new DemoDetails(R.string.camera_demo_label,
+ R.string.camera_demo_description,
+ CameraDemoActivity.class),
+ new DemoDetails(R.string.circle_demo_label,
+ R.string.circle_demo_description,
+ CircleDemoActivity.class),
+ new DemoDetails(R.string.events_demo_label,
+ R.string.events_demo_description,
+ EventsDemoActivity.class),
+ new DemoDetails(R.string.ground_overlay_demo_label,
+ R.string.ground_overlay_demo_description,
+ GroundOverlayDemoActivity.class),
+ new DemoDetails(R.string.indoor_demo_label,
+ R.string.indoor_demo_description,
+ IndoorDemoActivity.class),
+ new DemoDetails(R.string.layers_demo_label,
+ R.string.layers_demo_description,
+ LayersDemoActivity.class),
+ new DemoDetails(R.string.lite_demo_label,
+ R.string.lite_demo_description,
+ LiteDemoActivity.class),
+ new DemoDetails(R.string.lite_list_demo_label,
+ R.string.lite_list_demo_description,
+ LiteListDemoActivity.class),
+ new DemoDetails(R.string.location_source_demo_label,
+ R.string.location_source_demo_description,
+ LocationSourceDemoActivity.class),
+ new DemoDetails(R.string.map_in_pager_demo_label,
+ R.string.map_in_pager_demo_description,
+ MapInPagerDemoActivity.class),
+ new DemoDetails(R.string.marker_demo_label,
+ R.string.marker_demo_description,
+ MarkerDemoActivity.class),
+ new DemoDetails(R.string.multi_map_demo_label,
+ R.string.multi_map_demo_description,
+ MultiMapDemoActivity.class),
+ new DemoDetails(R.string.my_location_demo_label,
+ R.string.my_location_demo_description,
+ MyLocationDemoActivity.class),
+ new DemoDetails(R.string.options_demo_label,
+ R.string.options_demo_description,
+ OptionsDemoActivity.class),
+ new DemoDetails(R.string.polygon_demo_label,
+ R.string.polygon_demo_description,
+ PolygonDemoActivity.class),
+ new DemoDetails(R.string.polyline_demo_label,
+ R.string.polyline_demo_description,
+ PolylineDemoActivity.class),
+ new DemoDetails(R.string.programmatic_demo_label,
+ R.string.programmatic_demo_description,
+ ProgrammaticDemoActivity.class),
+ new DemoDetails(R.string.raw_map_view_demo_label,
+ R.string.raw_map_view_demo_description,
+ RawMapViewDemoActivity.class),
+ new DemoDetails(R.string.retain_map_demo_label,
+ R.string.retain_map_demo_description,
+ RetainMapDemoActivity.class),
+ new DemoDetails(R.string.save_state_demo_label,
+ R.string.save_state_demo_description,
+ SaveStateDemoActivity.class),
+ new DemoDetails(R.string.snapshot_demo_label,
+ R.string.snapshot_demo_description,
+ SnapshotDemoActivity.class),
+ new DemoDetails(R.string.split_street_view_panorama_and_map_demo_label,
+ R.string.split_street_view_panorama_and_map_demo_description,
+ SplitStreetViewPanoramaAndMapDemoActivity.class),
+ new DemoDetails(R.string.street_view_panorama_basic_demo_label,
+ R.string.street_view_panorama_basic_demo_description,
+ StreetViewPanoramaBasicDemoActivity.class),
+ new DemoDetails(R.string.street_view_panorama_events_demo_label,
+ R.string.street_view_panorama_events_demo_description,
+ StreetViewPanoramaEventsDemoActivity.class),
+ new DemoDetails(R.string.street_view_panorama_navigation_demo_label,
+ R.string.street_view_panorama_navigation_demo_description,
+ StreetViewPanoramaNavigationDemoActivity.class),
+ new DemoDetails(R.string.street_view_panorama_options_demo_label,
+ R.string.street_view_panorama_options_demo_description,
+ StreetViewPanoramaOptionsDemoActivity.class),
+ new DemoDetails(R.string.street_view_panorama_view_demo_label,
+ R.string.street_view_panorama_view_demo_description,
+ StreetViewPanoramaViewDemoActivity.class),
+ new DemoDetails(R.string.tile_coordinate_demo_label,
+ R.string.tile_coordinate_demo_description,
+ TileCoordinateDemoActivity.class),
+ new DemoDetails(R.string.tile_overlay_demo_label,
+ R.string.tile_overlay_demo_description,
+ TileOverlayDemoActivity.class),
+ new DemoDetails(R.string.ui_settings_demo_label,
+ R.string.ui_settings_demo_description,
+ UiSettingsDemoActivity.class),
+ new DemoDetails(R.string.visible_region_demo_label,
+ R.string.visible_region_demo_description,
+ VisibleRegionDemoActivity.class),
+ };
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/EventsDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/EventsDemoActivity.java
new file mode 100644
index 00000000000..17276d1d25f
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/EventsDemoActivity.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.GoogleMap.OnCameraChangeListener;
+import com.google.android.gms.maps.GoogleMap.OnMapClickListener;
+import com.google.android.gms.maps.GoogleMap.OnMapLongClickListener;
+import com.google.android.gms.maps.OnMapReadyCallback;
+import com.google.android.gms.maps.SupportMapFragment;
+import com.google.android.gms.maps.model.CameraPosition;
+import com.google.android.gms.maps.model.LatLng;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.widget.TextView;
+
+/**
+ * This shows how to listen to some {@link GoogleMap} events.
+ */
+public class EventsDemoActivity extends FragmentActivity
+ implements OnMapClickListener, OnMapLongClickListener, OnCameraChangeListener,
+ OnMapReadyCallback {
+
+ private TextView mTapTextView;
+ private TextView mCameraTextView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.events_demo);
+
+ mTapTextView = (TextView) findViewById(R.id.tap_text);
+ mCameraTextView = (TextView) findViewById(R.id.camera_text);
+
+ SupportMapFragment mapFragment =
+ (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
+ mapFragment.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(GoogleMap map) {
+ map.setOnMapClickListener(this);
+ map.setOnMapLongClickListener(this);
+ map.setOnCameraChangeListener(this);
+ }
+
+ @Override
+ public void onMapClick(LatLng point) {
+ mTapTextView.setText("tapped, point=" + point);
+ }
+
+ @Override
+ public void onMapLongClick(LatLng point) {
+ mTapTextView.setText("long pressed, point=" + point);
+ }
+
+ @Override
+ public void onCameraChange(final CameraPosition position) {
+ mCameraTextView.setText(position.toString());
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/FeatureView.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/FeatureView.java
new file mode 100644
index 00000000000..c14e03b99e5
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/FeatureView.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+
+/**
+ * A widget that describes an activity that demonstrates a feature.
+ */
+public final class FeatureView extends FrameLayout {
+
+ /**
+ * Constructs a feature view by inflating layout/feature.xml.
+ */
+ public FeatureView(Context context) {
+ super(context);
+
+ LayoutInflater layoutInflater =
+ (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ layoutInflater.inflate(R.layout.feature, this);
+ }
+
+ /**
+ * Set the resource id of the title of the demo.
+ *
+ * @param titleId the resource id of the title of the demo
+ */
+ public synchronized void setTitleId(int titleId) {
+ ((TextView) (findViewById(R.id.title))).setText(titleId);
+ }
+
+ /**
+ * Set the resource id of the description of the demo.
+ *
+ * @param descriptionId the resource id of the description of the demo
+ */
+ public synchronized void setDescriptionId(int descriptionId) {
+ ((TextView) (findViewById(R.id.description))).setText(descriptionId);
+ }
+
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/GroundOverlayDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/GroundOverlayDemoActivity.java
new file mode 100644
index 00000000000..e01c38fa925
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/GroundOverlayDemoActivity.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.CameraUpdateFactory;
+import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.OnMapReadyCallback;
+import com.google.android.gms.maps.SupportMapFragment;
+import com.google.android.gms.maps.model.BitmapDescriptor;
+import com.google.android.gms.maps.model.BitmapDescriptorFactory;
+import com.google.android.gms.maps.model.GroundOverlay;
+import com.google.android.gms.maps.model.GroundOverlayOptions;
+import com.google.android.gms.maps.model.LatLng;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.view.View;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This shows how to add a ground overlay to a map.
+ */
+public class GroundOverlayDemoActivity extends FragmentActivity
+ implements OnSeekBarChangeListener, OnMapReadyCallback {
+
+ private static final int TRANSPARENCY_MAX = 100;
+ private static final LatLng NEWARK = new LatLng(40.714086, -74.228697);
+
+ private final List mImages = new ArrayList();
+
+ private GroundOverlay mGroundOverlay;
+ private SeekBar mTransparencyBar;
+
+ private int mCurrentEntry = 0;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.ground_overlay_demo);
+
+ mTransparencyBar = (SeekBar) findViewById(R.id.transparencySeekBar);
+ mTransparencyBar.setMax(TRANSPARENCY_MAX);
+ mTransparencyBar.setProgress(0);
+
+ SupportMapFragment mapFragment =
+ (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
+ mapFragment.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(GoogleMap map) {
+ map.moveCamera(CameraUpdateFactory.newLatLngZoom(NEWARK, 11));
+
+ mImages.clear();
+ mImages.add(BitmapDescriptorFactory.fromResource(R.drawable.newark_nj_1922));
+ mImages.add(BitmapDescriptorFactory.fromResource(R.drawable.newark_prudential_sunny));
+
+ mCurrentEntry = 0;
+ mGroundOverlay = map.addGroundOverlay(new GroundOverlayOptions()
+ .image(mImages.get(mCurrentEntry)).anchor(0, 1)
+ .position(NEWARK, 8600f, 6500f));
+
+ mTransparencyBar.setOnSeekBarChangeListener(this);
+
+ // Override the default content description on the view, for accessibility mode.
+ // Ideally this string would be localised.
+ map.setContentDescription("Google Map with ground overlay.");
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ }
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ if (mGroundOverlay != null) {
+ mGroundOverlay.setTransparency((float) progress / (float) TRANSPARENCY_MAX);
+ }
+ }
+
+ public void switchImage(View view) {
+ mCurrentEntry = (mCurrentEntry + 1) % mImages.size();
+ mGroundOverlay.setImage(mImages.get(mCurrentEntry));
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/IndoorDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/IndoorDemoActivity.java
new file mode 100644
index 00000000000..8d3e2f2b5e2
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/IndoorDemoActivity.java
@@ -0,0 +1,133 @@
+/* Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.CameraUpdateFactory;
+import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.OnMapReadyCallback;
+import com.google.android.gms.maps.SupportMapFragment;
+import com.google.android.gms.maps.model.IndoorBuilding;
+import com.google.android.gms.maps.model.IndoorLevel;
+import com.google.android.gms.maps.model.LatLng;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.view.View;
+import android.widget.TextView;
+
+import java.util.List;
+
+/**
+ * A demo activity showing how to use indoor.
+ */
+public class IndoorDemoActivity extends FragmentActivity implements OnMapReadyCallback {
+
+ private GoogleMap mMap;
+
+ private boolean showLevelPicker = true;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.indoor_demo);
+
+ SupportMapFragment mapFragment =
+ (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
+ mapFragment.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(GoogleMap map) {
+ mMap = map;
+ mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(37.614631, -122.385153), 18));
+ }
+
+ /**
+ * Called when the toggle level picker button is clicked.
+ */
+ public void onToggleLevelPicker(View view) {
+ showLevelPicker = !showLevelPicker;
+ mMap.getUiSettings().setIndoorLevelPickerEnabled(showLevelPicker);
+ }
+
+ /**
+ * Called when the focused building info is clicked.
+ */
+ public void onFocusedBuildingInfo(View view) {
+ IndoorBuilding building = mMap.getFocusedBuilding();
+ if (building != null) {
+ StringBuilder s = new StringBuilder();
+ for (IndoorLevel level : building.getLevels()) {
+ s.append(level.getName()).append(" ");
+ }
+ if (building.isUnderground()) {
+ s.append("is underground");
+ }
+ setText(s.toString());
+ } else {
+ setText("No visible building");
+ }
+ }
+
+ /**
+ * Called when the focused level info is clicked.
+ */
+ public void onVisibleLevelInfo(View view) {
+ IndoorBuilding building = mMap.getFocusedBuilding();
+ if (building != null) {
+ IndoorLevel level =
+ building.getLevels().get(building.getActiveLevelIndex());
+ if (level != null) {
+ setText(level.getName());
+ } else {
+ setText("No visible level");
+ }
+ } else {
+ setText("No visible building");
+ }
+ }
+
+ /**
+ * Called when the activate higher level is clicked.
+ */
+ public void onHigherLevel(View view) {
+ IndoorBuilding building = mMap.getFocusedBuilding();
+ if (building != null) {
+ List levels = building.getLevels();
+ if (!levels.isEmpty()) {
+ int currentLevel = building.getActiveLevelIndex();
+ // The levels are in 'display order' from top to bottom,
+ // i.e. higher levels in the building are lower numbered in the array.
+ int newLevel = currentLevel - 1;
+ if (newLevel == -1) {
+ newLevel = levels.size() - 1;
+ }
+ IndoorLevel level = levels.get(newLevel);
+ setText("Activiating level " + level.getName());
+ level.activate();
+ } else {
+ setText("No levels in building");
+ }
+ } else {
+ setText("No visible building");
+ }
+ }
+
+ private void setText(String message) {
+ TextView text = (TextView) findViewById(R.id.top_text);
+ text.setText(message);
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/LayersDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/LayersDemoActivity.java
new file mode 100644
index 00000000000..48812e82aa1
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/LayersDemoActivity.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import static com.google.android.gms.maps.GoogleMap.MAP_TYPE_HYBRID;
+import static com.google.android.gms.maps.GoogleMap.MAP_TYPE_NONE;
+import static com.google.android.gms.maps.GoogleMap.MAP_TYPE_NORMAL;
+import static com.google.android.gms.maps.GoogleMap.MAP_TYPE_SATELLITE;
+import static com.google.android.gms.maps.GoogleMap.MAP_TYPE_TERRAIN;
+
+import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.OnMapReadyCallback;
+import com.google.android.gms.maps.SupportMapFragment;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.util.Log;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.ArrayAdapter;
+import android.widget.CheckBox;
+import android.widget.Spinner;
+import android.widget.Toast;
+
+/**
+ * Demonstrates the different base layers of a map.
+ */
+public class LayersDemoActivity extends FragmentActivity
+ implements OnItemSelectedListener, OnMapReadyCallback {
+
+ private GoogleMap mMap;
+
+ private CheckBox mTrafficCheckbox;
+ private CheckBox mMyLocationCheckbox;
+ private CheckBox mBuildingsCheckbox;
+ private CheckBox mIndoorCheckbox;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.layers_demo);
+
+ Spinner spinner = (Spinner) findViewById(R.id.layers_spinner);
+ ArrayAdapter adapter = ArrayAdapter.createFromResource(
+ this, R.array.layers_array, android.R.layout.simple_spinner_item);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ spinner.setAdapter(adapter);
+ spinner.setOnItemSelectedListener(this);
+
+ mTrafficCheckbox = (CheckBox) findViewById(R.id.traffic);
+ mMyLocationCheckbox = (CheckBox) findViewById(R.id.my_location);
+ mBuildingsCheckbox = (CheckBox) findViewById(R.id.buildings);
+ mIndoorCheckbox = (CheckBox) findViewById(R.id.indoor);
+
+ SupportMapFragment mapFragment =
+ (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
+ mapFragment.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(GoogleMap map) {
+ mMap = map;
+ updateTraffic();
+ updateMyLocation();
+ updateBuildings();
+ updateIndoor();
+ }
+
+ private boolean checkReady() {
+ if (mMap == null) {
+ Toast.makeText(this, R.string.map_not_ready, Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Called when the Traffic checkbox is clicked.
+ */
+ public void onTrafficToggled(View view) {
+ updateTraffic();
+ }
+
+ private void updateTraffic() {
+ if (!checkReady()) {
+ return;
+ }
+ mMap.setTrafficEnabled(mTrafficCheckbox.isChecked());
+ }
+
+ /**
+ * Called when the MyLocation checkbox is clicked.
+ */
+ public void onMyLocationToggled(View view) {
+ updateMyLocation();
+ }
+
+ private void updateMyLocation() {
+ if (!checkReady()) {
+ return;
+ }
+ mMap.setMyLocationEnabled(mMyLocationCheckbox.isChecked());
+ }
+
+ /**
+ * Called when the Buildings checkbox is clicked.
+ */
+ public void onBuildingsToggled(View view) {
+ updateBuildings();
+ }
+
+ private void updateBuildings() {
+ if (!checkReady()) {
+ return;
+ }
+ mMap.setBuildingsEnabled(mBuildingsCheckbox.isChecked());
+ }
+
+ /**
+ * Called when the Indoor checkbox is clicked.
+ */
+ public void onIndoorToggled(View view) {
+ updateIndoor();
+ }
+
+ private void updateIndoor() {
+ if (!checkReady()) {
+ return;
+ }
+ mMap.setIndoorEnabled(mIndoorCheckbox.isChecked());
+ }
+
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+ // This is also called by the Android framework in onResume(). The map may not be created at
+ // this stage yet.
+ if (mMap != null) {
+ setLayer((String) parent.getItemAtPosition(position));
+ }
+ }
+
+ private void setLayer(String layerName) {
+ if (layerName.equals(getString(R.string.normal))) {
+ mMap.setMapType(MAP_TYPE_NORMAL);
+ } else if (layerName.equals(getString(R.string.hybrid))) {
+ mMap.setMapType(MAP_TYPE_HYBRID);
+
+
+
+
+ } else if (layerName.equals(getString(R.string.satellite))) {
+ mMap.setMapType(MAP_TYPE_SATELLITE);
+ } else if (layerName.equals(getString(R.string.terrain))) {
+ mMap.setMapType(MAP_TYPE_TERRAIN);
+ } else if (layerName.equals(getString(R.string.none_map))) {
+ mMap.setMapType(MAP_TYPE_NONE);
+ } else {
+ Log.i("LDA", "Error setting layer with name " + layerName);
+ }
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) {
+ // Do nothing.
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/LegalInfoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/LegalInfoActivity.java
new file mode 100644
index 00000000000..9fa0bef6fa2
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/LegalInfoActivity.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import com.google.android.gms.common.GooglePlayServicesUtil;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+
+/**
+ * Activity to show legal information.
+ */
+public class LegalInfoActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.legal_info);
+
+ TextView legalInfoTextView = (TextView) findViewById(R.id.legal_info);
+ String openSourceSoftwareLicenseInfo =
+ GooglePlayServicesUtil.getOpenSourceSoftwareLicenseInfo(this);
+ if (openSourceSoftwareLicenseInfo != null) {
+ legalInfoTextView.setText(openSourceSoftwareLicenseInfo);
+ } else {
+ legalInfoTextView.setText(R.string.play_services_not_installed);
+ }
+ }
+
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/LiteDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/LiteDemoActivity.java
new file mode 100644
index 00000000000..7bde9ae4ca1
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/LiteDemoActivity.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+
+import com.google.android.gms.maps.CameraUpdateFactory;
+import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.OnMapReadyCallback;
+import com.google.android.gms.maps.SupportMapFragment;
+import com.google.android.gms.maps.model.BitmapDescriptorFactory;
+import com.google.android.gms.maps.model.LatLng;
+import com.google.android.gms.maps.model.LatLngBounds;
+import com.google.android.gms.maps.model.MarkerOptions;
+import com.google.android.gms.maps.model.PolygonOptions;
+import com.google.android.gms.maps.model.PolylineOptions;
+
+import android.annotation.SuppressLint;
+import android.graphics.Color;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.view.View;
+import android.view.ViewTreeObserver.OnGlobalLayoutListener;
+
+/**
+ * This demo shows some features supported in lite mode.
+ * In particular it demonstrates the use of {@link com.google.android.gms.maps.model.Marker}s to
+ * launch the Google Maps Mobile application, {@link com.google.android.gms.maps.CameraUpdate}s
+ * and {@link com.google.android.gms.maps.model.Polygon}s.
+ */
+public class LiteDemoActivity extends FragmentActivity implements OnMapReadyCallback {
+
+ private static final LatLng BRISBANE = new LatLng(-27.47093, 153.0235);
+ private static final LatLng MELBOURNE = new LatLng(-37.81319, 144.96298);
+ private static final LatLng SYDNEY = new LatLng(-33.87365, 151.20689);
+ private static final LatLng ADELAIDE = new LatLng(-34.92873, 138.59995);
+ private static final LatLng PERTH = new LatLng(-31.952854, 115.857342);
+ private static final LatLng DARWIN = new LatLng(-12.459501, 130.839915);
+
+ /**
+ * A Polygon with five points in the Norther Territory, Australia.
+ */
+ private static final LatLng[] POLYGON = new LatLng[]{
+ new LatLng(-18.000328, 130.473633), new LatLng(-16.173880, 135.087891),
+ new LatLng(-19.663970, 137.724609), new LatLng(-23.202307, 135.395508),
+ new LatLng(-19.705347, 129.550781)};
+
+ private GoogleMap mMap;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Set the layout
+ setContentView(R.layout.lite_demo);
+
+ // Get the map and register for the ready callback
+ SupportMapFragment mapFragment =
+ (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
+ mapFragment.getMapAsync(this);
+ }
+
+ /**
+ * Move the camera to center on Darwin.
+ */
+ public void showDarwin(View v) {
+ // Wait until map is ready
+ if (mMap == null) {
+ return;
+ }
+
+ // Center camera on Adelaide marker
+ mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(DARWIN, 10f));
+ }
+
+ /**
+ * Move the camera to center on Adelaide.
+ */
+ public void showAdelaide(View v) {
+ // Wait until map is ready
+ if (mMap == null) {
+ return;
+ }
+
+ // Center camera on Adelaide marker
+ mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(ADELAIDE, 10f));
+ }
+
+ /**
+ * Move the camera to show all of Australia.
+ * Construct a {@link com.google.android.gms.maps.model.LatLngBounds} from markers positions,
+ * then move the camera.
+ */
+ public void showAustralia(View v) {
+ // Wait until map is ready
+ if (mMap == null) {
+ return;
+ }
+
+ // Create bounds that include all locations of the map
+ LatLngBounds.Builder boundsBuilder = LatLngBounds.builder()
+ .include(PERTH)
+ .include(ADELAIDE)
+ .include(MELBOURNE)
+ .include(SYDNEY)
+ .include(DARWIN)
+ .include(BRISBANE);
+
+ // Move camera to show all markers and locations
+ mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(boundsBuilder.build(), 20));
+ }
+
+ /**
+ * Called when the map is ready to add all markers and objects to the map.
+ *
+ * @param googleMap
+ */
+ @Override
+ public void onMapReady(GoogleMap googleMap) {
+ mMap = googleMap;
+ addMarkers();
+ addPolyobjects();
+
+ final View mapView = getSupportFragmentManager().findFragmentById(R.id.map).getView();
+ if (mapView.getViewTreeObserver().isAlive()) {
+ mapView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
+ @SuppressWarnings("deprecation") // We use the new method when supported
+ @SuppressLint("NewApi") // We check which build version we are using.
+ @Override
+ public void onGlobalLayout() {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
+ mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
+ } else {
+ mapView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+ }
+ showAustralia(null);
+ }
+ });
+ }
+ }
+
+ /**
+ * Add a Polyline and a Polygon to the map.
+ * The Polyline connects Melbourne, Adelaide and Perth. The Polygon is located in the Northern
+ * Territory (Australia).
+ */
+ private void addPolyobjects() {
+ mMap.addPolyline((new PolylineOptions())
+ .add(MELBOURNE, ADELAIDE, PERTH)
+ .color(Color.GREEN)
+ .width(5f));
+
+ mMap.addPolygon(new PolygonOptions()
+ .add(POLYGON)
+ .fillColor(Color.CYAN)
+ .strokeColor(Color.BLUE)
+ .strokeWidth(5));
+ }
+
+ /**
+ * Add Markers with default info windows to the map.
+ */
+ private void addMarkers() {
+ mMap.addMarker(new MarkerOptions()
+ .position(BRISBANE)
+ .title("Brisbane"));
+
+ mMap.addMarker(new MarkerOptions()
+ .position(MELBOURNE)
+ .title("Melbourne")
+ .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE)));
+
+ mMap.addMarker(new MarkerOptions()
+ .position(SYDNEY)
+ .title("Sydney")
+ .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
+
+ mMap.addMarker(new MarkerOptions()
+ .position(ADELAIDE)
+ .title("Adelaide")
+ .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_YELLOW)));
+
+ mMap.addMarker(new MarkerOptions()
+ .position(PERTH)
+ .title("Perth")
+ .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA)));
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/LiteListDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/LiteListDemoActivity.java
new file mode 100644
index 00000000000..b38191dd0a4
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/LiteListDemoActivity.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.CameraUpdateFactory;
+import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.MapView;
+import com.google.android.gms.maps.MapsInitializer;
+import com.google.android.gms.maps.OnMapReadyCallback;
+import com.google.android.gms.maps.model.LatLng;
+import com.google.android.gms.maps.model.MarkerOptions;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.ListFragment;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.ArrayAdapter;
+import android.widget.TextView;
+
+import java.util.HashSet;
+
+/**
+ * This shows to include a map in lite mode in a ListView.
+ * Note the use of the view holder pattern with the
+ * {@link com.google.android.gms.maps.OnMapReadyCallback}.
+ */
+public class LiteListDemoActivity extends FragmentActivity {
+
+ private ListFragment mList;
+ private MapAdapter mAdapter;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.lite_list_demo);
+
+ // Set a custom list adapter for a list of locations
+ mAdapter = new MapAdapter(this, LIST_LOCATIONS);
+ mList = (ListFragment) getSupportFragmentManager().findFragmentById(R.id.list);
+ mList.setListAdapter(mAdapter);
+
+ // Set a RecyclerListener to clean up MapView from ListView
+ AbsListView lv = mList.getListView();
+ lv.setRecyclerListener(mRecycleListener);
+
+ }
+
+ /**
+ * Adapter that displays a title and {@link com.google.android.gms.maps.MapView} for each item.
+ * The layout is defined in lite_list_demo_row.xml. It contains a MapView
+ * that is programatically initialised in
+ * {@link #getView(int, android.view.View, android.view.ViewGroup)}
+ */
+ private class MapAdapter extends ArrayAdapter {
+
+ private final HashSet mMaps = new HashSet();
+
+ public MapAdapter(Context context, NamedLocation[] locations) {
+ super(context, R.layout.lite_list_demo_row, R.id.lite_listrow_text, locations);
+ }
+
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ View row = convertView;
+ ViewHolder holder;
+
+ // Check if a view can be reused, otherwise inflate a layout and set up the view holder
+ if (row == null) {
+ // Inflate view from layout file
+ row = getLayoutInflater().inflate(R.layout.lite_list_demo_row, null);
+
+ // Set up holder and assign it to the View
+ holder = new ViewHolder();
+ holder.mapView = (MapView) row.findViewById(R.id.lite_listrow_map);
+ holder.title = (TextView) row.findViewById(R.id.lite_listrow_text);
+ // Set holder as tag for row for more efficient access.
+ row.setTag(holder);
+
+ // Initialise the MapView
+ holder.initializeMapView();
+
+ // Keep track of MapView
+ mMaps.add(holder.mapView);
+ } else {
+ // View has already been initialised, get its holder
+ holder = (ViewHolder) row.getTag();
+ }
+
+ // Get the NamedLocation for this item and attach it to the MapView
+ NamedLocation item = getItem(position);
+ holder.mapView.setTag(item);
+
+ // Ensure the map has been initialised by the on map ready callback in ViewHolder.
+ // If it is not ready yet, it will be initialised with the NamedLocation set as its tag
+ // when the callback is received.
+ if (holder.map != null) {
+ // The map is already ready to be used
+ setMapLocation(holder.map, item);
+ }
+
+ // Set the text label for this item
+ holder.title.setText(item.name);
+
+ return row;
+ }
+
+ /**
+ * Retuns the set of all initialised {@link MapView} objects.
+ *
+ * @return All MapViews that have been initialised programmatically by this adapter
+ */
+ public HashSet getMaps() {
+ return mMaps;
+ }
+ }
+
+ /**
+ * Displays a {@link LiteListDemoActivity.NamedLocation} on a
+ * {@link com.google.android.gms.maps.GoogleMap}.
+ * Adds a marker and centers the camera on the NamedLocation with the normal map type.
+ *
+ * @param map
+ * @param data
+ */
+ private static void setMapLocation(GoogleMap map, NamedLocation data) {
+ // Add a marker for this item and set the camera
+ map.moveCamera(CameraUpdateFactory.newLatLngZoom(data.location, 13f));
+ map.addMarker(new MarkerOptions().position(data.location));
+
+ // Set the map type back to normal.
+ map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
+ }
+
+ /**
+ * Holder for Views used in the {@link LiteListDemoActivity.MapAdapter}.
+ * Once the the map field is set, otherwise it is null.
+ * When the {@link #onMapReady(com.google.android.gms.maps.GoogleMap)} callback is received and
+ * the {@link com.google.android.gms.maps.GoogleMap} is ready, it stored in the {@link #map}
+ * field. The map is then initialised with the NamedLocation that is stored as the tag of the
+ * MapView. This ensures that the map is initialised with the latest data that it should
+ * display.
+ */
+ class ViewHolder implements OnMapReadyCallback {
+ MapView mapView;
+ TextView title;
+ GoogleMap map;
+
+ @Override
+ public void onMapReady(GoogleMap googleMap) {
+ MapsInitializer.initialize(getApplicationContext());
+ map = googleMap;
+ NamedLocation data = (NamedLocation) mapView.getTag();
+ if (data != null) {
+ setMapLocation(map, data);
+ }
+ }
+
+ /**
+ * Initialises the MapView by calling its lifecycle methods.
+ */
+ public void initializeMapView() {
+ if (mapView != null) {
+ // Initialise the MapView
+ mapView.onCreate(null);
+ // Set the map ready callback to receive the GoogleMap object
+ mapView.getMapAsync(this);
+ }
+ }
+
+ }
+
+ /**
+ * RecycleListener that completely clears the {@link com.google.android.gms.maps.GoogleMap}
+ * attached to a row in the ListView.
+ * Sets the map type to {@link com.google.android.gms.maps.GoogleMap#MAP_TYPE_NONE} and clears
+ * the map.
+ */
+ private AbsListView.RecyclerListener mRecycleListener = new AbsListView.RecyclerListener() {
+
+ @Override
+ public void onMovedToScrapHeap(View view) {
+ ViewHolder holder = (ViewHolder) view.getTag();
+ if (holder != null && holder.map != null) {
+ // Clear the map and free up resources by changing the map type to none
+ holder.map.clear();
+ holder.map.setMapType(GoogleMap.MAP_TYPE_NONE);
+ }
+
+ }
+ };
+
+ /**
+ * Location represented by a position ({@link com.google.android.gms.maps.model.LatLng} and a
+ * name ({@link java.lang.String}).
+ */
+ private static class NamedLocation {
+ public final String name;
+ public final LatLng location;
+
+ NamedLocation(String name, LatLng location) {
+ this.name = name;
+ this.location = location;
+ }
+ }
+
+ /**
+ * A list of locations to show in this ListView.
+ */
+ private static final NamedLocation[] LIST_LOCATIONS = new NamedLocation[] {
+ new NamedLocation("Cape Town", new LatLng(-33.920455, 18.466941)),
+ new NamedLocation("Beijing", new LatLng(39.937795, 116.387224)),
+ new NamedLocation("Bern", new LatLng(46.948020, 7.448206)),
+ new NamedLocation("Breda", new LatLng(51.589256, 4.774396)),
+ new NamedLocation("Brussels", new LatLng(50.854509, 4.376678)),
+ new NamedLocation("Copenhagen", new LatLng(55.679423, 12.577114)),
+ new NamedLocation("Hannover", new LatLng(52.372026, 9.735672)),
+ new NamedLocation("Helsinki", new LatLng(60.169653, 24.939480)),
+ new NamedLocation("Hong Kong", new LatLng(22.325862, 114.165532)),
+ new NamedLocation("Istanbul", new LatLng(41.034435, 28.977556)),
+ new NamedLocation("Johannesburg", new LatLng(-26.202886, 28.039753)),
+ new NamedLocation("Lisbon", new LatLng(38.707163, -9.135517)),
+ new NamedLocation("London", new LatLng(51.500208, -0.126729)),
+ new NamedLocation("Madrid", new LatLng(40.420006, -3.709924)),
+ new NamedLocation("Mexico City", new LatLng(19.427050, -99.127571)),
+ new NamedLocation("Moscow", new LatLng(55.750449, 37.621136)),
+ new NamedLocation("New York", new LatLng(40.750580, -73.993584)),
+ new NamedLocation("Oslo", new LatLng(59.910761, 10.749092)),
+ new NamedLocation("Paris", new LatLng(48.859972, 2.340260)),
+ new NamedLocation("Prague", new LatLng(50.087811, 14.420460)),
+ new NamedLocation("Rio de Janeiro", new LatLng(-22.90187, -43.232437)),
+ new NamedLocation("Rome", new LatLng(41.889998, 12.500162)),
+ new NamedLocation("Sao Paolo", new LatLng(-22.863878, -43.244097)),
+ new NamedLocation("Seoul", new LatLng(37.560908, 126.987705)),
+ new NamedLocation("Stockholm", new LatLng(59.330650, 18.067360)),
+ new NamedLocation("Sydney", new LatLng(-33.873651, 151.2068896)),
+ new NamedLocation("Taipei", new LatLng(25.022112, 121.478019)),
+ new NamedLocation("Tokyo", new LatLng(35.670267, 139.769955)),
+ new NamedLocation("Tulsa Oklahoma", new LatLng(36.149777, -95.993398)),
+ new NamedLocation("Vaduz", new LatLng(47.141076, 9.521482)),
+ new NamedLocation("Vienna", new LatLng(48.209206, 16.372778)),
+ new NamedLocation("Warsaw", new LatLng(52.235474, 21.004057)),
+ new NamedLocation("Wellington", new LatLng(-41.286480, 174.776217)),
+ new NamedLocation("Winnipeg", new LatLng(49.875832, -97.150726))
+ };
+
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/LocationSourceDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/LocationSourceDemoActivity.java
new file mode 100644
index 00000000000..fcb42760a80
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/LocationSourceDemoActivity.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.GoogleMap.OnMapLongClickListener;
+import com.google.android.gms.maps.LocationSource;
+import com.google.android.gms.maps.OnMapReadyCallback;
+import com.google.android.gms.maps.SupportMapFragment;
+import com.google.android.gms.maps.model.LatLng;
+
+import android.location.Location;
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+
+/**
+ * This shows how to use a custom location source.
+ */
+public class LocationSourceDemoActivity extends FragmentActivity implements OnMapReadyCallback {
+
+ /**
+ * A {@link LocationSource} which reports a new location whenever a user long presses the map at
+ * the point at which a user long pressed the map.
+ */
+ private static class LongPressLocationSource implements LocationSource, OnMapLongClickListener {
+ private OnLocationChangedListener mListener;
+
+ /**
+ * Flag to keep track of the activity's lifecycle. This is not strictly necessary in this
+ * case because onMapLongPress events don't occur while the activity containing the map is
+ * paused but is included to demonstrate best practices (e.g., if a background service were
+ * to be used).
+ */
+ private boolean mPaused;
+
+ @Override
+ public void activate(OnLocationChangedListener listener) {
+ mListener = listener;
+ }
+
+ @Override
+ public void deactivate() {
+ mListener = null;
+ }
+
+ @Override
+ public void onMapLongClick(LatLng point) {
+ if (mListener != null && !mPaused) {
+ Location location = new Location("LongPressLocationProvider");
+ location.setLatitude(point.latitude);
+ location.setLongitude(point.longitude);
+ location.setAccuracy(100);
+ mListener.onLocationChanged(location);
+ }
+ }
+
+ public void onPause() {
+ mPaused = true;
+ }
+
+ public void onResume() {
+ mPaused = false;
+ }
+ }
+
+ private LongPressLocationSource mLocationSource;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.basic_demo);
+
+ mLocationSource = new LongPressLocationSource();
+
+ SupportMapFragment mapFragment =
+ (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
+ mapFragment.getMapAsync(this);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mLocationSource.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mLocationSource.onPause();
+ }
+
+ @Override
+ public void onMapReady(GoogleMap map) {
+ map.setLocationSource(mLocationSource);
+ map.setOnMapLongClickListener(mLocationSource);
+ map.setMyLocationEnabled(true);
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/MainActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/MainActivity.java
new file mode 100644
index 00000000000..5374ccd906d
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/MainActivity.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import android.app.ListActivity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+
+/**
+ * The main activity of the API library demo gallery.
+ *
+ * The main layout lists the demonstrated features, with buttons to launch them.
+ */
+public final class MainActivity extends ListActivity {
+
+ /**
+ * A custom array adapter that shows a {@link FeatureView} containing details about the demo.
+ */
+ private static class CustomArrayAdapter extends ArrayAdapter {
+
+ /**
+ * @param demos An array containing the details of the demos to be displayed.
+ */
+ public CustomArrayAdapter(Context context, DemoDetails[] demos) {
+ super(context, R.layout.feature, R.id.title, demos);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ FeatureView featureView;
+ if (convertView instanceof FeatureView) {
+ featureView = (FeatureView) convertView;
+ } else {
+ featureView = new FeatureView(getContext());
+ }
+
+ DemoDetails demo = getItem(position);
+
+ featureView.setTitleId(demo.titleId);
+ featureView.setDescriptionId(demo.descriptionId);
+
+ Resources resources = getContext().getResources();
+ String title = resources.getString(demo.titleId);
+ String description = resources.getString(demo.descriptionId);
+ featureView.setContentDescription(title + ". " + description);
+
+ return featureView;
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+
+ ListAdapter adapter = new CustomArrayAdapter(this, DemoDetailsList.DEMOS);
+
+ setListAdapter(adapter);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.activity_main, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle item selection
+ if (item.getItemId() == R.id.menu_legal) {
+ startActivity(new Intent(this, LegalInfoActivity.class));
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ protected void onListItemClick(ListView l, View v, int position, long id) {
+ DemoDetails demo = (DemoDetails) getListAdapter().getItem(position);
+ startActivity(new Intent(this, demo.activityClass));
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/MapInPagerDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/MapInPagerDemoActivity.java
new file mode 100644
index 00000000000..01d6a2e2cd5
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/MapInPagerDemoActivity.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.SupportMapFragment;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentPagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * This shows how to add a map to a ViewPager. Note the use of
+ * {@link ViewGroup#requestTransparentRegion(View)} to reduce jankiness.
+ */
+public class MapInPagerDemoActivity extends FragmentActivity {
+ private MyAdapter mAdapter;
+ private ViewPager mPager;
+
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.map_in_pager_demo);
+ mAdapter = new MyAdapter(getSupportFragmentManager());
+
+ mPager = (ViewPager) findViewById(R.id.pager);
+ mPager.setAdapter(mAdapter);
+
+ // This is required to avoid a black flash when the map is loaded. The flash is due
+ // to the use of a SurfaceView as the underlying view of the map.
+ mPager.requestTransparentRegion(mPager);
+ }
+
+ /** A simple fragment that displays a TextView. */
+ public static class TextFragment extends Fragment {
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
+ return inflater.inflate(R.layout.text_fragment, container, false);
+ }
+ }
+
+ /** A simple FragmentPagerAdapter that returns two TextFragment and a SupportMapFragment. */
+ public static class MyAdapter extends FragmentPagerAdapter {
+ public MyAdapter(FragmentManager fm) {
+ super(fm);
+ }
+
+ @Override
+ public int getCount() {
+ return 3;
+ }
+
+ @Override
+ public Fragment getItem(int position) {
+ switch (position) {
+ case 0:
+ case 1:
+ return new TextFragment();
+ case 2:
+ return SupportMapFragment.newInstance();
+ default:
+ return null;
+ }
+ }
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/MarkerDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/MarkerDemoActivity.java
new file mode 100644
index 00000000000..a74afa293ea
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/MarkerDemoActivity.java
@@ -0,0 +1,421 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.CameraUpdateFactory;
+import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.GoogleMap.InfoWindowAdapter;
+import com.google.android.gms.maps.GoogleMap.OnInfoWindowClickListener;
+import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener;
+import com.google.android.gms.maps.GoogleMap.OnMarkerDragListener;
+import com.google.android.gms.maps.OnMapReadyCallback;
+import com.google.android.gms.maps.SupportMapFragment;
+import com.google.android.gms.maps.model.BitmapDescriptorFactory;
+import com.google.android.gms.maps.model.LatLng;
+import com.google.android.gms.maps.model.LatLngBounds;
+import com.google.android.gms.maps.model.Marker;
+import com.google.android.gms.maps.model.MarkerOptions;
+
+import android.annotation.SuppressLint;
+import android.graphics.Color;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.SystemClock;
+import android.support.v4.app.FragmentActivity;
+import android.text.SpannableString;
+import android.text.style.ForegroundColorSpan;
+import android.view.View;
+import android.view.ViewTreeObserver.OnGlobalLayoutListener;
+import android.view.animation.BounceInterpolator;
+import android.view.animation.Interpolator;
+import android.widget.CheckBox;
+import android.widget.ImageView;
+import android.widget.RadioGroup;
+import android.widget.RadioGroup.OnCheckedChangeListener;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * This shows how to place markers on a map.
+ */
+public class MarkerDemoActivity extends FragmentActivity implements
+ OnMarkerClickListener,
+ OnInfoWindowClickListener,
+ OnMarkerDragListener,
+ OnSeekBarChangeListener,
+ OnMapReadyCallback {
+
+ private static final LatLng BRISBANE = new LatLng(-27.47093, 153.0235);
+ private static final LatLng MELBOURNE = new LatLng(-37.81319, 144.96298);
+ private static final LatLng SYDNEY = new LatLng(-33.87365, 151.20689);
+ private static final LatLng ADELAIDE = new LatLng(-34.92873, 138.59995);
+ private static final LatLng PERTH = new LatLng(-31.952854, 115.857342);
+
+ /** Demonstrates customizing the info window and/or its contents. */
+ class CustomInfoWindowAdapter implements InfoWindowAdapter {
+ // These a both viewgroups containing an ImageView with id "badge" and two TextViews with id
+ // "title" and "snippet".
+ private final View mWindow;
+ private final View mContents;
+
+ CustomInfoWindowAdapter() {
+ mWindow = getLayoutInflater().inflate(R.layout.custom_info_window, null);
+ mContents = getLayoutInflater().inflate(R.layout.custom_info_contents, null);
+ }
+
+ @Override
+ public View getInfoWindow(Marker marker) {
+ if (mOptions.getCheckedRadioButtonId() != R.id.custom_info_window) {
+ // This means that getInfoContents will be called.
+ return null;
+ }
+ render(marker, mWindow);
+ return mWindow;
+ }
+
+ @Override
+ public View getInfoContents(Marker marker) {
+ if (mOptions.getCheckedRadioButtonId() != R.id.custom_info_contents) {
+ // This means that the default info contents will be used.
+ return null;
+ }
+ render(marker, mContents);
+ return mContents;
+ }
+
+ private void render(Marker marker, View view) {
+ int badge;
+ // Use the equals() method on a Marker to check for equals. Do not use ==.
+ if (marker.equals(mBrisbane)) {
+ badge = R.drawable.badge_qld;
+ } else if (marker.equals(mAdelaide)) {
+ badge = R.drawable.badge_sa;
+ } else if (marker.equals(mSydney)) {
+ badge = R.drawable.badge_nsw;
+ } else if (marker.equals(mMelbourne)) {
+ badge = R.drawable.badge_victoria;
+ } else if (marker.equals(mPerth)) {
+ badge = R.drawable.badge_wa;
+ } else {
+ // Passing 0 to setImageResource will clear the image view.
+ badge = 0;
+ }
+ ((ImageView) view.findViewById(R.id.badge)).setImageResource(badge);
+
+ String title = marker.getTitle();
+ TextView titleUi = ((TextView) view.findViewById(R.id.title));
+ if (title != null) {
+ // Spannable string allows us to edit the formatting of the text.
+ SpannableString titleText = new SpannableString(title);
+ titleText.setSpan(new ForegroundColorSpan(Color.RED), 0, titleText.length(), 0);
+ titleUi.setText(titleText);
+ } else {
+ titleUi.setText("");
+ }
+
+ String snippet = marker.getSnippet();
+ TextView snippetUi = ((TextView) view.findViewById(R.id.snippet));
+ if (snippet != null && snippet.length() > 12) {
+ SpannableString snippetText = new SpannableString(snippet);
+ snippetText.setSpan(new ForegroundColorSpan(Color.MAGENTA), 0, 10, 0);
+ snippetText.setSpan(new ForegroundColorSpan(Color.BLUE), 12, snippet.length(), 0);
+ snippetUi.setText(snippetText);
+ } else {
+ snippetUi.setText("");
+ }
+ }
+ }
+
+ private GoogleMap mMap;
+
+ private Marker mPerth;
+ private Marker mSydney;
+ private Marker mBrisbane;
+ private Marker mAdelaide;
+ private Marker mMelbourne;
+
+ /**
+ * Keeps track of the last selected marker (though it may no longer be selected). This is
+ * useful for refreshing the info window.
+ */
+ private Marker mLastSelectedMarker;
+
+ private final List mMarkerRainbow = new ArrayList();
+
+ private TextView mTopText;
+ private SeekBar mRotationBar;
+ private CheckBox mFlatBox;
+ private RadioGroup mOptions;
+
+ private final Random mRandom = new Random();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.marker_demo);
+
+ mTopText = (TextView) findViewById(R.id.top_text);
+
+ mRotationBar = (SeekBar) findViewById(R.id.rotationSeekBar);
+ mRotationBar.setMax(360);
+ mRotationBar.setOnSeekBarChangeListener(this);
+
+ mFlatBox = (CheckBox) findViewById(R.id.flat);
+
+ mOptions = (RadioGroup) findViewById(R.id.custom_info_window_options);
+ mOptions.setOnCheckedChangeListener(new OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(RadioGroup group, int checkedId) {
+ if (mLastSelectedMarker != null && mLastSelectedMarker.isInfoWindowShown()) {
+ // Refresh the info window when the info window's content has changed.
+ mLastSelectedMarker.showInfoWindow();
+ }
+ }
+ });
+
+ SupportMapFragment mapFragment =
+ (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
+ mapFragment.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(GoogleMap map) {
+ mMap = map;
+
+ // Hide the zoom controls as the button panel will cover it.
+ mMap.getUiSettings().setZoomControlsEnabled(false);
+
+ // Add lots of markers to the map.
+ addMarkersToMap();
+
+ // Setting an info window adapter allows us to change the both the contents and look of the
+ // info window.
+ mMap.setInfoWindowAdapter(new CustomInfoWindowAdapter());
+
+ // Set listeners for marker events. See the bottom of this class for their behavior.
+ mMap.setOnMarkerClickListener(this);
+ mMap.setOnInfoWindowClickListener(this);
+ mMap.setOnMarkerDragListener(this);
+
+ // Override the default content description on the view, for accessibility mode.
+ // Ideally this string would be localised.
+ map.setContentDescription("Map with lots of markers.");
+
+ // Pan to see all markers in view.
+ // Cannot zoom to bounds until the map has a size.
+ final View mapView = getSupportFragmentManager().findFragmentById(R.id.map).getView();
+ if (mapView.getViewTreeObserver().isAlive()) {
+ mapView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
+ @SuppressWarnings("deprecation") // We use the new method when supported
+ @SuppressLint("NewApi") // We check which build version we are using.
+ @Override
+ public void onGlobalLayout() {
+ LatLngBounds bounds = new LatLngBounds.Builder()
+ .include(PERTH)
+ .include(SYDNEY)
+ .include(ADELAIDE)
+ .include(BRISBANE)
+ .include(MELBOURNE)
+ .build();
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
+ mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
+ } else {
+ mapView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+ }
+ mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50));
+ }
+ });
+ }
+ }
+
+ private void addMarkersToMap() {
+ // Uses a colored icon.
+ mBrisbane = mMap.addMarker(new MarkerOptions()
+ .position(BRISBANE)
+ .title("Brisbane")
+ .snippet("Population: 2,074,200")
+ .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE)));
+
+ // Uses a custom icon with the info window popping out of the center of the icon.
+ mSydney = mMap.addMarker(new MarkerOptions()
+ .position(SYDNEY)
+ .title("Sydney")
+ .snippet("Population: 4,627,300")
+ .icon(BitmapDescriptorFactory.fromResource(R.drawable.arrow))
+ .infoWindowAnchor(0.5f, 0.5f));
+
+ // Creates a draggable marker. Long press to drag.
+ mMelbourne = mMap.addMarker(new MarkerOptions()
+ .position(MELBOURNE)
+ .title("Melbourne")
+ .snippet("Population: 4,137,400")
+ .draggable(true));
+
+ // A few more markers for good measure.
+ mPerth = mMap.addMarker(new MarkerOptions()
+ .position(PERTH)
+ .title("Perth")
+ .snippet("Population: 1,738,800"));
+ mAdelaide = mMap.addMarker(new MarkerOptions()
+ .position(ADELAIDE)
+ .title("Adelaide")
+ .snippet("Population: 1,213,000"));
+
+ // Creates a marker rainbow demonstrating how to create default marker icons of different
+ // hues (colors).
+ float rotation = mRotationBar.getProgress();
+ boolean flat = mFlatBox.isChecked();
+
+ int numMarkersInRainbow = 12;
+ for (int i = 0; i < numMarkersInRainbow; i++) {
+ mMarkerRainbow.add(mMap.addMarker(new MarkerOptions()
+ .position(new LatLng(
+ -30 + 10 * Math.sin(i * Math.PI / (numMarkersInRainbow - 1)),
+ 135 - 10 * Math.cos(i * Math.PI / (numMarkersInRainbow - 1))))
+ .title("Marker " + i)
+ .icon(BitmapDescriptorFactory.defaultMarker(i * 360 / numMarkersInRainbow))
+ .flat(flat)
+ .rotation(rotation)));
+ }
+ }
+
+ private boolean checkReady() {
+ if (mMap == null) {
+ Toast.makeText(this, R.string.map_not_ready, Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ return true;
+ }
+
+ /** Called when the Clear button is clicked. */
+ public void onClearMap(View view) {
+ if (!checkReady()) {
+ return;
+ }
+ mMap.clear();
+ }
+
+ /** Called when the Reset button is clicked. */
+ public void onResetMap(View view) {
+ if (!checkReady()) {
+ return;
+ }
+ // Clear the map because we don't want duplicates of the markers.
+ mMap.clear();
+ addMarkersToMap();
+ }
+
+ /** Called when the Reset button is clicked. */
+ public void onToggleFlat(View view) {
+ if (!checkReady()) {
+ return;
+ }
+ boolean flat = mFlatBox.isChecked();
+ for (Marker marker : mMarkerRainbow) {
+ marker.setFlat(flat);
+ }
+ }
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ if (!checkReady()) {
+ return;
+ }
+ float rotation = seekBar.getProgress();
+ for (Marker marker : mMarkerRainbow) {
+ marker.setRotation(rotation);
+ }
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // Do nothing.
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ // Do nothing.
+ }
+
+ //
+ // Marker related listeners.
+ //
+
+ @Override
+ public boolean onMarkerClick(final Marker marker) {
+ if (marker.equals(mPerth)) {
+ // This causes the marker at Perth to bounce into position when it is clicked.
+ final Handler handler = new Handler();
+ final long start = SystemClock.uptimeMillis();
+ final long duration = 1500;
+
+ final Interpolator interpolator = new BounceInterpolator();
+
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ long elapsed = SystemClock.uptimeMillis() - start;
+ float t = Math.max(
+ 1 - interpolator.getInterpolation((float) elapsed / duration), 0);
+ marker.setAnchor(0.5f, 1.0f + 2 * t);
+
+ if (t > 0.0) {
+ // Post again 16ms later.
+ handler.postDelayed(this, 16);
+ }
+ }
+ });
+ } else if (marker.equals(mAdelaide)) {
+ // This causes the marker at Adelaide to change color and alpha.
+ marker.setIcon(BitmapDescriptorFactory.defaultMarker(mRandom.nextFloat() * 360));
+ marker.setAlpha(mRandom.nextFloat());
+ }
+
+ mLastSelectedMarker = marker;
+ // We return false to indicate that we have not consumed the event and that we wish
+ // for the default behavior to occur (which is for the camera to move such that the
+ // marker is centered and for the marker's info window to open, if it has one).
+ return false;
+ }
+
+ @Override
+ public void onInfoWindowClick(Marker marker) {
+ Toast.makeText(this, "Click Info Window", Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
+ public void onMarkerDragStart(Marker marker) {
+ mTopText.setText("onMarkerDragStart");
+ }
+
+ @Override
+ public void onMarkerDragEnd(Marker marker) {
+ mTopText.setText("onMarkerDragEnd");
+ }
+
+ @Override
+ public void onMarkerDrag(Marker marker) {
+ mTopText.setText("onMarkerDrag. Current Position: " + marker.getPosition());
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/MultiMapDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/MultiMapDemoActivity.java
new file mode 100644
index 00000000000..1d7b07deb95
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/MultiMapDemoActivity.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+
+/**
+ * This shows how to create a simple activity with multiple maps on screen.
+ */
+public class MultiMapDemoActivity extends FragmentActivity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.multimap_demo);
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/MyLocationDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/MyLocationDemoActivity.java
new file mode 100644
index 00000000000..f83feb6428c
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/MyLocationDemoActivity.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import com.google.android.gms.common.ConnectionResult;
+import com.google.android.gms.common.api.GoogleApiClient;
+import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
+import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
+import com.google.android.gms.location.LocationListener;
+import com.google.android.gms.location.LocationRequest;
+import com.google.android.gms.location.LocationServices;
+import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.GoogleMap.OnMyLocationButtonClickListener;
+import com.google.android.gms.maps.OnMapReadyCallback;
+import com.google.android.gms.maps.SupportMapFragment;
+
+import android.location.Location;
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.view.View;
+import android.widget.TextView;
+import android.widget.Toast;
+
+/**
+ * This demo shows how GMS Location can be used to check for changes to the users location. The
+ * "My Location" button uses GMS Location to set the blue dot representing the users location. To
+ * track changes to the users location on the map, we request updates from the
+ * {@link com.google.android.gms.location.FusedLocationProviderApi}.
+ */
+public class MyLocationDemoActivity extends FragmentActivity
+ implements
+ ConnectionCallbacks,
+ OnConnectionFailedListener,
+ LocationListener,
+ OnMyLocationButtonClickListener,
+ OnMapReadyCallback {
+
+ private GoogleApiClient mGoogleApiClient;
+ private TextView mMessageView;
+
+ // These settings are the same as the settings for the map. They will in fact give you updates
+ // at the maximal rates currently possible.
+ private static final LocationRequest REQUEST = LocationRequest.create()
+ .setInterval(5000) // 5 seconds
+ .setFastestInterval(16) // 16ms = 60fps
+ .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.my_location_demo);
+ mMessageView = (TextView) findViewById(R.id.message_text);
+
+ SupportMapFragment mapFragment =
+ (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
+ mapFragment.getMapAsync(this);
+
+ mGoogleApiClient = new GoogleApiClient.Builder(this)
+ .addApi(LocationServices.API)
+ .addConnectionCallbacks(this)
+ .addOnConnectionFailedListener(this)
+ .build();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mGoogleApiClient.connect();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mGoogleApiClient.disconnect();
+ }
+
+ @Override
+ public void onMapReady(GoogleMap map) {
+ map.setMyLocationEnabled(true);
+ map.setOnMyLocationButtonClickListener(this);
+ }
+
+ /**
+ * Button to get current Location. This demonstrates how to get the current Location as required
+ * without needing to register a LocationListener.
+ */
+ public void showMyLocation(View view) {
+ if (mGoogleApiClient.isConnected()) {
+ String msg = "Location = "
+ + LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
+ Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ /**
+ * Implementation of {@link LocationListener}.
+ */
+ @Override
+ public void onLocationChanged(Location location) {
+ mMessageView.setText("Location = " + location);
+ }
+
+ /**
+ * Callback called when connected to GCore. Implementation of {@link ConnectionCallbacks}.
+ */
+ @Override
+ public void onConnected(Bundle connectionHint) {
+ LocationServices.FusedLocationApi.requestLocationUpdates(
+ mGoogleApiClient,
+ REQUEST,
+ this); // LocationListener
+ }
+
+ /**
+ * Callback called when disconnected from GCore. Implementation of {@link ConnectionCallbacks}.
+ */
+ @Override
+ public void onConnectionSuspended(int cause) {
+ // Do nothing
+ }
+
+ /**
+ * Implementation of {@link OnConnectionFailedListener}.
+ */
+ @Override
+ public void onConnectionFailed(ConnectionResult result) {
+ // Do nothing
+ }
+
+ @Override
+ public boolean onMyLocationButtonClick() {
+ Toast.makeText(this, "MyLocation button clicked", Toast.LENGTH_SHORT).show();
+ // Return false so that we don't consume the event and the default behavior still occurs
+ // (the camera animates to the user's current position).
+ return false;
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/OptionsDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/OptionsDemoActivity.java
new file mode 100644
index 00000000000..1a3ef2bdc57
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/OptionsDemoActivity.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+
+/**
+ * An activity that creates a map with some initial options.
+ */
+public final class OptionsDemoActivity extends FragmentActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.options_demo);
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/PolygonDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/PolygonDemoActivity.java
new file mode 100644
index 00000000000..3c9ac107bd9
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/PolygonDemoActivity.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.CameraUpdateFactory;
+import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.OnMapReadyCallback;
+import com.google.android.gms.maps.SupportMapFragment;
+import com.google.android.gms.maps.model.LatLng;
+import com.google.android.gms.maps.model.Polygon;
+import com.google.android.gms.maps.model.PolygonOptions;
+
+import android.graphics.Color;
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * This shows how to draw polygons on a map.
+ */
+public class PolygonDemoActivity extends FragmentActivity
+ implements OnSeekBarChangeListener, OnMapReadyCallback {
+
+ private static final LatLng SYDNEY = new LatLng(-33.87365, 151.20689);
+
+ private static final int WIDTH_MAX = 50;
+ private static final int HUE_MAX = 360;
+ private static final int ALPHA_MAX = 255;
+
+ private Polygon mMutablePolygon;
+
+ private SeekBar mColorBar;
+ private SeekBar mAlphaBar;
+ private SeekBar mWidthBar;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.polygon_demo);
+
+ mColorBar = (SeekBar) findViewById(R.id.hueSeekBar);
+ mColorBar.setMax(HUE_MAX);
+ mColorBar.setProgress(0);
+
+ mAlphaBar = (SeekBar) findViewById(R.id.alphaSeekBar);
+ mAlphaBar.setMax(ALPHA_MAX);
+ mAlphaBar.setProgress(127);
+
+ mWidthBar = (SeekBar) findViewById(R.id.widthSeekBar);
+ mWidthBar.setMax(WIDTH_MAX);
+ mWidthBar.setProgress(10);
+
+ SupportMapFragment mapFragment =
+ (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
+ mapFragment.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(GoogleMap map) {
+ // Override the default content description on the view, for accessibility mode.
+ // Ideally this string would be localised.
+ map.setContentDescription("Google Map with polygons.");
+
+ // Create a rectangle with two rectangular holes.
+ map.addPolygon(new PolygonOptions()
+ .addAll(createRectangle(new LatLng(-20, 130), 5, 5))
+ .addHole(createRectangle(new LatLng(-22, 128), 1, 1))
+ .addHole(createRectangle(new LatLng(-18, 133), 0.5, 1.5))
+ .fillColor(Color.CYAN)
+ .strokeColor(Color.BLUE)
+ .strokeWidth(5));
+
+ // Create a rectangle centered at Sydney.
+ PolygonOptions options = new PolygonOptions().addAll(createRectangle(SYDNEY, 5, 8));
+
+ int fillColor = Color.HSVToColor(
+ mAlphaBar.getProgress(), new float[] {mColorBar.getProgress(), 1, 1});
+ mMutablePolygon = map.addPolygon(options
+ .strokeWidth(mWidthBar.getProgress())
+ .strokeColor(Color.BLACK)
+ .fillColor(fillColor));
+
+ mColorBar.setOnSeekBarChangeListener(this);
+ mAlphaBar.setOnSeekBarChangeListener(this);
+ mWidthBar.setOnSeekBarChangeListener(this);
+
+ // Move the map so that it is centered on the mutable polygon.
+ map.moveCamera(CameraUpdateFactory.newLatLng(SYDNEY));
+ }
+
+ /**
+ * Creates a List of LatLngs that form a rectangle with the given dimensions.
+ */
+ private List createRectangle(LatLng center, double halfWidth, double halfHeight) {
+ return Arrays.asList(new LatLng(center.latitude - halfHeight, center.longitude - halfWidth),
+ new LatLng(center.latitude - halfHeight, center.longitude + halfWidth),
+ new LatLng(center.latitude + halfHeight, center.longitude + halfWidth),
+ new LatLng(center.latitude + halfHeight, center.longitude - halfWidth),
+ new LatLng(center.latitude - halfHeight, center.longitude - halfWidth));
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ // Don't do anything here.
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // Don't do anything here.
+ }
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ if (mMutablePolygon == null) {
+ return;
+ }
+
+ if (seekBar == mColorBar) {
+ mMutablePolygon.setFillColor(Color.HSVToColor(
+ Color.alpha(mMutablePolygon.getFillColor()), new float[] {progress, 1, 1}));
+ } else if (seekBar == mAlphaBar) {
+ int prevColor = mMutablePolygon.getFillColor();
+ mMutablePolygon.setFillColor(Color.argb(
+ progress, Color.red(prevColor), Color.green(prevColor),
+ Color.blue(prevColor)));
+ } else if (seekBar == mWidthBar) {
+ mMutablePolygon.setStrokeWidth(progress);
+ }
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/PolylineDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/PolylineDemoActivity.java
new file mode 100644
index 00000000000..c34a3c7bfb0
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/PolylineDemoActivity.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.CameraUpdateFactory;
+import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.OnMapReadyCallback;
+import com.google.android.gms.maps.SupportMapFragment;
+import com.google.android.gms.maps.model.LatLng;
+import com.google.android.gms.maps.model.Polyline;
+import com.google.android.gms.maps.model.PolylineOptions;
+
+import android.graphics.Color;
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+
+/**
+ * This shows how to draw polylines on a map.
+ */
+public class PolylineDemoActivity extends FragmentActivity
+ implements OnSeekBarChangeListener, OnMapReadyCallback {
+
+ private static final LatLng MELBOURNE = new LatLng(-37.81319, 144.96298);
+ private static final LatLng SYDNEY = new LatLng(-33.87365, 151.20689);
+ private static final LatLng ADELAIDE = new LatLng(-34.92873, 138.59995);
+ private static final LatLng PERTH = new LatLng(-31.95285, 115.85734);
+
+ private static final LatLng LHR = new LatLng(51.471547, -0.460052);
+ private static final LatLng LAX = new LatLng(33.936524, -118.377686);
+ private static final LatLng JFK = new LatLng(40.641051, -73.777485);
+ private static final LatLng AKL = new LatLng(-37.006254, 174.783018);
+
+ private static final int WIDTH_MAX = 50;
+ private static final int HUE_MAX = 360;
+ private static final int ALPHA_MAX = 255;
+
+ private Polyline mMutablePolyline;
+ private SeekBar mColorBar;
+ private SeekBar mAlphaBar;
+ private SeekBar mWidthBar;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.polyline_demo);
+
+ mColorBar = (SeekBar) findViewById(R.id.hueSeekBar);
+ mColorBar.setMax(HUE_MAX);
+ mColorBar.setProgress(0);
+
+ mAlphaBar = (SeekBar) findViewById(R.id.alphaSeekBar);
+ mAlphaBar.setMax(ALPHA_MAX);
+ mAlphaBar.setProgress(255);
+
+ mWidthBar = (SeekBar) findViewById(R.id.widthSeekBar);
+ mWidthBar.setMax(WIDTH_MAX);
+ mWidthBar.setProgress(10);
+
+ SupportMapFragment mapFragment =
+ (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
+ mapFragment.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(GoogleMap map) {
+ // Override the default content description on the view, for accessibility mode.
+ // Ideally this string would be localised.
+ map.setContentDescription("Google Map with polylines.");
+
+ // A simple polyline with the default options from Melbourne-Adelaide-Perth.
+ map.addPolyline((new PolylineOptions())
+ .add(MELBOURNE, ADELAIDE, PERTH));
+
+ // A geodesic polyline that goes around the world.
+ map.addPolyline((new PolylineOptions())
+ .add(LHR, AKL, LAX, JFK, LHR)
+ .width(5)
+ .color(Color.BLUE)
+ .geodesic(true));
+
+ // Rectangle centered at Sydney. This polyline will be mutable.
+ int radius = 5;
+ PolylineOptions options = new PolylineOptions()
+ .add(new LatLng(SYDNEY.latitude + radius, SYDNEY.longitude + radius))
+ .add(new LatLng(SYDNEY.latitude + radius, SYDNEY.longitude - radius))
+ .add(new LatLng(SYDNEY.latitude - radius, SYDNEY.longitude - radius))
+ .add(new LatLng(SYDNEY.latitude - radius, SYDNEY.longitude + radius))
+ .add(new LatLng(SYDNEY.latitude + radius, SYDNEY.longitude + radius));
+ int color = Color.HSVToColor(
+ mAlphaBar.getProgress(), new float[] {mColorBar.getProgress(), 1, 1});
+ mMutablePolyline = map.addPolyline(options
+ .color(color)
+ .width(mWidthBar.getProgress()));
+
+ mColorBar.setOnSeekBarChangeListener(this);
+ mAlphaBar.setOnSeekBarChangeListener(this);
+ mWidthBar.setOnSeekBarChangeListener(this);
+
+ // Move the map so that it is centered on the mutable polyline.
+ map.moveCamera(CameraUpdateFactory.newLatLng(SYDNEY));
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ // Don't do anything here.
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // Don't do anything here.
+ }
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ if (mMutablePolyline == null) {
+ return;
+ }
+
+ if (seekBar == mColorBar) {
+ mMutablePolyline.setColor(Color.HSVToColor(
+ Color.alpha(mMutablePolyline.getColor()), new float[] {progress, 1, 1}));
+ } else if (seekBar == mAlphaBar) {
+ float[] prevHSV = new float[3];
+ Color.colorToHSV(mMutablePolyline.getColor(), prevHSV);
+ mMutablePolyline.setColor(Color.HSVToColor(progress, prevHSV));
+ } else if (seekBar == mWidthBar) {
+ mMutablePolyline.setWidth(progress);
+ }
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/ProgrammaticDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/ProgrammaticDemoActivity.java
new file mode 100644
index 00000000000..6d1ba25b128
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/ProgrammaticDemoActivity.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.OnMapReadyCallback;
+import com.google.android.gms.maps.SupportMapFragment;
+import com.google.android.gms.maps.model.LatLng;
+import com.google.android.gms.maps.model.MarkerOptions;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentTransaction;
+
+/**
+ * Demonstrates how to instantiate a SupportMapFragment programmatically and add a marker to it.
+ */
+public class ProgrammaticDemoActivity extends FragmentActivity implements OnMapReadyCallback {
+
+ private static final String MAP_FRAGMENT_TAG = "map";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // It isn't possible to set a fragment's id programmatically so we set a tag instead and
+ // search for it using that.
+ SupportMapFragment mapFragment = (SupportMapFragment)
+ getSupportFragmentManager().findFragmentByTag(MAP_FRAGMENT_TAG);
+
+ // We only create a fragment if it doesn't already exist.
+ if (mapFragment == null) {
+ // To programmatically add the map, we first create a SupportMapFragment.
+ mapFragment = SupportMapFragment.newInstance();
+
+ // Then we add it using a FragmentTransaction.
+ FragmentTransaction fragmentTransaction =
+ getSupportFragmentManager().beginTransaction();
+ fragmentTransaction.add(android.R.id.content, mapFragment, MAP_FRAGMENT_TAG);
+ fragmentTransaction.commit();
+ }
+ mapFragment.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(GoogleMap map) {
+ map.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/RawMapViewDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/RawMapViewDemoActivity.java
new file mode 100644
index 00000000000..826b9790b53
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/RawMapViewDemoActivity.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.MapView;
+import com.google.android.gms.maps.OnMapReadyCallback;
+import com.google.android.gms.maps.model.LatLng;
+import com.google.android.gms.maps.model.MarkerOptions;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+
+/**
+ * This shows how to create a simple activity with a raw MapView and add a marker to it. This
+ * requires forwarding all the important lifecycle methods onto MapView.
+ */
+public class RawMapViewDemoActivity extends FragmentActivity implements OnMapReadyCallback {
+
+ private MapView mMapView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.raw_mapview_demo);
+
+ mMapView = (MapView) findViewById(R.id.map);
+ mMapView.onCreate(savedInstanceState);
+
+ mMapView.getMapAsync(this);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mMapView.onResume();
+ }
+
+ @Override
+ public void onMapReady(GoogleMap map) {
+ map.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
+ }
+
+ @Override
+ protected void onPause() {
+ mMapView.onPause();
+ super.onPause();
+ }
+
+ @Override
+ protected void onDestroy() {
+ mMapView.onDestroy();
+ super.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mMapView.onLowMemory();
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mMapView.onSaveInstanceState(outState);
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/RetainMapDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/RetainMapDemoActivity.java
new file mode 100644
index 00000000000..9271510f970
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/RetainMapDemoActivity.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.OnMapReadyCallback;
+import com.google.android.gms.maps.SupportMapFragment;
+import com.google.android.gms.maps.model.LatLng;
+import com.google.android.gms.maps.model.MarkerOptions;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+
+/**
+ * This shows how to retain a map across activity restarts (e.g., from screen rotations), which can
+ * be faster than relying on state serialization.
+ */
+public class RetainMapDemoActivity extends FragmentActivity implements OnMapReadyCallback {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.basic_demo);
+
+ SupportMapFragment mapFragment =
+ (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
+
+ if (savedInstanceState == null) {
+ // First incarnation of this activity.
+ mapFragment.setRetainInstance(true);
+ }
+
+ mapFragment.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(GoogleMap map) {
+ map.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/SaveStateDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/SaveStateDemoActivity.java
new file mode 100644
index 00000000000..a02e1fcafad
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/SaveStateDemoActivity.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.CameraUpdateFactory;
+import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener;
+import com.google.android.gms.maps.GoogleMap.OnMarkerDragListener;
+import com.google.android.gms.maps.OnMapReadyCallback;
+import com.google.android.gms.maps.SupportMapFragment;
+import com.google.android.gms.maps.model.BitmapDescriptorFactory;
+import com.google.android.gms.maps.model.LatLng;
+import com.google.android.gms.maps.model.Marker;
+import com.google.android.gms.maps.model.MarkerOptions;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.support.v4.app.FragmentActivity;
+
+import java.util.Random;
+
+/**
+ * This activity shows how to save the state of a MapFragment when the activity is recreated, like
+ * after rotation of the device.
+ */
+public class SaveStateDemoActivity extends FragmentActivity {
+
+ /** Default marker position when the activity is first created. */
+ private static final LatLng DEFAULT_MARKER_POSITION = new LatLng(48.858179, 2.294576);
+
+ /** List of hues to use for the marker */
+ private static final float[] MARKER_HUES = new float[]{
+ BitmapDescriptorFactory.HUE_RED,
+ BitmapDescriptorFactory.HUE_ORANGE,
+ BitmapDescriptorFactory.HUE_YELLOW,
+ BitmapDescriptorFactory.HUE_GREEN,
+ BitmapDescriptorFactory.HUE_CYAN,
+ BitmapDescriptorFactory.HUE_AZURE,
+ BitmapDescriptorFactory.HUE_BLUE,
+ BitmapDescriptorFactory.HUE_VIOLET,
+ BitmapDescriptorFactory.HUE_MAGENTA,
+ BitmapDescriptorFactory.HUE_ROSE,
+ };
+
+ // Bundle keys.
+ private static final String OTHER_OPTIONS = "options";
+ private static final String MARKER_POSITION = "markerPosition";
+ private static final String MARKER_INFO = "markerInfo";
+
+ /**
+ * Extra info about a marker.
+ */
+ static class MarkerInfo implements Parcelable {
+
+ public static final Parcelable.Creator CREATOR =
+ new Parcelable.Creator() {
+ @Override
+ public MarkerInfo createFromParcel(Parcel in) {
+ return new MarkerInfo(in);
+ }
+
+ @Override
+ public MarkerInfo[] newArray(int size) {
+ return new MarkerInfo[size];
+ }
+ };
+
+ float mHue;
+
+ public MarkerInfo(float color) {
+ mHue = color;
+ }
+
+ private MarkerInfo(Parcel in) {
+ mHue = in.readFloat();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeFloat(mHue);
+ }
+ }
+
+ /**
+ * Example of a custom {@code MapFragment} showing how the position of a marker and other custom
+ * {@link Parcelable}s objects can be saved after rotation of the device.
+ *
+ * Storing custom {@link Parcelable} objects directly in the {@link Bundle} provided by the
+ * {@link #onActivityCreated(Bundle)} method will throw a {@code ClassNotFoundException}. This
+ * is due to the fact that this Bundle is parceled (thus losing its ClassLoader attribute at
+ * this moment) and unparceled later in a different ClassLoader.
+ *
+ * A workaround to store these objects is to wrap the custom {@link Parcelable} objects in a new
+ * {@link Bundle} object.
+ *
+ * However, note that it is safe to store {@link Parcelable} objects from the Maps API (eg.
+ * MarkerOptions, LatLng, etc.) directly in the Bundle provided by the
+ * {@link #onActivityCreated(Bundle)} method.
+ */
+ public static class SaveStateMapFragment extends SupportMapFragment
+ implements OnMarkerClickListener, OnMarkerDragListener, OnMapReadyCallback {
+
+ private LatLng mMarkerPosition;
+ private MarkerInfo mMarkerInfo;
+ private boolean mMoveCameraToMarker;
+
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (savedInstanceState == null) {
+ // Activity created for the first time.
+ mMarkerPosition = DEFAULT_MARKER_POSITION;
+ mMarkerInfo = new MarkerInfo(BitmapDescriptorFactory.HUE_RED);
+ mMoveCameraToMarker = true;
+ } else {
+ // Extract the state of the MapFragment:
+ // - Objects from the API (eg. LatLng, MarkerOptions, etc.) were stored directly in
+ // the savedInsanceState Bundle.
+ // - Custom Parcelable objects were wrapped in another Bundle.
+
+ mMarkerPosition = savedInstanceState.getParcelable(MARKER_POSITION);
+
+ Bundle bundle = savedInstanceState.getBundle(OTHER_OPTIONS);
+ mMarkerInfo = bundle.getParcelable(MARKER_INFO);
+
+ mMoveCameraToMarker = false;
+ }
+
+ getMapAsync(this);
+ }
+
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+
+ // All Parcelable objects of the API (eg. LatLng, MarkerOptions, etc.) can be set
+ // directly in the given Bundle.
+ outState.putParcelable(MARKER_POSITION, mMarkerPosition);
+
+ // All other custom Parcelable objects must be wrapped in another Bundle. Indeed,
+ // failing to do so would throw a ClassNotFoundException. This is due to the fact that
+ // this Bundle is being parceled (losing its ClassLoader at this time) and unparceled
+ // later in a different ClassLoader.
+ Bundle bundle = new Bundle();
+ bundle.putParcelable(MARKER_INFO, mMarkerInfo);
+ outState.putBundle(OTHER_OPTIONS, bundle);
+ }
+
+ @Override
+ public boolean onMarkerClick(Marker marker) {
+ float newHue = MARKER_HUES[new Random().nextInt(MARKER_HUES.length)];
+ mMarkerInfo.mHue = newHue;
+ marker.setIcon(BitmapDescriptorFactory.defaultMarker(newHue));
+ return true;
+ }
+
+ @Override
+ public void onMapReady(GoogleMap map) {
+ MarkerOptions markerOptions = new MarkerOptions()
+ .position(mMarkerPosition)
+ .icon(BitmapDescriptorFactory.defaultMarker(mMarkerInfo.mHue))
+ .draggable(true);
+ map.addMarker(markerOptions);
+ map.setOnMarkerDragListener(this);
+ map.setOnMarkerClickListener(this);
+
+ if (mMoveCameraToMarker) {
+ map.animateCamera(CameraUpdateFactory.newLatLng(mMarkerPosition));
+ }
+ }
+
+ @Override
+ public void onMarkerDragStart(Marker marker) {}
+
+ @Override
+ public void onMarkerDrag(Marker marker) {}
+
+ @Override
+ public void onMarkerDragEnd(Marker marker) {
+ mMarkerPosition = marker.getPosition();
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.save_state_demo);
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/SnapshotDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/SnapshotDemoActivity.java
new file mode 100644
index 00000000000..aed421daffa
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/SnapshotDemoActivity.java
@@ -0,0 +1,87 @@
+// Copyright 2013 Google Inc. All Rights Reserved.
+
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.GoogleMap.OnMapLoadedCallback;
+import com.google.android.gms.maps.GoogleMap.SnapshotReadyCallback;
+import com.google.android.gms.maps.OnMapReadyCallback;
+import com.google.android.gms.maps.SupportMapFragment;
+
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.ImageView;
+
+/**
+ * This shows how to take a snapshot of the map.
+ */
+public class SnapshotDemoActivity extends FragmentActivity implements OnMapReadyCallback {
+
+ /**
+ * Note that this may be null if the Google Play services APK is not available.
+ */
+ private GoogleMap mMap;
+
+ private CheckBox mWaitForMapLoadCheckBox;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.snapshot_demo);
+ mWaitForMapLoadCheckBox = (CheckBox) findViewById(R.id.wait_for_map_load);
+
+ SupportMapFragment mapFragment =
+ (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
+ mapFragment.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(GoogleMap map) {
+ mMap = map;
+ }
+
+ /**
+ * Called when the snapshot button is clicked.
+ */
+ public void onScreenshot(View view) {
+ takeSnapshot();
+ }
+
+ private void takeSnapshot() {
+ if (mMap == null) {
+ return;
+ }
+
+ final ImageView snapshotHolder = (ImageView) findViewById(R.id.snapshot_holder);
+
+ final SnapshotReadyCallback callback = new SnapshotReadyCallback() {
+ @Override
+ public void onSnapshotReady(Bitmap snapshot) {
+ // Callback is called from the main thread, so we can modify the ImageView safely.
+ snapshotHolder.setImageBitmap(snapshot);
+ }
+ };
+
+ if (mWaitForMapLoadCheckBox.isChecked()) {
+ mMap.setOnMapLoadedCallback(new OnMapLoadedCallback() {
+ @Override
+ public void onMapLoaded() {
+ mMap.snapshot(callback);
+ }
+ });
+ } else {
+ mMap.snapshot(callback);
+ }
+ }
+
+ /**
+ * Called when the clear button is clicked.
+ */
+ public void onClearScreenshot(View view) {
+ ImageView snapshotHolder = (ImageView) findViewById(R.id.snapshot_holder);
+ snapshotHolder.setImageDrawable(null);
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/SplitStreetViewPanoramaAndMapDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/SplitStreetViewPanoramaAndMapDemoActivity.java
new file mode 100644
index 00000000000..b7e6a9d1b87
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/SplitStreetViewPanoramaAndMapDemoActivity.java
@@ -0,0 +1,100 @@
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.GoogleMap.OnMarkerDragListener;
+import com.google.android.gms.maps.OnMapReadyCallback;
+import com.google.android.gms.maps.OnStreetViewPanoramaReadyCallback;
+import com.google.android.gms.maps.StreetViewPanorama;
+import com.google.android.gms.maps.StreetViewPanorama.OnStreetViewPanoramaChangeListener;
+import com.google.android.gms.maps.SupportMapFragment;
+import com.google.android.gms.maps.SupportStreetViewPanoramaFragment;
+import com.google.android.gms.maps.model.BitmapDescriptorFactory;
+import com.google.android.gms.maps.model.LatLng;
+import com.google.android.gms.maps.model.Marker;
+import com.google.android.gms.maps.model.MarkerOptions;
+import com.google.android.gms.maps.model.StreetViewPanoramaLocation;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+
+/**
+ * This shows how to create a simple activity with streetview and a map
+ */
+public class SplitStreetViewPanoramaAndMapDemoActivity extends FragmentActivity
+ implements OnMarkerDragListener, OnStreetViewPanoramaChangeListener {
+
+ private static final String MARKER_POSITION_KEY = "MarkerPosition";
+
+ // George St, Sydney
+ private static final LatLng SYDNEY = new LatLng(-33.87365, 151.20689);
+
+ private StreetViewPanorama mStreetViewPanorama;
+ private Marker mMarker;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.split_street_view_panorama_and_map_demo);
+
+ final LatLng markerPosition;
+ if (savedInstanceState == null) {
+ markerPosition = SYDNEY;
+ } else {
+ markerPosition = savedInstanceState.getParcelable(MARKER_POSITION_KEY);
+ }
+
+ SupportStreetViewPanoramaFragment streetViewPanoramaFragment =
+ (SupportStreetViewPanoramaFragment)
+ getSupportFragmentManager().findFragmentById(R.id.streetviewpanorama);
+ streetViewPanoramaFragment.getStreetViewPanoramaAsync(
+ new OnStreetViewPanoramaReadyCallback() {
+ @Override
+ public void onStreetViewPanoramaReady(StreetViewPanorama panorama) {
+ mStreetViewPanorama = panorama;
+ mStreetViewPanorama.setPosition(markerPosition);
+ mStreetViewPanorama.setOnStreetViewPanoramaChangeListener(
+ SplitStreetViewPanoramaAndMapDemoActivity.this);
+ }
+ });
+
+ SupportMapFragment mapFragment =
+ (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
+ mapFragment.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(GoogleMap map) {
+ map.setOnMarkerDragListener(SplitStreetViewPanoramaAndMapDemoActivity.this);
+ // Creates a draggable marker. Long press to drag.
+ mMarker = map.addMarker(new MarkerOptions()
+ .position(markerPosition)
+ .icon(BitmapDescriptorFactory.fromResource(R.drawable.pegman))
+ .draggable(true));
+ }
+ });
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putParcelable(MARKER_POSITION_KEY, mMarker.getPosition());
+ }
+
+ @Override
+ public void onStreetViewPanoramaChange(StreetViewPanoramaLocation location) {
+ if (location != null) {
+ mMarker.setPosition(location.position);
+ }
+ }
+
+ @Override
+ public void onMarkerDragStart(Marker marker) {
+ }
+
+ @Override
+ public void onMarkerDragEnd(Marker marker) {
+ mStreetViewPanorama.setPosition(marker.getPosition(), 150);
+ }
+
+ @Override
+ public void onMarkerDrag(Marker marker) {
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/StreetViewPanoramaBasicDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/StreetViewPanoramaBasicDemoActivity.java
new file mode 100644
index 00000000000..909cdc7bc1b
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/StreetViewPanoramaBasicDemoActivity.java
@@ -0,0 +1,39 @@
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.OnStreetViewPanoramaReadyCallback;
+import com.google.android.gms.maps.StreetViewPanorama;
+import com.google.android.gms.maps.SupportStreetViewPanoramaFragment;
+import com.google.android.gms.maps.model.LatLng;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+
+/**
+ * This shows how to create a simple activity with streetview
+ */
+public class StreetViewPanoramaBasicDemoActivity extends FragmentActivity {
+
+ // George St, Sydney
+ private static final LatLng SYDNEY = new LatLng(-33.87365, 151.20689);
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.street_view_panorama_basic_demo);
+
+ SupportStreetViewPanoramaFragment streetViewPanoramaFragment =
+ (SupportStreetViewPanoramaFragment)
+ getSupportFragmentManager().findFragmentById(R.id.streetviewpanorama);
+ streetViewPanoramaFragment.getStreetViewPanoramaAsync(
+ new OnStreetViewPanoramaReadyCallback() {
+ @Override
+ public void onStreetViewPanoramaReady(StreetViewPanorama panorama) {
+ // Only set the panorama to SYDNEY on startup (when no panoramas have been
+ // loaded which is when the savedInstanceState is null).
+ if (savedInstanceState == null) {
+ panorama.setPosition(SYDNEY);
+ }
+ }
+ });
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/StreetViewPanoramaEventsDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/StreetViewPanoramaEventsDemoActivity.java
new file mode 100644
index 00000000000..fe1b31c1934
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/StreetViewPanoramaEventsDemoActivity.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.OnStreetViewPanoramaReadyCallback;
+import com.google.android.gms.maps.StreetViewPanorama;
+import com.google.android.gms.maps.StreetViewPanorama.OnStreetViewPanoramaCameraChangeListener;
+import com.google.android.gms.maps.StreetViewPanorama.OnStreetViewPanoramaChangeListener;
+import com.google.android.gms.maps.StreetViewPanorama.OnStreetViewPanoramaClickListener;
+import com.google.android.gms.maps.StreetViewPanorama.OnStreetViewPanoramaLongClickListener;
+import com.google.android.gms.maps.SupportStreetViewPanoramaFragment;
+import com.google.android.gms.maps.model.LatLng;
+import com.google.android.gms.maps.model.StreetViewPanoramaCamera;
+import com.google.android.gms.maps.model.StreetViewPanoramaLocation;
+import com.google.android.gms.maps.model.StreetViewPanoramaOrientation;
+
+import android.graphics.Point;
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.widget.TextView;
+
+/**
+ * This shows how to listen to some {@link StreetViewPanorama} events.
+ */
+public class StreetViewPanoramaEventsDemoActivity extends FragmentActivity
+ implements OnStreetViewPanoramaChangeListener, OnStreetViewPanoramaCameraChangeListener,
+ OnStreetViewPanoramaClickListener, OnStreetViewPanoramaLongClickListener {
+
+ // George St, Sydney
+ private static final LatLng SYDNEY = new LatLng(-33.87365, 151.20689);
+
+ private StreetViewPanorama mStreetViewPanorama;
+
+ private TextView mPanoChangeTimesTextView;
+ private TextView mPanoCameraChangeTextView;
+ private TextView mPanoClickTextView;
+ private TextView mPanoLongClickTextView;
+
+ private int mPanoChangeTimes = 0;
+ private int mPanoCameraChangeTimes = 0;
+ private int mPanoClickTimes = 0;
+ private int mPanoLongClickTimes = 0;
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.street_view_panorama_events_demo);
+
+ mPanoChangeTimesTextView = (TextView) findViewById(R.id.change_pano);
+ mPanoCameraChangeTextView = (TextView) findViewById(R.id.change_camera);
+ mPanoClickTextView = (TextView) findViewById(R.id.click_pano);
+ mPanoLongClickTextView = (TextView) findViewById(R.id.long_click_pano);
+
+ SupportStreetViewPanoramaFragment streetViewPanoramaFragment =
+ (SupportStreetViewPanoramaFragment)
+ getSupportFragmentManager().findFragmentById(R.id.streetviewpanorama);
+ streetViewPanoramaFragment.getStreetViewPanoramaAsync(
+ new OnStreetViewPanoramaReadyCallback() {
+ @Override
+ public void onStreetViewPanoramaReady(StreetViewPanorama panorama) {
+ mStreetViewPanorama = panorama;
+ mStreetViewPanorama.setOnStreetViewPanoramaChangeListener(
+ StreetViewPanoramaEventsDemoActivity.this);
+ mStreetViewPanorama.setOnStreetViewPanoramaCameraChangeListener(
+ StreetViewPanoramaEventsDemoActivity.this);
+ mStreetViewPanorama.setOnStreetViewPanoramaClickListener(
+ StreetViewPanoramaEventsDemoActivity.this);
+ mStreetViewPanorama.setOnStreetViewPanoramaLongClickListener(
+ StreetViewPanoramaEventsDemoActivity.this);
+
+ // Only set the panorama to SYDNEY on startup (when no panoramas have been
+ // loaded which is when the savedInstanceState is null).
+ if (savedInstanceState == null) {
+ mStreetViewPanorama.setPosition(SYDNEY);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onStreetViewPanoramaChange(StreetViewPanoramaLocation location) {
+ if (location != null) {
+ mPanoChangeTimesTextView.setText("Times panorama changed=" + ++mPanoChangeTimes);
+ }
+ }
+
+ @Override
+ public void onStreetViewPanoramaCameraChange(StreetViewPanoramaCamera camera) {
+ mPanoCameraChangeTextView.setText("Times camera changed=" + ++mPanoCameraChangeTimes);
+ }
+
+ @Override
+ public void onStreetViewPanoramaClick(StreetViewPanoramaOrientation orientation) {
+ Point point = mStreetViewPanorama.orientationToPoint(orientation);
+ if (point != null) {
+ mPanoClickTimes++;
+ mPanoClickTextView.setText(
+ "Times clicked=" + mPanoClickTimes + " : " + point.toString());
+ mStreetViewPanorama.animateTo(
+ new StreetViewPanoramaCamera.Builder()
+ .orientation(orientation)
+ .zoom(mStreetViewPanorama.getPanoramaCamera().zoom)
+ .build(), 1000);
+ }
+ }
+
+ @Override
+ public void onStreetViewPanoramaLongClick(StreetViewPanoramaOrientation orientation) {
+ Point point = mStreetViewPanorama.orientationToPoint(orientation);
+ if (point != null) {
+ mPanoLongClickTimes++;
+ mPanoLongClickTextView.setText(
+ "Times long clicked=" + mPanoLongClickTimes + " : " + point.toString());
+ }
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/StreetViewPanoramaNavigationDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/StreetViewPanoramaNavigationDemoActivity.java
new file mode 100644
index 00000000000..eaaca1e7f9c
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/StreetViewPanoramaNavigationDemoActivity.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.OnStreetViewPanoramaReadyCallback;
+import com.google.android.gms.maps.StreetViewPanorama;
+import com.google.android.gms.maps.SupportStreetViewPanoramaFragment;
+import com.google.android.gms.maps.model.LatLng;
+import com.google.android.gms.maps.model.StreetViewPanoramaCamera;
+import com.google.android.gms.maps.model.StreetViewPanoramaLink;
+import com.google.android.gms.maps.model.StreetViewPanoramaLocation;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.util.FloatMath;
+import android.view.View;
+import android.widget.SeekBar;
+import android.widget.Toast;
+
+/**
+ * This shows how to create an activity with access to all the options in Panorama
+ * which can be adjusted dynamically
+ */
+
+public class StreetViewPanoramaNavigationDemoActivity extends FragmentActivity {
+
+ // George St, Sydney
+ private static final LatLng SYDNEY = new LatLng(-33.87365, 151.20689);
+
+ // Cole St, San Fran
+ private static final LatLng SAN_FRAN = new LatLng(37.769263, -122.450727);
+
+ // Santorini, Greece
+ private static final String SANTORINI = "WddsUw1geEoAAAQIt9RnsQ";
+
+ // LatLng with no panorama
+ private static final LatLng INVALID = new LatLng(-45.125783, 151.276417);
+
+ /**
+ * The amount in degrees by which to scroll the camera
+ */
+ private static final int PAN_BY_DEG = 30;
+
+ private static final float ZOOM_BY = 0.5f;
+
+ private StreetViewPanorama mStreetViewPanorama;
+
+ private SeekBar mCustomDurationBar;
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.street_view_panorama_navigation_demo);
+
+ SupportStreetViewPanoramaFragment streetViewPanoramaFragment =
+ (SupportStreetViewPanoramaFragment)
+ getSupportFragmentManager().findFragmentById(R.id.streetviewpanorama);
+ streetViewPanoramaFragment.getStreetViewPanoramaAsync(
+ new OnStreetViewPanoramaReadyCallback() {
+ @Override
+ public void onStreetViewPanoramaReady(StreetViewPanorama panorama) {
+ mStreetViewPanorama = panorama;
+ // Only set the panorama to SYDNEY on startup (when no panoramas have been
+ // loaded which is when the savedInstanceState is null).
+ if (savedInstanceState == null) {
+ mStreetViewPanorama.setPosition(SYDNEY);
+ }
+ }
+ });
+ mCustomDurationBar = (SeekBar) findViewById(R.id.duration_bar);
+ }
+
+ /**
+ * When the panorama is not ready the PanoramaView cannot be used. This should be called on
+ * all entry points that call methods on the Panorama API.
+ */
+ private boolean checkReady() {
+ if (mStreetViewPanorama == null) {
+ Toast.makeText(this, R.string.panorama_not_ready, Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Called when the Go To San Fran button is clicked.
+ */
+ public void onGoToSanFran(View view) {
+ if (!checkReady()) {
+ return;
+ }
+ mStreetViewPanorama.setPosition(SAN_FRAN, 30);
+ }
+
+ /**
+ * Called when the Animate To Sydney button is clicked.
+ */
+ public void onGoToSydney(View view) {
+ if (!checkReady()) {
+ return;
+ }
+ mStreetViewPanorama.setPosition(SYDNEY);
+ }
+
+ /**
+ * Called when the Animate To Santorini button is clicked.
+ */
+ public void onGoToSantorini(View view) {
+ if (!checkReady()) {
+ return;
+ }
+ mStreetViewPanorama.setPosition(SANTORINI);
+ }
+
+ /**
+ * Called when the Animate To Invalid button is clicked.
+ */
+ public void onGoToInvalid(View view) {
+ if (!checkReady()) {
+ return;
+ }
+ mStreetViewPanorama.setPosition(INVALID);
+ }
+
+ public void onZoomIn(View view) {
+ if (!checkReady()) {
+ return;
+ }
+
+ mStreetViewPanorama.animateTo(
+ new StreetViewPanoramaCamera.Builder().zoom(
+ mStreetViewPanorama.getPanoramaCamera().zoom + ZOOM_BY)
+ .tilt(mStreetViewPanorama.getPanoramaCamera().tilt)
+ .bearing(mStreetViewPanorama.getPanoramaCamera().bearing)
+ .build(), getDuration());
+ }
+
+ public void onZoomOut(View view) {
+ if (!checkReady()) {
+ return;
+ }
+
+ mStreetViewPanorama.animateTo(
+ new StreetViewPanoramaCamera.Builder().zoom(
+ mStreetViewPanorama.getPanoramaCamera().zoom - ZOOM_BY)
+ .tilt(mStreetViewPanorama.getPanoramaCamera().tilt)
+ .bearing(mStreetViewPanorama.getPanoramaCamera().bearing)
+ .build(), getDuration());
+ }
+
+ public void onPanLeft(View view) {
+ if (!checkReady()) {
+ return;
+ }
+
+ mStreetViewPanorama.animateTo(
+ new StreetViewPanoramaCamera.Builder().zoom(
+ mStreetViewPanorama.getPanoramaCamera().zoom)
+ .tilt(mStreetViewPanorama.getPanoramaCamera().tilt)
+ .bearing(mStreetViewPanorama.getPanoramaCamera().bearing - PAN_BY_DEG)
+ .build(), getDuration());
+ }
+
+ public void onPanRight(View view) {
+ if (!checkReady()) {
+ return;
+ }
+
+ mStreetViewPanorama.animateTo(
+ new StreetViewPanoramaCamera.Builder().zoom(
+ mStreetViewPanorama.getPanoramaCamera().zoom)
+ .tilt(mStreetViewPanorama.getPanoramaCamera().tilt)
+ .bearing(mStreetViewPanorama.getPanoramaCamera().bearing + PAN_BY_DEG)
+ .build(), getDuration());
+
+ }
+
+ public void onPanUp(View view) {
+ if (!checkReady()) {
+ return;
+ }
+
+ float currentTilt = mStreetViewPanorama.getPanoramaCamera().tilt;
+ float newTilt = currentTilt + PAN_BY_DEG;
+
+ newTilt = (newTilt > 90) ? 90 : newTilt;
+
+ mStreetViewPanorama.animateTo(
+ new StreetViewPanoramaCamera.Builder()
+ .zoom(mStreetViewPanorama.getPanoramaCamera().zoom)
+ .tilt(newTilt)
+ .bearing(mStreetViewPanorama.getPanoramaCamera().bearing)
+ .build(), getDuration());
+ }
+
+ public void onPanDown(View view) {
+ if (!checkReady()) {
+ return;
+ }
+
+ float currentTilt = mStreetViewPanorama.getPanoramaCamera().tilt;
+ float newTilt = currentTilt - PAN_BY_DEG;
+
+ newTilt = (newTilt < -90) ? -90 : newTilt;
+
+ mStreetViewPanorama.animateTo(
+ new StreetViewPanoramaCamera.Builder()
+ .zoom(mStreetViewPanorama.getPanoramaCamera().zoom)
+ .tilt(newTilt)
+ .bearing(mStreetViewPanorama.getPanoramaCamera().bearing)
+ .build(), getDuration());
+ }
+
+ public void onRequestPosition(View view) {
+ if (!checkReady()){
+ return;
+ }
+ if (mStreetViewPanorama.getLocation() != null) {
+ Toast.makeText(view.getContext(), mStreetViewPanorama.getLocation().position.toString(),
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ public void onMovePosition(View view) {
+ StreetViewPanoramaLocation location = mStreetViewPanorama.getLocation();
+ StreetViewPanoramaCamera camera = mStreetViewPanorama.getPanoramaCamera();
+ if (location != null && location.links != null) {
+ StreetViewPanoramaLink link = findClosestLinkToBearing(location.links, camera.bearing);
+ mStreetViewPanorama.setPosition(link.panoId);
+ }
+ }
+
+ public static StreetViewPanoramaLink findClosestLinkToBearing(StreetViewPanoramaLink[] links,
+ float bearing) {
+ float minBearingDiff = 360;
+ StreetViewPanoramaLink closestLink = links[0];
+ for (StreetViewPanoramaLink link : links) {
+ if (minBearingDiff > findNormalizedDifference(bearing, link.bearing)) {
+ minBearingDiff = findNormalizedDifference(bearing, link.bearing);
+ closestLink = link;
+ }
+ }
+ return closestLink;
+ }
+
+ // Find the difference between angle a and b as a value between 0 and 180
+ public static float findNormalizedDifference(float a, float b) {
+ float diff = a - b;
+ float normalizedDiff = diff - (360.0f * FloatMath.floor(diff / 360.0f));
+ return (normalizedDiff < 180.0f) ? normalizedDiff : 360.0f - normalizedDiff;
+ }
+
+ private long getDuration() {
+ return mCustomDurationBar.getProgress();
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/StreetViewPanoramaOptionsDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/StreetViewPanoramaOptionsDemoActivity.java
new file mode 100644
index 00000000000..b9fd54c3f31
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/StreetViewPanoramaOptionsDemoActivity.java
@@ -0,0 +1,96 @@
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.OnStreetViewPanoramaReadyCallback;
+import com.google.android.gms.maps.StreetViewPanorama;
+import com.google.android.gms.maps.SupportStreetViewPanoramaFragment;
+import com.google.android.gms.maps.model.LatLng;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.Toast;
+
+/**
+ * This shows how to create an activity with static streetview (all options have been switched off)
+ */
+public class StreetViewPanoramaOptionsDemoActivity extends FragmentActivity {
+
+ // Cole St, San Fran
+ private static final LatLng SAN_FRAN = new LatLng(37.765927, -122.449972);
+
+ private StreetViewPanorama mStreetViewPanorama;
+
+ private CheckBox mStreetNameCheckbox;
+ private CheckBox mNavigationCheckbox;
+ private CheckBox mZoomCheckbox;
+ private CheckBox mPanningCheckbox;
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.street_view_panorama_options_demo);
+
+ mStreetNameCheckbox = (CheckBox) findViewById(R.id.streetnames);
+ mNavigationCheckbox = (CheckBox) findViewById(R.id.navigation);
+ mZoomCheckbox = (CheckBox) findViewById(R.id.zoom);
+ mPanningCheckbox = (CheckBox) findViewById(R.id.panning);
+
+ SupportStreetViewPanoramaFragment streetViewPanoramaFragment =
+ (SupportStreetViewPanoramaFragment)
+ getSupportFragmentManager().findFragmentById(R.id.streetviewpanorama);
+ streetViewPanoramaFragment.getStreetViewPanoramaAsync(
+ new OnStreetViewPanoramaReadyCallback() {
+ @Override
+ public void onStreetViewPanoramaReady(StreetViewPanorama panorama) {
+ mStreetViewPanorama = panorama;
+ mStreetViewPanorama.setStreetNamesEnabled(mStreetNameCheckbox.isChecked());
+ mStreetViewPanorama.setUserNavigationEnabled(mNavigationCheckbox.isChecked());
+ mStreetViewPanorama.setZoomGesturesEnabled(mZoomCheckbox.isChecked());
+ mStreetViewPanorama.setPanningGesturesEnabled(mPanningCheckbox.isChecked());
+
+ // Only set the panorama to SAN_FRAN on startup (when no panoramas have been
+ // loaded which is when the savedInstanceState is null).
+ if (savedInstanceState == null) {
+ mStreetViewPanorama.setPosition(SAN_FRAN);
+ }
+ }
+ });
+ }
+
+ private boolean checkReady() {
+ if (mStreetViewPanorama == null) {
+ Toast.makeText(this, R.string.map_not_ready, Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ return true;
+ }
+
+ public void onStreetNamesToggled(View view) {
+ if (!checkReady()) {
+ return;
+ }
+ mStreetViewPanorama.setStreetNamesEnabled(mStreetNameCheckbox.isChecked());
+ }
+
+ public void onNavigationToggled(View view) {
+ if (!checkReady()) {
+ return;
+ }
+ mStreetViewPanorama.setUserNavigationEnabled(mNavigationCheckbox.isChecked());
+ }
+
+ public void onZoomToggled(View view) {
+ if (!checkReady()) {
+ return;
+ }
+ mStreetViewPanorama.setZoomGesturesEnabled(mZoomCheckbox.isChecked());
+ }
+
+ public void onPanningToggled(View view) {
+ if (!checkReady()) {
+ return;
+ }
+ mStreetViewPanorama.setPanningGesturesEnabled(mPanningCheckbox.isChecked());
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/StreetViewPanoramaViewDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/StreetViewPanoramaViewDemoActivity.java
new file mode 100644
index 00000000000..f65a81e8c89
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/StreetViewPanoramaViewDemoActivity.java
@@ -0,0 +1,60 @@
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.StreetViewPanoramaOptions;
+import com.google.android.gms.maps.StreetViewPanoramaView;
+import com.google.android.gms.maps.model.LatLng;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.view.ViewGroup.LayoutParams;
+
+/**
+ * This shows how to create a simple activity with streetview
+ */
+public class StreetViewPanoramaViewDemoActivity extends FragmentActivity {
+
+ // George St, Sydney
+ private static final LatLng SYDNEY = new LatLng(-33.87365, 151.20689);
+
+ private StreetViewPanoramaView mStreetViewPanoramaView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ StreetViewPanoramaOptions options = new StreetViewPanoramaOptions();
+ if (savedInstanceState == null) {
+ options.position(SYDNEY);
+ }
+
+ mStreetViewPanoramaView = new StreetViewPanoramaView(this, options);
+ addContentView(mStreetViewPanoramaView,
+ new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+
+ mStreetViewPanoramaView.onCreate(savedInstanceState);
+ }
+
+ @Override
+ protected void onResume() {
+ mStreetViewPanoramaView.onResume();
+ super.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ mStreetViewPanoramaView.onPause();
+ super.onPause();
+ }
+
+ @Override
+ protected void onDestroy() {
+ mStreetViewPanoramaView.onDestroy();
+ super.onPause();
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mStreetViewPanoramaView.onSaveInstanceState(outState);
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/TileCoordinateDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/TileCoordinateDemoActivity.java
new file mode 100644
index 00000000000..4e9146d296c
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/TileCoordinateDemoActivity.java
@@ -0,0 +1,85 @@
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.OnMapReadyCallback;
+import com.google.android.gms.maps.SupportMapFragment;
+import com.google.android.gms.maps.model.Tile;
+import com.google.android.gms.maps.model.TileOverlayOptions;
+import com.google.android.gms.maps.model.TileProvider;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * This demonstrates tile overlay coordinates.
+ */
+public class TileCoordinateDemoActivity extends FragmentActivity implements OnMapReadyCallback {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.tile_coordinate_demo);
+
+ SupportMapFragment mapFragment =
+ (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
+ mapFragment.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(GoogleMap map) {
+ TileProvider coordTileProvider = new CoordTileProvider(this.getApplicationContext());
+ map.addTileOverlay(new TileOverlayOptions().tileProvider(coordTileProvider));
+ }
+
+ private static class CoordTileProvider implements TileProvider {
+ private static final int TILE_SIZE_DP = 256;
+ private float mScaleFactor;
+ private Paint mBorderPaint;
+ private Bitmap mBorderTile;
+
+ public CoordTileProvider(Context context) {
+ /* Scale factor based on density, with a 0.6 multiplier to increase tile generation
+ * speed */
+ mScaleFactor = context.getResources().getDisplayMetrics().density * 0.6f;
+ mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mBorderPaint.setStyle(Paint.Style.STROKE);
+ mBorderTile = Bitmap.createBitmap((int) (TILE_SIZE_DP * mScaleFactor),
+ (int) (TILE_SIZE_DP * mScaleFactor), android.graphics.Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(mBorderTile);
+ canvas.drawRect(0, 0, TILE_SIZE_DP * mScaleFactor, TILE_SIZE_DP * mScaleFactor,
+ mBorderPaint);
+ }
+
+ @Override
+ public Tile getTile(int x, int y, int zoom) {
+ Bitmap coordTile = drawTileCoords(x, y, zoom);
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ coordTile.compress(Bitmap.CompressFormat.PNG, 0, stream);
+ byte[] bitmapData = stream.toByteArray();
+ return new Tile((int) (TILE_SIZE_DP * mScaleFactor),
+ (int) (TILE_SIZE_DP * mScaleFactor), bitmapData);
+ }
+
+ private Bitmap drawTileCoords(int x, int y, int zoom) {
+ Bitmap copy = mBorderTile.copy(android.graphics.Bitmap.Config.ARGB_8888, true);
+ Canvas canvas = new Canvas(copy);
+ String tileCoords = "(" + x + ", " + y + ")";
+ String zoomLevel = "zoom = " + zoom;
+ /* Paint is not thread safe. */
+ Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mTextPaint.setTextAlign(Paint.Align.CENTER);
+ mTextPaint.setTextSize(18 * mScaleFactor);
+ canvas.drawText(tileCoords, TILE_SIZE_DP * mScaleFactor / 2,
+ TILE_SIZE_DP * mScaleFactor / 2, mTextPaint);
+ canvas.drawText(zoomLevel, TILE_SIZE_DP * mScaleFactor / 2,
+ TILE_SIZE_DP * mScaleFactor * 2 / 3, mTextPaint);
+ return copy;
+ }
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/TileOverlayDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/TileOverlayDemoActivity.java
new file mode 100644
index 00000000000..095d0c05a14
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/TileOverlayDemoActivity.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.OnMapReadyCallback;
+import com.google.android.gms.maps.SupportMapFragment;
+import com.google.android.gms.maps.model.TileOverlay;
+import com.google.android.gms.maps.model.TileOverlayOptions;
+import com.google.android.gms.maps.model.TileProvider;
+import com.google.android.gms.maps.model.UrlTileProvider;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.view.View;
+import android.widget.CheckBox;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Locale;
+
+/**
+ * This demonstrates how to add a tile overlay to a map.
+ */
+public class TileOverlayDemoActivity extends FragmentActivity implements OnMapReadyCallback {
+
+ /** This returns moon tiles. */
+ private static final String MOON_MAP_URL_FORMAT =
+ "http://mw1.google.com/mw-planetary/lunar/lunarmaps_v1/clem_bw/%d/%d/%d.jpg";
+
+ private TileOverlay mMoonTiles;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.tile_overlay_demo);
+
+ SupportMapFragment mapFragment =
+ (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
+ mapFragment.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(GoogleMap map) {
+ map.setMapType(GoogleMap.MAP_TYPE_NONE);
+
+ TileProvider tileProvider = new UrlTileProvider(256, 256) {
+ @Override
+ public synchronized URL getTileUrl(int x, int y, int zoom) {
+ // The moon tile coordinate system is reversed. This is not normal.
+ int reversedY = (1 << zoom) - y - 1;
+ String s = String.format(Locale.US, MOON_MAP_URL_FORMAT, zoom, x, reversedY);
+ URL url = null;
+ try {
+ url = new URL(s);
+ } catch (MalformedURLException e) {
+ throw new AssertionError(e);
+ }
+ return url;
+ }
+ };
+
+ mMoonTiles = map.addTileOverlay(new TileOverlayOptions().tileProvider(tileProvider));
+ }
+
+ public void setFadeIn(View v) {
+ if (mMoonTiles == null) {
+ return;
+ }
+ mMoonTiles.setFadeIn(((CheckBox) v).isChecked());
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/UiSettingsDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/UiSettingsDemoActivity.java
new file mode 100644
index 00000000000..50c5b61baa0
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/UiSettingsDemoActivity.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.OnMapReadyCallback;
+import com.google.android.gms.maps.SupportMapFragment;
+import com.google.android.gms.maps.UiSettings;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.Toast;
+
+/**
+ * This shows how UI settings can be toggled.
+ */
+public class UiSettingsDemoActivity extends FragmentActivity implements OnMapReadyCallback {
+ private GoogleMap mMap;
+ private UiSettings mUiSettings;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.ui_settings_demo);
+
+ SupportMapFragment mapFragment =
+ (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
+ mapFragment.getMapAsync(this);
+ }
+
+ /**
+ * Returns whether the checkbox with the given id is checked.
+ */
+ private boolean isChecked(int id) {
+ return ((CheckBox) findViewById(id)).isChecked();
+ }
+
+ @Override
+ public void onMapReady(GoogleMap map) {
+ mMap = map;
+
+ mMap.setMyLocationEnabled(true);
+ mUiSettings = mMap.getUiSettings();
+
+ // Keep the UI Settings state in sync with the checkboxes.
+ mUiSettings.setZoomControlsEnabled(isChecked(R.id.zoom_buttons_toggle));
+ mUiSettings.setCompassEnabled(isChecked(R.id.compass_toggle));
+ mUiSettings.setMyLocationButtonEnabled(isChecked(R.id.mylocationbutton_toggle));
+ mMap.setMyLocationEnabled(isChecked(R.id.mylocationlayer_toggle));
+ mUiSettings.setScrollGesturesEnabled(isChecked(R.id.scroll_toggle));
+ mUiSettings.setZoomGesturesEnabled(isChecked(R.id.zoom_gestures_toggle));
+ mUiSettings.setTiltGesturesEnabled(isChecked(R.id.tilt_toggle));
+ mUiSettings.setRotateGesturesEnabled(isChecked(R.id.rotate_toggle));
+ }
+
+ /**
+ * Checks if the map is ready (which depends on whether the Google Play services APK is
+ * available. This should be called prior to calling any methods on GoogleMap.
+ */
+ private boolean checkReady() {
+ if (mMap == null) {
+ Toast.makeText(this, R.string.map_not_ready, Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ return true;
+ }
+
+ public void setZoomButtonsEnabled(View v) {
+ if (!checkReady()) {
+ return;
+ }
+ // Enables/disables the zoom controls (+/- buttons in the bottom right of the map).
+ mUiSettings.setZoomControlsEnabled(((CheckBox) v).isChecked());
+ }
+
+ public void setCompassEnabled(View v) {
+ if (!checkReady()) {
+ return;
+ }
+ // Enables/disables the compass (icon in the top left that indicates the orientation of the
+ // map).
+ mUiSettings.setCompassEnabled(((CheckBox) v).isChecked());
+ }
+
+ public void setMyLocationButtonEnabled(View v) {
+ if (!checkReady()) {
+ return;
+ }
+ // Enables/disables the my location button (this DOES NOT enable/disable the my location
+ // dot/chevron on the map). The my location button will never appear if the my location
+ // layer is not enabled.
+ mUiSettings.setMyLocationButtonEnabled(((CheckBox) v).isChecked());
+ }
+
+ public void setMyLocationLayerEnabled(View v) {
+ if (!checkReady()) {
+ return;
+ }
+ // Enables/disables the my location layer (i.e., the dot/chevron on the map). If enabled, it
+ // will also cause the my location button to show (if it is enabled); if disabled, the my
+ // location button will never show.
+ mMap.setMyLocationEnabled(((CheckBox) v).isChecked());
+ }
+
+ public void setScrollGesturesEnabled(View v) {
+ if (!checkReady()) {
+ return;
+ }
+ // Enables/disables scroll gestures (i.e. panning the map).
+ mUiSettings.setScrollGesturesEnabled(((CheckBox) v).isChecked());
+ }
+
+ public void setZoomGesturesEnabled(View v) {
+ if (!checkReady()) {
+ return;
+ }
+ // Enables/disables zoom gestures (i.e., double tap, pinch & stretch).
+ mUiSettings.setZoomGesturesEnabled(((CheckBox) v).isChecked());
+ }
+
+ public void setTiltGesturesEnabled(View v) {
+ if (!checkReady()) {
+ return;
+ }
+ // Enables/disables tilt gestures.
+ mUiSettings.setTiltGesturesEnabled(((CheckBox) v).isChecked());
+ }
+
+ public void setRotateGesturesEnabled(View v) {
+ if (!checkReady()) {
+ return;
+ }
+ // Enables/disables rotate gestures.
+ mUiSettings.setRotateGesturesEnabled(((CheckBox) v).isChecked());
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/VisibleRegionDemoActivity.java b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/VisibleRegionDemoActivity.java
new file mode 100644
index 00000000000..b1fd4849d9d
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/java/com/example/mapdemo/VisibleRegionDemoActivity.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.mapdemo;
+
+import com.google.android.gms.maps.CameraUpdateFactory;
+import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.GoogleMap.OnCameraChangeListener;
+import com.google.android.gms.maps.OnMapReadyCallback;
+import com.google.android.gms.maps.SupportMapFragment;
+import com.google.android.gms.maps.model.CameraPosition;
+import com.google.android.gms.maps.model.LatLng;
+import com.google.android.gms.maps.model.LatLngBounds;
+import com.google.android.gms.maps.model.MarkerOptions;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.SystemClock;
+import android.support.v4.app.FragmentActivity;
+import android.view.View;
+import android.view.animation.Interpolator;
+import android.view.animation.OvershootInterpolator;
+import android.widget.TextView;
+import android.widget.Toast;
+
+/**
+ * This shows how to use setPadding to allow overlays that obscure part of the map without
+ * obscuring the map UI or copyright notices.
+ */
+public class VisibleRegionDemoActivity extends FragmentActivity implements OnMapReadyCallback {
+ /**
+ * Note that this may be null if the Google Play services APK is not available.
+ */
+ private GoogleMap mMap;
+
+ private static final LatLng SOH = new LatLng(-33.85704, 151.21522);
+ private static final LatLng SFO = new LatLng(37.614631, -122.385153);
+ private static final LatLngBounds AUS = new LatLngBounds(
+ new LatLng(-44, 113), new LatLng(-10, 154));
+
+ private TextView mMessageView;
+
+ /** Keep track of current values for padding, so we can animate from them. */
+ int currentLeft = 150;
+ int currentTop = 0;
+ int currentRight = 0;
+ int currentBottom = 0;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.visible_region_demo);
+ mMessageView = (TextView) findViewById(R.id.message_text);
+
+ SupportMapFragment mapFragment =
+ (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
+ mapFragment.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(GoogleMap map) {
+ mMap = map;
+
+ // turn MyLocation on and move to a place with indoor (SFO airport)
+ mMap.setMyLocationEnabled(true);
+ mMap.setPadding(currentLeft, currentTop, currentRight, currentBottom);
+ mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(SFO, 18));
+ // Add a marker to the Opera House
+ mMap.addMarker(new MarkerOptions().position(SOH).title("Sydney Opera House"));
+ // Add a camera change listener.
+ mMap.setOnCameraChangeListener(new OnCameraChangeListener() {
+ @Override
+ public void onCameraChange(CameraPosition pos) {
+ mMessageView.setText("CameraChangeListener: " + pos);
+ }
+ });
+ }
+
+ /**
+ * Checks if the map is ready (which depends on whether the Google Play services APK is
+ * available. This should be called prior to calling any methods on GoogleMap.
+ */
+ private boolean checkReady() {
+ if (mMap == null) {
+ Toast.makeText(this, R.string.map_not_ready, Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ return true;
+ }
+
+ public void moveToOperaHouse(View view) {
+ if (!checkReady()) {
+ return;
+ }
+ mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(SOH, 16));
+ }
+
+ public void moveToSFO(View view) {
+ if (!checkReady()) {
+ return;
+ }
+ mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(SFO, 18));
+ }
+
+ public void moveToAUS(View view) {
+ if (!checkReady()) {
+ return;
+ }
+ mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(AUS, 0));
+ }
+
+ public void setNoPadding(View view) {
+ if (!checkReady()) {
+ return;
+ }
+ animatePadding(150, 0, 0, 0);
+ }
+
+ public void setMorePadding(View view) {
+ if (!checkReady()) {
+ return;
+ }
+ View mapView = ((SupportMapFragment)
+ getSupportFragmentManager().findFragmentById(R.id.map)).getView();
+ int left = 150;
+ int top = 0;
+ int right = mapView.getWidth() / 3;
+ int bottom = mapView.getHeight() / 4;
+ animatePadding(left, top, right, bottom);
+ }
+
+ public void animatePadding(
+ final int toLeft, final int toTop, final int toRight, final int toBottom) {
+
+ final Handler handler = new Handler();
+ final long start = SystemClock.uptimeMillis();
+ final long duration = 1000;
+
+ final Interpolator interpolator = new OvershootInterpolator();
+
+ final int startLeft = currentLeft;
+ final int startTop = currentTop;
+ final int startRight = currentRight;
+ final int startBottom = currentBottom;
+
+ currentLeft = toLeft;
+ currentTop = toTop;
+ currentRight = toRight;
+ currentBottom = toBottom;
+
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ long elapsed = SystemClock.uptimeMillis() - start;
+ float t = interpolator.getInterpolation((float) elapsed / duration);
+
+ int left = (int) (startLeft + ((toLeft - startLeft) * t));
+ int top = (int) (startTop + ((toTop - startTop) * t));
+ int right = (int) (startRight + ((toRight - startRight) * t));
+ int bottom = (int) (startBottom + ((toBottom - startBottom) * t));
+
+ mMap.setPadding(left, top, right, bottom);
+
+ if (elapsed < duration) {
+ // Post again 16ms later.
+ handler.postDelayed(this, 16);
+ }
+ }
+ });
+ }
+}
diff --git a/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/arrow.png b/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/arrow.png
new file mode 100644
index 00000000000..61ad19a7920
Binary files /dev/null and b/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/arrow.png differ
diff --git a/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/badge_nsw.png b/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/badge_nsw.png
new file mode 100644
index 00000000000..88572ea512d
Binary files /dev/null and b/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/badge_nsw.png differ
diff --git a/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/badge_qld.png b/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/badge_qld.png
new file mode 100644
index 00000000000..dd5359448e1
Binary files /dev/null and b/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/badge_qld.png differ
diff --git a/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/badge_sa.png b/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/badge_sa.png
new file mode 100644
index 00000000000..b8d7c452efd
Binary files /dev/null and b/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/badge_sa.png differ
diff --git a/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/badge_victoria.png b/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/badge_victoria.png
new file mode 100644
index 00000000000..8fd7bbb2864
Binary files /dev/null and b/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/badge_victoria.png differ
diff --git a/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/badge_wa.png b/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/badge_wa.png
new file mode 100644
index 00000000000..9e6ea6f5f98
Binary files /dev/null and b/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/badge_wa.png differ
diff --git a/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/custom_info_bubble.9.png b/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/custom_info_bubble.9.png
new file mode 100644
index 00000000000..d6440b0c142
Binary files /dev/null and b/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/custom_info_bubble.9.png differ
diff --git a/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/ic_launcher.png b/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 00000000000..23c510f6447
Binary files /dev/null and b/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/ic_launcher.png differ
diff --git a/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/pegman.png b/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/pegman.png
new file mode 100644
index 00000000000..e85f9b651e4
Binary files /dev/null and b/ui/watch/mapdemo/app/src/main/res/drawable-hdpi/pegman.png differ
diff --git a/ui/watch/mapdemo/app/src/main/res/drawable-ldpi/ic_launcher.png b/ui/watch/mapdemo/app/src/main/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 00000000000..1095584ec21
Binary files /dev/null and b/ui/watch/mapdemo/app/src/main/res/drawable-ldpi/ic_launcher.png differ
diff --git a/ui/watch/mapdemo/app/src/main/res/drawable-mdpi/arrow.png b/ui/watch/mapdemo/app/src/main/res/drawable-mdpi/arrow.png
new file mode 100644
index 00000000000..8e7fd22d953
Binary files /dev/null and b/ui/watch/mapdemo/app/src/main/res/drawable-mdpi/arrow.png differ
diff --git a/ui/watch/mapdemo/app/src/main/res/drawable-mdpi/custom_info_bubble.9.png b/ui/watch/mapdemo/app/src/main/res/drawable-mdpi/custom_info_bubble.9.png
new file mode 100644
index 00000000000..b1cfec3a017
Binary files /dev/null and b/ui/watch/mapdemo/app/src/main/res/drawable-mdpi/custom_info_bubble.9.png differ
diff --git a/ui/watch/mapdemo/app/src/main/res/drawable-mdpi/ic_launcher.png b/ui/watch/mapdemo/app/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 00000000000..436b5d1d0a1
Binary files /dev/null and b/ui/watch/mapdemo/app/src/main/res/drawable-mdpi/ic_launcher.png differ
diff --git a/ui/watch/mapdemo/app/src/main/res/drawable-mdpi/pegman.png b/ui/watch/mapdemo/app/src/main/res/drawable-mdpi/pegman.png
new file mode 100644
index 00000000000..6cabcb0c00f
Binary files /dev/null and b/ui/watch/mapdemo/app/src/main/res/drawable-mdpi/pegman.png differ
diff --git a/ui/watch/mapdemo/app/src/main/res/drawable-xhdpi/ic_launcher.png b/ui/watch/mapdemo/app/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 00000000000..42ecbdd5dd2
Binary files /dev/null and b/ui/watch/mapdemo/app/src/main/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/ui/watch/mapdemo/app/src/main/res/drawable-xhdpi/pegman.png b/ui/watch/mapdemo/app/src/main/res/drawable-xhdpi/pegman.png
new file mode 100644
index 00000000000..0b4dd63406c
Binary files /dev/null and b/ui/watch/mapdemo/app/src/main/res/drawable-xhdpi/pegman.png differ
diff --git a/ui/watch/mapdemo/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/ui/watch/mapdemo/app/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000000..85e9459c5a1
Binary files /dev/null and b/ui/watch/mapdemo/app/src/main/res/drawable-xxhdpi/ic_launcher.png differ
diff --git a/ui/watch/mapdemo/app/src/main/res/drawable-xxhdpi/pegman.png b/ui/watch/mapdemo/app/src/main/res/drawable-xxhdpi/pegman.png
new file mode 100644
index 00000000000..7d855320a32
Binary files /dev/null and b/ui/watch/mapdemo/app/src/main/res/drawable-xxhdpi/pegman.png differ
diff --git a/ui/watch/mapdemo/app/src/main/res/drawable-xxxhdpi/ic_launcher.png b/ui/watch/mapdemo/app/src/main/res/drawable-xxxhdpi/ic_launcher.png
new file mode 100644
index 00000000000..c593ada2462
Binary files /dev/null and b/ui/watch/mapdemo/app/src/main/res/drawable-xxxhdpi/ic_launcher.png differ
diff --git a/ui/watch/mapdemo/app/src/main/res/drawable/newark_nj_1922.png b/ui/watch/mapdemo/app/src/main/res/drawable/newark_nj_1922.png
new file mode 100644
index 00000000000..ef13c2ff180
Binary files /dev/null and b/ui/watch/mapdemo/app/src/main/res/drawable/newark_nj_1922.png differ
diff --git a/ui/watch/mapdemo/app/src/main/res/drawable/newark_prudential_sunny.jpg b/ui/watch/mapdemo/app/src/main/res/drawable/newark_prudential_sunny.jpg
new file mode 100644
index 00000000000..294fe5efb86
Binary files /dev/null and b/ui/watch/mapdemo/app/src/main/res/drawable/newark_prudential_sunny.jpg differ
diff --git a/ui/watch/mapdemo/app/src/main/res/layout-land/snapshot_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout-land/snapshot_demo.xml
new file mode 100644
index 00000000000..74cb854327e
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout-land/snapshot_demo.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/basic_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/basic_demo.xml
new file mode 100644
index 00000000000..d8a36054e4b
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/basic_demo.xml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/camera_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/camera_demo.xml
new file mode 100644
index 00000000000..4780bbff270
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/camera_demo.xml
@@ -0,0 +1,157 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/circle_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/circle_demo.xml
new file mode 100644
index 00000000000..6f7b70f4cdc
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/circle_demo.xml
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/custom_info_contents.xml b/ui/watch/mapdemo/app/src/main/res/layout/custom_info_contents.xml
new file mode 100644
index 00000000000..1522add24e7
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/custom_info_contents.xml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/custom_info_window.xml b/ui/watch/mapdemo/app/src/main/res/layout/custom_info_window.xml
new file mode 100644
index 00000000000..f3eb8f11fcf
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/custom_info_window.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/events_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/events_demo.xml
new file mode 100644
index 00000000000..a545c319374
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/events_demo.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/feature.xml b/ui/watch/mapdemo/app/src/main/res/layout/feature.xml
new file mode 100644
index 00000000000..16c04ab7f51
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/feature.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/ground_overlay_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/ground_overlay_demo.xml
new file mode 100644
index 00000000000..75aa6b28808
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/ground_overlay_demo.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/indoor_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/indoor_demo.xml
new file mode 100644
index 00000000000..4eac6557b78
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/indoor_demo.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/layers_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/layers_demo.xml
new file mode 100644
index 00000000000..bb3be72ca6b
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/layers_demo.xml
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/legal_info.xml b/ui/watch/mapdemo/app/src/main/res/layout/legal_info.xml
new file mode 100644
index 00000000000..014569846fa
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/legal_info.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/lite_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/lite_demo.xml
new file mode 100644
index 00000000000..007218bee73
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/lite_demo.xml
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/lite_list_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/lite_list_demo.xml
new file mode 100644
index 00000000000..70c3742c92b
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/lite_list_demo.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/lite_list_demo_row.xml b/ui/watch/mapdemo/app/src/main/res/layout/lite_list_demo_row.xml
new file mode 100644
index 00000000000..5aa0152ea01
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/lite_list_demo_row.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/main.xml b/ui/watch/mapdemo/app/src/main/res/layout/main.xml
new file mode 100644
index 00000000000..d9dd29dfe23
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/main.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/map_in_pager_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/map_in_pager_demo.xml
new file mode 100644
index 00000000000..9ab18ab8761
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/map_in_pager_demo.xml
@@ -0,0 +1,6 @@
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/marker_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/marker_demo.xml
new file mode 100644
index 00000000000..2be0b434d29
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/marker_demo.xml
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/multimap_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/multimap_demo.xml
new file mode 100644
index 00000000000..1973579fee0
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/multimap_demo.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/my_location_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/my_location_demo.xml
new file mode 100644
index 00000000000..c867a436fe3
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/my_location_demo.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/options_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/options_demo.xml
new file mode 100644
index 00000000000..16b79fcc107
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/options_demo.xml
@@ -0,0 +1,35 @@
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/polygon_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/polygon_demo.xml
new file mode 100644
index 00000000000..0925c7102a8
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/polygon_demo.xml
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/polyline_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/polyline_demo.xml
new file mode 100644
index 00000000000..50532e0caeb
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/polyline_demo.xml
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/raw_mapview_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/raw_mapview_demo.xml
new file mode 100644
index 00000000000..7f9d8da3825
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/raw_mapview_demo.xml
@@ -0,0 +1,21 @@
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/save_state_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/save_state_demo.xml
new file mode 100644
index 00000000000..583c643ea01
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/save_state_demo.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/snapshot_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/snapshot_demo.xml
new file mode 100644
index 00000000000..1f0f45fb6c5
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/snapshot_demo.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/split_street_view_panorama_and_map_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/split_street_view_panorama_and_map_demo.xml
new file mode 100644
index 00000000000..20f1d905e43
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/split_street_view_panorama_and_map_demo.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/street_view_panorama_basic_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/street_view_panorama_basic_demo.xml
new file mode 100644
index 00000000000..c5f6429b8cc
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/street_view_panorama_basic_demo.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/street_view_panorama_events_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/street_view_panorama_events_demo.xml
new file mode 100644
index 00000000000..700d68eaec9
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/street_view_panorama_events_demo.xml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/street_view_panorama_navigation_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/street_view_panorama_navigation_demo.xml
new file mode 100644
index 00000000000..43a590e1883
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/street_view_panorama_navigation_demo.xml
@@ -0,0 +1,161 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/street_view_panorama_options_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/street_view_panorama_options_demo.xml
new file mode 100644
index 00000000000..c90a279bb48
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/street_view_panorama_options_demo.xml
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/street_view_panorama_view_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/street_view_panorama_view_demo.xml
new file mode 100644
index 00000000000..03a510bd0e2
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/street_view_panorama_view_demo.xml
@@ -0,0 +1,22 @@
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/text_fragment.xml b/ui/watch/mapdemo/app/src/main/res/layout/text_fragment.xml
new file mode 100644
index 00000000000..96770a7758b
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/text_fragment.xml
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/tile_coordinate_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/tile_coordinate_demo.xml
new file mode 100644
index 00000000000..e8b82184ce7
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/tile_coordinate_demo.xml
@@ -0,0 +1,21 @@
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/tile_overlay_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/tile_overlay_demo.xml
new file mode 100644
index 00000000000..897514be73a
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/tile_overlay_demo.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/ui_settings_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/ui_settings_demo.xml
new file mode 100644
index 00000000000..2ae814986b2
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/ui_settings_demo.xml
@@ -0,0 +1,103 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/layout/visible_region_demo.xml b/ui/watch/mapdemo/app/src/main/res/layout/visible_region_demo.xml
new file mode 100644
index 00000000000..58938a12c8d
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/layout/visible_region_demo.xml
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/app/src/main/res/menu/activity_main.xml b/ui/watch/mapdemo/app/src/main/res/menu/activity_main.xml
new file mode 100644
index 00000000000..0916171b831
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/menu/activity_main.xml
@@ -0,0 +1,22 @@
+
+
+
\ No newline at end of file
diff --git a/ui/watch/mapdemo/app/src/main/res/values/demo_strings.xml b/ui/watch/mapdemo/app/src/main/res/values/demo_strings.xml
new file mode 100644
index 00000000000..e43a5a32012
--- /dev/null
+++ b/ui/watch/mapdemo/app/src/main/res/values/demo_strings.xml
@@ -0,0 +1,229 @@
+
+
+
+ Alpha
+ Animate
+ Basic Map
+ Launches a map
+ Buildings
+ Camera
+ Demonstrates camera functions.
+ Circles
+ Demonstrates how to add Circles to a map.
+ Clear
+ Compass
+ Custom info contents
+ Custom info window
+ Default info window
+ Google Maps API Demos
+ \u2193
+ Drag Melbourne
+ Custom Duration
+ Hue
+ Events
+ Demonstrates event handling.
+ Fade In Tiles
+ Fill Alpha
+ Fill Hue
+ Flat
+ Go to Bondi
+ Go to Santorini
+ Go to Sydney
+ Ground Overlays
+ Demonstrates how to add a GroundOverlay to a map.
+ Hybrid
+
+
+
+ Indoor
+
+ @string/normal
+ @string/hybrid
+
+
+
+ @string/satellite
+ @string/terrain
+ @string/none_map
+
+ Layers
+ Demonstrates the different map layers.
+ \u2190
+ Legal Info
+ Location Source Demo
+ Demonstrates how to use a custom location source.
+ Map is not ready yet
+ Map In Pager
+ Demonstrates how to add a map to a ViewPager.
+ Markers
+ Demonstrates how to add Markers to a map.
+ Move the camera
+ Multiple Maps
+ Demonstrates how to show multiple maps in a single activity.
+ My Location
+ My Location Demo
+ Demonstrates how to use GMS Location
+ My Location Button
+ My Location Layer
+ No demos
+ None
+ Normal
+ Options
+ Demonstrates how to use Options to initialize a map.
+
+
+
+
+ Google Play services is not installed on this device.
+ Polygons
+ Demonstrates how to add Polygons to a map.
+ Polylines
+ Demonstrates how to add Polylines to a map.
+ Programmatically add map
+ Demonstrates how to add a MapFragment programmatically.
+ Properties for Circle(s)
+ Properties for Sydney Polyline
+ Properties for Sydney Polygon
+ Rotate Gestures
+ Raw MapView
+ Demonstrates how to use a raw MapView.
+ Reset
+ Retain map
+ Demonstrates how to reuse a MapFragment.
+ \u2192
+ Rotation:
+ Satellite
+ Save the state of a MapFragment.
+ Demonstrates how to save the state of a MapFragment upon rotation of the device.
+ Drag the marker, tap on it to change its color and rotate the device to check that the state of the map is preserved.
+ Scroll Gestures
+ Clear
+ Snapshot
+ Demonstrates how to take a snapshot of the map.
+ Area for the map snapshot.
+ Take snapshot
+ \u25A0
+ Stroke Width
+ \u2190 Swipe \u2192
+ Switch Image
+ Tap or long press on the map
+ Terrain
+ Tile Coordinate Overlay
+ Demonstrates how to add a tile overlay with tile coordinates to a map.
+ Tile Overlays
+ Demonstrates how to add a tile overlay to a map.
+ Tilt Gestures
+ \u2193
+ \u2191
+ Traffic
+ Transparency
+ UI Settings
+ Demonstrates how to alter user interface settings.
+ \u2191
+ Visible Regions
+ Demonstrates how to use Visible Regions
+ AUS
+ Normal
+ More
+ SOH
+ SFO
+ Wait for Map Load
+ Width
+ Zoom Buttons
+ Zoom Gestures
+ +
+ -
+
+
+ Lite Mode
+ Demonstrates some features on a map in lite mode.
+ Click the map with no, one or multiple markers displayed to open the Google Maps Mobile app.
+ Go to Darwin (No Markers)
+ Go to Adelaide (One Marker)
+ Go to Australia (Five Markers)
+ Lite Mode ListView
+ Demonstrates using maps in lite mode in a ListView
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Activate Higher Level
+ Focused Building
+ Focused Level
+ Demonstrates how to use the Indoor API
+ Indoor
+ Toggle Level Picker
+
+
+ Go to Invalid Point
+ Go to San Fran
+ navigate to another panorama
+ Navigation
+ pan camera
+ Panning Gestures
+ Panorama is not ready yet
+ Position
+ Demonstrates how to show a Street View panorama and map.
+ Street View Panorama and Map
+ Standard Street View Panorama using a Fragment.
+ Street View Panorama
+
+
+
+
+ Standard Street View Panorama with event handling.
+ Street View Panorama events
+ Street View Panorama with programatic navigation
+ Street View Panorama navigation
+ Street View Panorama with toggles for options
+ Street View Panorama options
+ Standard Street View Panorama using a View
+ Street View Panorama View
+ Streetnames
+ tap screen
+ long press screen
+ Walk
+
+ long press
+ Long click to exit the map.
+
+
diff --git a/ui/watch/mapdemo/build.gradle b/ui/watch/mapdemo/build.gradle
new file mode 100644
index 00000000000..9405f3fd18b
--- /dev/null
+++ b/ui/watch/mapdemo/build.gradle
@@ -0,0 +1,19 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:1.2.3'
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ }
+}
diff --git a/ui/watch/mapdemo/gradle.properties b/ui/watch/mapdemo/gradle.properties
new file mode 100644
index 00000000000..1d3591c8a4c
--- /dev/null
+++ b/ui/watch/mapdemo/gradle.properties
@@ -0,0 +1,18 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
\ No newline at end of file
diff --git a/ui/watch/mapdemo/gradle/wrapper/gradle-wrapper.jar b/ui/watch/mapdemo/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000000..8c0fb64a869
Binary files /dev/null and b/ui/watch/mapdemo/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/ui/watch/mapdemo/gradle/wrapper/gradle-wrapper.properties b/ui/watch/mapdemo/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000000..0c71e760dc9
--- /dev/null
+++ b/ui/watch/mapdemo/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Apr 10 15:27:10 PDT 2013
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
diff --git a/ui/watch/mapdemo/gradlew b/ui/watch/mapdemo/gradlew
new file mode 100644
index 00000000000..91a7e269e19
--- /dev/null
+++ b/ui/watch/mapdemo/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/ui/watch/mapdemo/gradlew.bat b/ui/watch/mapdemo/gradlew.bat
new file mode 100644
index 00000000000..8a0b282aa68
--- /dev/null
+++ b/ui/watch/mapdemo/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/ui/watch/mapdemo/mapdemo.iml b/ui/watch/mapdemo/mapdemo.iml
new file mode 100644
index 00000000000..dac5ffbcee8
--- /dev/null
+++ b/ui/watch/mapdemo/mapdemo.iml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ui/watch/mapdemo/mobile/.gitignore b/ui/watch/mapdemo/mobile/.gitignore
new file mode 100644
index 00000000000..796b96d1c40
--- /dev/null
+++ b/ui/watch/mapdemo/mobile/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/ui/watch/mapdemo/mobile/build.gradle b/ui/watch/mapdemo/mobile/build.gradle
new file mode 100644
index 00000000000..ad480382b98
--- /dev/null
+++ b/ui/watch/mapdemo/mobile/build.gradle
@@ -0,0 +1,26 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 22
+ buildToolsVersion "23.0.0 rc3"
+
+ defaultConfig {
+ applicationId "com.example.mapdemo"
+ minSdkVersion 19
+ targetSdkVersion 22
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ compile fileTree(include: ['*.jar'], dir: 'libs')
+ compile 'com.android.support:appcompat-v7:22.2.1'
+ compile 'com.google.android.gms:play-services:7.5.0'
+}
diff --git a/ui/watch/mapdemo/mobile/mobile.iml b/ui/watch/mapdemo/mobile/mobile.iml
new file mode 100644
index 00000000000..11d325eb0f8
--- /dev/null
+++ b/ui/watch/mapdemo/mobile/mobile.iml
@@ -0,0 +1,139 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ui/watch/mapdemo/mobile/proguard-rules.pro b/ui/watch/mapdemo/mobile/proguard-rules.pro
new file mode 100644
index 00000000000..e93e140e0cd
--- /dev/null
+++ b/ui/watch/mapdemo/mobile/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in C:\Users\Show\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/ui/watch/mapdemo/mobile/src/androidTest/java/com/example/mapdemo/ApplicationTest.java b/ui/watch/mapdemo/mobile/src/androidTest/java/com/example/mapdemo/ApplicationTest.java
new file mode 100644
index 00000000000..260655948ef
--- /dev/null
+++ b/ui/watch/mapdemo/mobile/src/androidTest/java/com/example/mapdemo/ApplicationTest.java
@@ -0,0 +1,13 @@
+package com.example.mapdemo;
+
+import android.app.Application;
+import android.test.ApplicationTestCase;
+
+/**
+ * Testing Fundamentals
+ */
+public class ApplicationTest extends ApplicationTestCase {
+ public ApplicationTest() {
+ super(Application.class);
+ }
+}
\ No newline at end of file
diff --git a/ui/watch/mapdemo/mobile/src/main/AndroidManifest.xml b/ui/watch/mapdemo/mobile/src/main/AndroidManifest.xml
new file mode 100644
index 00000000000..abf7a98f329
--- /dev/null
+++ b/ui/watch/mapdemo/mobile/src/main/AndroidManifest.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/mobile/src/main/java/com/example/mapdemo/DataItemSampleActivity.java b/ui/watch/mapdemo/mobile/src/main/java/com/example/mapdemo/DataItemSampleActivity.java
new file mode 100644
index 00000000000..4a1588b78d3
--- /dev/null
+++ b/ui/watch/mapdemo/mobile/src/main/java/com/example/mapdemo/DataItemSampleActivity.java
@@ -0,0 +1,110 @@
+package com.example.mapdemo;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.TextView;
+
+import com.google.android.gms.common.ConnectionResult;
+import com.google.android.gms.common.api.GoogleApiClient;
+import com.google.android.gms.wearable.DataApi;
+import com.google.android.gms.wearable.DataEvent;
+import com.google.android.gms.wearable.DataEventBuffer;
+import com.google.android.gms.wearable.DataMap;
+import com.google.android.gms.wearable.Wearable;
+
+public class DataItemSampleActivity extends Activity
+ implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, DataApi.DataListener {
+
+ private GoogleApiClient mGoogleApiClient;
+
+ private int count = 0;
+ private TextView textView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_data_item_sample);
+
+ textView = (TextView)findViewById(R.id.counter);
+ textView.setText(Integer.toString(count));
+
+ mGoogleApiClient = new GoogleApiClient
+ .Builder(this)
+ .addConnectionCallbacks(this)
+ .addOnConnectionFailedListener(this)
+ .addApi(Wearable.API)
+ .build();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mGoogleApiClient.connect();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
+ Wearable.DataApi.removeListener(mGoogleApiClient, this);
+ mGoogleApiClient.disconnect();
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.data_item_sample, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle action bar item clicks here. The action bar will
+ // automatically handle clicks on the Home/Up button, so long
+ // as you specify a parent activity in AndroidManifest.xml.
+ int id = item.getItemId();
+ if (id == R.id.action_settings) {
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void onConnected(Bundle bundle) {
+ Log.d("TAG", "onConnected");
+ Wearable.DataApi.addListener(mGoogleApiClient, this);
+ }
+
+ @Override
+ public void onConnectionSuspended(int i) {
+ Log.d("TAG", "onConnectionSuspended");
+ }
+
+ @Override
+ public void onConnectionFailed(ConnectionResult connectionResult) {
+ Log.e("TAG", "onConnectionFailed: " + connectionResult);
+ }
+
+ @Override
+ public void onDataChanged(DataEventBuffer dataEvents) {
+ for (DataEvent event : dataEvents) {
+ if (event.getType() == DataEvent.TYPE_DELETED) {
+ Log.d("TAG", "DataItem deleted: " + event.getDataItem().getUri());
+ } else if (event.getType() == DataEvent.TYPE_CHANGED) {
+ Log.d("TAG", "DataItem changed: " + event.getDataItem().getUri());
+ DataMap dataMap = DataMap.fromByteArray(event.getDataItem().getData());
+ count = dataMap.getInt("key");
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ textView.setText(Integer.toString(count));
+ }
+ });
+ }
+ }
+ }
+}
diff --git a/ui/watch/mapdemo/mobile/src/main/java/com/example/mapdemo/MessageSampleActivity.java b/ui/watch/mapdemo/mobile/src/main/java/com/example/mapdemo/MessageSampleActivity.java
new file mode 100644
index 00000000000..00d154e158d
--- /dev/null
+++ b/ui/watch/mapdemo/mobile/src/main/java/com/example/mapdemo/MessageSampleActivity.java
@@ -0,0 +1,101 @@
+package com.example.mapdemo;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.Toast;
+
+import com.google.android.gms.common.ConnectionResult;
+import com.google.android.gms.common.api.GoogleApiClient;
+import com.google.android.gms.wearable.MessageApi;
+import com.google.android.gms.wearable.MessageEvent;
+import com.google.android.gms.wearable.Wearable;
+
+public class MessageSampleActivity extends Activity
+ implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, MessageApi.MessageListener {
+
+ private GoogleApiClient mGoogleApiClient;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_message_sample);
+
+ mGoogleApiClient = new GoogleApiClient
+ .Builder(this)
+ .addConnectionCallbacks(this)
+ .addOnConnectionFailedListener(this)
+ .addApi(Wearable.API)
+ .build();
+ }
+
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.message_sample, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle action bar item clicks here. The action bar will
+ // automatically handle clicks on the Home/Up button, so long
+ // as you specify a parent activity in AndroidManifest.xml.
+ int id = item.getItemId();
+ if (id == R.id.action_settings) {
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mGoogleApiClient.connect();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
+ Wearable.MessageApi.removeListener(mGoogleApiClient, this);
+ mGoogleApiClient.disconnect();
+ }
+ }
+
+ @Override
+ public void onConnected(Bundle bundle) {
+ Log.d("TAG", "onConnected");
+ Wearable.MessageApi.addListener(mGoogleApiClient, this);
+ }
+
+ @Override
+ public void onConnectionSuspended(int i) {
+ Log.d("TAG", "onConnectionSuspended");
+ }
+
+ @Override
+ public void onConnectionFailed(ConnectionResult connectionResult) {
+ Log.e("TAG", "onConnectionFailed: " + connectionResult);
+ }
+
+ @Override
+ public void onMessageReceived(MessageEvent messageEvent) {
+ Log.d("TAG", "onMessageReceived");
+ final Context context = this;
+ if (messageEvent.getPath().equals("/messagesample")) {
+ final String messagePayload = new String(messageEvent.getData());
+ Log.d("TAG", messagePayload);
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(context , messagePayload, Toast.LENGTH_LONG).show();
+ }
+ });
+ }
+ }
+}
diff --git a/ui/watch/mapdemo/mobile/src/main/java/com/example/mapdemo/MyActivity.java b/ui/watch/mapdemo/mobile/src/main/java/com/example/mapdemo/MyActivity.java
new file mode 100644
index 00000000000..85726196c07
--- /dev/null
+++ b/ui/watch/mapdemo/mobile/src/main/java/com/example/mapdemo/MyActivity.java
@@ -0,0 +1,42 @@
+package com.example.mapdemo;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import com.example.mapdemo.fragments.ItemListFragment;
+
+
+public class MyActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_my);
+ if (savedInstanceState == null) {
+ getFragmentManager().beginTransaction()
+ .add(R.id.listContainer, new ItemListFragment()).commit();
+ }
+ }
+
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.my, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle action bar item clicks here. The action bar will
+ // automatically handle clicks on the Home/Up button, so long
+ // as you specify a parent activity in AndroidManifest.xml.
+ int id = item.getItemId();
+ if (id == R.id.action_settings) {
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+}
diff --git a/ui/watch/mapdemo/mobile/src/main/java/com/example/mapdemo/fragments/ItemListFragment.java b/ui/watch/mapdemo/mobile/src/main/java/com/example/mapdemo/fragments/ItemListFragment.java
new file mode 100644
index 00000000000..3c0d0d1a788
--- /dev/null
+++ b/ui/watch/mapdemo/mobile/src/main/java/com/example/mapdemo/fragments/ItemListFragment.java
@@ -0,0 +1,43 @@
+package com.example.mapdemo.fragments;
+
+import android.app.ListFragment;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+import com.example.mapdemo.DataItemSampleActivity;
+import com.example.mapdemo.MessageSampleActivity;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ItemListFragment extends ListFragment {
+
+ ArrayAdapter adapter;
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ List listItems = new ArrayList();
+ listItems.add("DataItem");
+ listItems.add("Message");
+ adapter = new ArrayAdapter(getActivity(), android.R.layout.simple_list_item_1, listItems);
+ setListAdapter(adapter);
+ }
+
+ @Override
+ public void onListItemClick(ListView l, View v, int position, long id) {
+ super.onListItemClick(l, v, position, id);
+ String item = adapter.getItem(position);
+ if ("DataItem".equals(item)) {
+ Intent intent = new Intent(getActivity(), DataItemSampleActivity.class);
+ startActivity(intent);
+ } else if ("Message".equals(item)) {
+ Intent intent = new Intent(getActivity(), MessageSampleActivity.class);
+ startActivity(intent);
+ }
+ }
+}
diff --git a/ui/watch/mapdemo/mobile/src/main/res/drawable-hdpi/ic_launcher.png b/ui/watch/mapdemo/mobile/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 00000000000..96a442e5b8e
Binary files /dev/null and b/ui/watch/mapdemo/mobile/src/main/res/drawable-hdpi/ic_launcher.png differ
diff --git a/ui/watch/mapdemo/mobile/src/main/res/drawable-mdpi/ic_launcher.png b/ui/watch/mapdemo/mobile/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 00000000000..359047dfa4e
Binary files /dev/null and b/ui/watch/mapdemo/mobile/src/main/res/drawable-mdpi/ic_launcher.png differ
diff --git a/ui/watch/mapdemo/mobile/src/main/res/drawable-xhdpi/ic_launcher.png b/ui/watch/mapdemo/mobile/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 00000000000..71c6d760f05
Binary files /dev/null and b/ui/watch/mapdemo/mobile/src/main/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/ui/watch/mapdemo/mobile/src/main/res/drawable-xxhdpi/ic_launcher.png b/ui/watch/mapdemo/mobile/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000000..4df18946442
Binary files /dev/null and b/ui/watch/mapdemo/mobile/src/main/res/drawable-xxhdpi/ic_launcher.png differ
diff --git a/ui/watch/mapdemo/mobile/src/main/res/layout/activity_data_item_sample.xml b/ui/watch/mapdemo/mobile/src/main/res/layout/activity_data_item_sample.xml
new file mode 100644
index 00000000000..c1f2eaf5422
--- /dev/null
+++ b/ui/watch/mapdemo/mobile/src/main/res/layout/activity_data_item_sample.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/mobile/src/main/res/layout/activity_message_sample.xml b/ui/watch/mapdemo/mobile/src/main/res/layout/activity_message_sample.xml
new file mode 100644
index 00000000000..f9ee82556a8
--- /dev/null
+++ b/ui/watch/mapdemo/mobile/src/main/res/layout/activity_message_sample.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
diff --git a/ui/watch/mapdemo/mobile/src/main/res/layout/activity_my.xml b/ui/watch/mapdemo/mobile/src/main/res/layout/activity_my.xml
new file mode 100644
index 00000000000..ee4f029d834
--- /dev/null
+++ b/ui/watch/mapdemo/mobile/src/main/res/layout/activity_my.xml
@@ -0,0 +1,6 @@
+
+
diff --git a/ui/watch/mapdemo/mobile/src/main/res/menu/data_item_sample.xml b/ui/watch/mapdemo/mobile/src/main/res/menu/data_item_sample.xml
new file mode 100644
index 00000000000..a051825d496
--- /dev/null
+++ b/ui/watch/mapdemo/mobile/src/main/res/menu/data_item_sample.xml
@@ -0,0 +1,8 @@
+
diff --git a/ui/watch/mapdemo/mobile/src/main/res/menu/message_sample.xml b/ui/watch/mapdemo/mobile/src/main/res/menu/message_sample.xml
new file mode 100644
index 00000000000..8bfeeaf0e35
--- /dev/null
+++ b/ui/watch/mapdemo/mobile/src/main/res/menu/message_sample.xml
@@ -0,0 +1,8 @@
+
diff --git a/ui/watch/mapdemo/mobile/src/main/res/menu/my.xml b/ui/watch/mapdemo/mobile/src/main/res/menu/my.xml
new file mode 100644
index 00000000000..e3267a421ed
--- /dev/null
+++ b/ui/watch/mapdemo/mobile/src/main/res/menu/my.xml
@@ -0,0 +1,8 @@
+
diff --git a/ui/watch/mapdemo/mobile/src/main/res/values-large/refs.xml b/ui/watch/mapdemo/mobile/src/main/res/values-large/refs.xml
new file mode 100644
index 00000000000..e5f8fdc2aa9
--- /dev/null
+++ b/ui/watch/mapdemo/mobile/src/main/res/values-large/refs.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/ui/watch/mapdemo/mobile/src/main/res/values-sw600dp/refs.xml b/ui/watch/mapdemo/mobile/src/main/res/values-sw600dp/refs.xml
new file mode 100644
index 00000000000..6b30d8d9d47
--- /dev/null
+++ b/ui/watch/mapdemo/mobile/src/main/res/values-sw600dp/refs.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/ui/watch/mapdemo/mobile/src/main/res/values-w820dp/dimens.xml b/ui/watch/mapdemo/mobile/src/main/res/values-w820dp/dimens.xml
new file mode 100644
index 00000000000..63fc8164446
--- /dev/null
+++ b/ui/watch/mapdemo/mobile/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 64dp
+
diff --git a/ui/watch/mapdemo/mobile/src/main/res/values/dimens.xml b/ui/watch/mapdemo/mobile/src/main/res/values/dimens.xml
new file mode 100644
index 00000000000..47c82246738
--- /dev/null
+++ b/ui/watch/mapdemo/mobile/src/main/res/values/dimens.xml
@@ -0,0 +1,5 @@
+
+
+ 16dp
+ 16dp
+
diff --git a/ui/watch/mapdemo/mobile/src/main/res/values/refs.xml b/ui/watch/mapdemo/mobile/src/main/res/values/refs.xml
new file mode 100644
index 00000000000..e5f8fdc2aa9
--- /dev/null
+++ b/ui/watch/mapdemo/mobile/src/main/res/values/refs.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/ui/watch/mapdemo/mobile/src/main/res/values/strings.xml b/ui/watch/mapdemo/mobile/src/main/res/values/strings.xml
new file mode 100644
index 00000000000..a94c9931dbc
--- /dev/null
+++ b/ui/watch/mapdemo/mobile/src/main/res/values/strings.xml
@@ -0,0 +1,10 @@
+
+
+
+ DataLayerSample
+ Hello world!
+ Settings
+ DataItemSampleActivity
+ Message
+
+
diff --git a/ui/watch/mapdemo/mobile/src/main/res/values/styles.xml b/ui/watch/mapdemo/mobile/src/main/res/values/styles.xml
new file mode 100644
index 00000000000..ff6c9d2c0fb
--- /dev/null
+++ b/ui/watch/mapdemo/mobile/src/main/res/values/styles.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/ui/watch/mapdemo/settings.gradle b/ui/watch/mapdemo/settings.gradle
new file mode 100644
index 00000000000..ae81827ad75
--- /dev/null
+++ b/ui/watch/mapdemo/settings.gradle
@@ -0,0 +1 @@
+include ':app', ':mobile'