Moving the rest of wear samples from development/samples/wearable to developers/samples/android
so that those samples are indexed on android.developers.com.
Change-Id: Ie3f9118b3ddd40ed10028f4f80ed1d613f4317eb
diff --git a/wearable/wear/FindMyPhone/Application/.gitignore b/wearable/wear/FindMyPhone/Application/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/FindMyPhone/Application/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/FindMyPhone/Application/proguard-project.txt b/wearable/wear/FindMyPhone/Application/proguard-project.txt
new file mode 100644
index 0000000..0d8f171
--- /dev/null
+++ b/wearable/wear/FindMyPhone/Application/proguard-project.txt
@@ -0,0 +1,20 @@
+ To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# 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/wearable/wear/FindMyPhone/Application/src/main/AndroidManifest.xml b/wearable/wear/FindMyPhone/Application/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..b18583c
--- /dev/null
+++ b/wearable/wear/FindMyPhone/Application/src/main/AndroidManifest.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.findphone">
+
+ <uses-sdk android:minSdkVersion="19"
+ android:targetSdkVersion="19" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@android:style/Theme.Holo.Light"
+ android:allowBackup="true">
+
+ <meta-data
+ android:name="com.google.android.gms.version"
+ android:value="@integer/google_play_services_version" />
+
+ <service
+ android:name="com.example.android.findphone.SoundAlarmListenerService" >
+ <intent-filter>
+ <action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
+ </intent-filter>
+ </service>
+
+ </application>
+</manifest>
diff --git a/wearable/wear/FindMyPhone/Application/src/main/java/com/example/android/findphone/SoundAlarmListenerService.java b/wearable/wear/FindMyPhone/Application/src/main/java/com/example/android/findphone/SoundAlarmListenerService.java
new file mode 100644
index 0000000..106a47a
--- /dev/null
+++ b/wearable/wear/FindMyPhone/Application/src/main/java/com/example/android/findphone/SoundAlarmListenerService.java
@@ -0,0 +1,101 @@
+/*
+ * 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.android.findphone;
+
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.util.Log;
+
+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.WearableListenerService;
+
+import java.io.IOException;
+
+/**
+ * Listens for disconnection from home device.
+ */
+public class SoundAlarmListenerService extends WearableListenerService {
+
+ private static final String TAG = "ExampleFindPhoneApp";
+
+ private static final String FIELD_ALARM_ON = "alarm_on";
+
+ private AudioManager mAudioManager;
+ private static int mOrigVolume;
+ private int mMaxVolume;
+ private Uri mAlarmSound;
+ private MediaPlayer mMediaPlayer;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
+ mOrigVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_ALARM);
+ mMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM);
+ mAlarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
+ mMediaPlayer = new MediaPlayer();
+ }
+
+ @Override
+ public void onDestroy() {
+ // Reset the alarm volume to the user's original setting.
+ mAudioManager.setStreamVolume(AudioManager.STREAM_ALARM, mOrigVolume, 0);
+ mMediaPlayer.release();
+ super.onDestroy();
+ }
+
+ @Override
+ public void onDataChanged(DataEventBuffer dataEvents) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "onDataChanged: " + dataEvents + " for " + getPackageName());
+ }
+ for (DataEvent event : dataEvents) {
+ if (event.getType() == DataEvent.TYPE_DELETED) {
+ Log.i(TAG, event + " deleted");
+ } else if (event.getType() == DataEvent.TYPE_CHANGED) {
+ Boolean alarmOn =
+ DataMap.fromByteArray(event.getDataItem().getData()).get(FIELD_ALARM_ON);
+ if (alarmOn) {
+ mOrigVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_ALARM);
+ mMediaPlayer.reset();
+ // Sound alarm at max volume.
+ mAudioManager.setStreamVolume(AudioManager.STREAM_ALARM, mMaxVolume, 0);
+ mMediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
+ try {
+ mMediaPlayer.setDataSource(getApplicationContext(), mAlarmSound);
+ mMediaPlayer.prepare();
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to prepare media player to play alarm.", e);
+ }
+ mMediaPlayer.start();
+ } else {
+ // Reset the alarm volume to the user's original setting.
+ mAudioManager.setStreamVolume(AudioManager.STREAM_ALARM, mOrigVolume, 0);
+ if (mMediaPlayer.isPlaying()) {
+ mMediaPlayer.stop();
+ }
+ }
+ }
+ }
+ dataEvents.close();
+ }
+
+}
diff --git a/wearable/wear/FindMyPhone/Application/src/main/res/drawable-hdpi/ic_launcher.png b/wearable/wear/FindMyPhone/Application/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..43254bd
--- /dev/null
+++ b/wearable/wear/FindMyPhone/Application/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/FindMyPhone/Application/src/main/res/drawable-mdpi/ic_launcher.png b/wearable/wear/FindMyPhone/Application/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..de255d6
--- /dev/null
+++ b/wearable/wear/FindMyPhone/Application/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/FindMyPhone/Application/src/main/res/drawable-xhdpi/ic_launcher.png b/wearable/wear/FindMyPhone/Application/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..5a849da
--- /dev/null
+++ b/wearable/wear/FindMyPhone/Application/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/FindMyPhone/Application/src/main/res/drawable-xxhdpi/ic_launcher.png b/wearable/wear/FindMyPhone/Application/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..96a7cb8
--- /dev/null
+++ b/wearable/wear/FindMyPhone/Application/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/FindMyPhone/Application/src/main/res/values/strings.xml b/wearable/wear/FindMyPhone/Application/src/main/res/values/strings.xml
new file mode 100644
index 0000000..64163c2
--- /dev/null
+++ b/wearable/wear/FindMyPhone/Application/src/main/res/values/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+</resources>
diff --git a/wearable/wear/FindMyPhone/CONTRIB.md b/wearable/wear/FindMyPhone/CONTRIB.md
new file mode 100644
index 0000000..14a4fcf
--- /dev/null
+++ b/wearable/wear/FindMyPhone/CONTRIB.md
@@ -0,0 +1,35 @@
+# How to become a contributor and submit your own code
+
+## Contributor License Agreements
+
+We'd love to accept your sample apps and patches! Before we can take them, we
+have to jump a couple of legal hurdles.
+
+Please fill out either the individual or corporate Contributor License Agreement (CLA).
+
+ * If you are an individual writing original source code and you're sure you
+ own the intellectual property, then you'll need to sign an [individual CLA]
+ (https://developers.google.com/open-source/cla/individual).
+ * If you work for a company that wants to allow you to contribute your work,
+ then you'll need to sign a [corporate CLA]
+ (https://developers.google.com/open-source/cla/corporate).
+
+Follow either of the two links above to access the appropriate CLA and
+instructions for how to sign and return it. Once we receive it, we'll be able to
+accept your pull requests.
+
+## Contributing A Patch
+
+1. Submit an issue describing your proposed change to the repo in question.
+1. The repo owner will respond to your issue promptly.
+1. If your proposed change is accepted, and you haven't already done so, sign a
+ Contributor License Agreement (see details above).
+1. Fork the desired repo, develop and test your code changes.
+1. Ensure that your code adheres to the existing style in the sample to which
+ you are contributing. Refer to the
+ [Android Code Style Guide]
+ (https://source.android.com/source/code-style.html) for the
+ recommended coding standards for this organization.
+1. Ensure that your code has an appropriate set of unit tests which all pass.
+1. Submit a pull request.
+
diff --git a/wearable/wear/FindMyPhone/LICENSE b/wearable/wear/FindMyPhone/LICENSE
new file mode 100644
index 0000000..1af981f
--- /dev/null
+++ b/wearable/wear/FindMyPhone/LICENSE
@@ -0,0 +1,201 @@
+ 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 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/wearable/wear/FindMyPhone/README-wear.txt b/wearable/wear/FindMyPhone/README-wear.txt
new file mode 100644
index 0000000..17523d7
--- /dev/null
+++ b/wearable/wear/FindMyPhone/README-wear.txt
@@ -0,0 +1,30 @@
+<#--
+ Copyright 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.
+-->
+
+Steps to use Wear template on top of an existing sample:
+- In template-params.xml.ftl:
+ - Add the following template:
+ <template src="Wear"/>
+
+- Refresh your project (./gradlew refresh)
+- Add Wearable-specific code to Wearable directory
+- Add code to be shared among the main application and the wearable to Shared
+ directory
+
+Note that you still need the main application sample code. This is usually
+achieved by adding another template, like "base" for example.
+
+
diff --git a/wearable/wear/FindMyPhone/Shared/.gitignore b/wearable/wear/FindMyPhone/Shared/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/FindMyPhone/Shared/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/FindMyPhone/Shared/src/main/AndroidManifest.xml b/wearable/wear/FindMyPhone/Shared/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..80efe2e
--- /dev/null
+++ b/wearable/wear/FindMyPhone/Shared/src/main/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.findphone.common">
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name">
+ </application>
+
+</manifest>
diff --git a/wearable/wear/FindMyPhone/Shared/src/main/res/values/strings.xml b/wearable/wear/FindMyPhone/Shared/src/main/res/values/strings.xml
new file mode 100644
index 0000000..0f2bb90
--- /dev/null
+++ b/wearable/wear/FindMyPhone/Shared/src/main/res/values/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+ <string name="app_name">Shared</string>
+</resources>
diff --git a/wearable/wear/FindMyPhone/Wearable/.gitignore b/wearable/wear/FindMyPhone/Wearable/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/FindMyPhone/Wearable/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/FindMyPhone/Wearable/src/main/AndroidManifest.xml b/wearable/wear/FindMyPhone/Wearable/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..b81dd33
--- /dev/null
+++ b/wearable/wear/FindMyPhone/Wearable/src/main/AndroidManifest.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.findphone" >
+
+ <uses-sdk android:minSdkVersion="20"
+ android:targetSdkVersion="20" />
+
+ <uses-permission android:name="android.permission.VIBRATE" />
+ <uses-feature android:name="android.hardware.type.watch" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@android:style/Theme.DeviceDefault" >
+
+ <meta-data
+ android:name="com.google.android.gms.version"
+ android:value="@integer/google_play_services_version" />
+
+ <service android:name=".DisconnectListenerService" >
+ <intent-filter>
+ <action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
+ </intent-filter>
+ </service>
+
+ <service android:name="com.example.android.findphone.FindPhoneService"/>
+
+ <activity
+ android:name=".FindPhoneActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/wearable/wear/FindMyPhone/Wearable/src/main/java/com/example/android/findphone/DisconnectListenerService.java b/wearable/wear/FindMyPhone/Wearable/src/main/java/com/example/android/findphone/DisconnectListenerService.java
new file mode 100644
index 0000000..749a38d
--- /dev/null
+++ b/wearable/wear/FindMyPhone/Wearable/src/main/java/com/example/android/findphone/DisconnectListenerService.java
@@ -0,0 +1,55 @@
+/*
+ * 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.android.findphone;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+
+import com.google.android.gms.wearable.WearableListenerService;
+
+/**
+ * Listens for disconnection from home device.
+ */
+public class DisconnectListenerService extends WearableListenerService {
+
+ private static final String TAG = "ExampleFindPhoneApp";
+
+ private static final int FORGOT_PHONE_NOTIFICATION_ID = 1;
+
+ @Override
+ public void onPeerDisconnected(com.google.android.gms.wearable.Node peer) {
+ // Create a "forgot phone" notification when phone connection is broken.
+ Notification.Builder notificationBuilder = new Notification.Builder(this)
+ .setContentTitle(getString(R.string.left_phone_title))
+ .setContentText(getString(R.string.left_phone_content))
+ .setVibrate(new long[] {0, 200}) // Vibrate for 200 milliseconds.
+ .setSmallIcon(R.drawable.ic_launcher)
+ .setLocalOnly(true)
+ .setPriority(Notification.PRIORITY_MAX);
+ Notification card = notificationBuilder.build();
+ ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
+ .notify(FORGOT_PHONE_NOTIFICATION_ID, card);
+ }
+
+ @Override
+ public void onPeerConnected(com.google.android.gms.wearable.Node peer) {
+ // Remove the "forgot phone" notification when connection is restored.
+ ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
+ .cancel(FORGOT_PHONE_NOTIFICATION_ID);
+ }
+
+}
diff --git a/wearable/wear/FindMyPhone/Wearable/src/main/java/com/example/android/findphone/FindPhoneActivity.java b/wearable/wear/FindMyPhone/Wearable/src/main/java/com/example/android/findphone/FindPhoneActivity.java
new file mode 100644
index 0000000..8251bab
--- /dev/null
+++ b/wearable/wear/FindMyPhone/Wearable/src/main/java/com/example/android/findphone/FindPhoneActivity.java
@@ -0,0 +1,87 @@
+/*
+ * 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.android.findphone;
+
+import android.app.Activity;
+import android.app.Notification;
+import android.app.Notification.Action;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.style.RelativeSizeSpan;
+
+
+public class FindPhoneActivity extends Activity {
+
+ private static final int FIND_PHONE_NOTIFICATION_ID = 2;
+ private static Notification.Builder notification;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Create a notification with an action to toggle an alarm on the phone.
+ Intent toggleAlarmOperation = new Intent(this, FindPhoneService.class);
+ toggleAlarmOperation.setAction(FindPhoneService.ACTION_TOGGLE_ALARM);
+ PendingIntent toggleAlarmIntent = PendingIntent.getService(this, 0, toggleAlarmOperation,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+ Action alarmAction = new Action(R.drawable.alarm_action_icon, "", toggleAlarmIntent);
+ // This intent turns off the alarm if the user dismisses the card from the wearable.
+ Intent cancelAlarmOperation = new Intent(this, FindPhoneService.class);
+ cancelAlarmOperation.setAction(FindPhoneService.ACTION_CANCEL_ALARM);
+ PendingIntent cancelAlarmIntent = PendingIntent.getService(this, 0, cancelAlarmOperation,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+ // Use a spannable string for the notification title to resize it.
+ SpannableString title = new SpannableString(getString(R.string.app_name));
+ title.setSpan(new RelativeSizeSpan(0.85f), 0, title.length(), Spannable.SPAN_POINT_MARK);
+ notification = new Notification.Builder(this)
+ .setContentTitle(title)
+ .setContentText(getString(R.string.turn_alarm_on))
+ .setSmallIcon(R.drawable.ic_launcher)
+ .setVibrate(new long[] {0, 50}) // Vibrate to bring card to top of stream.
+ .setDeleteIntent(cancelAlarmIntent)
+ .extend(new Notification.WearableExtender()
+ .addAction(alarmAction)
+ .setContentAction(0)
+ .setHintHideIcon(true))
+ .setLocalOnly(true)
+ .setPriority(Notification.PRIORITY_MAX);
+ ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
+ .notify(FIND_PHONE_NOTIFICATION_ID, notification.build());
+
+ finish();
+ }
+
+ /**
+ * Updates the text on the wearable notification. This is used so the notification reflects the
+ * current state of the alarm on the phone. For instance, if the alarm is turned on, the
+ * notification text indicates that the user can tap it to turn it off, and vice-versa.
+ *
+ * @param context
+ * @param notificationText The new text to display on the wearable notification.
+ */
+ public static void updateNotification(Context context, String notificationText) {
+ notification.setContentText(notificationText);
+ ((NotificationManager) context.getSystemService(NOTIFICATION_SERVICE))
+ .notify(FIND_PHONE_NOTIFICATION_ID, notification.build());
+ }
+
+}
diff --git a/wearable/wear/FindMyPhone/Wearable/src/main/java/com/example/android/findphone/FindPhoneService.java b/wearable/wear/FindMyPhone/Wearable/src/main/java/com/example/android/findphone/FindPhoneService.java
new file mode 100644
index 0000000..cb9f961
--- /dev/null
+++ b/wearable/wear/FindMyPhone/Wearable/src/main/java/com/example/android/findphone/FindPhoneService.java
@@ -0,0 +1,121 @@
+/*
+ * 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.android.findphone;
+
+import android.app.IntentService;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.google.android.gms.common.ConnectionResult;
+import com.google.android.gms.common.api.GoogleApiClient;
+import com.google.android.gms.wearable.DataItemBuffer;
+import com.google.android.gms.wearable.DataMap;
+import com.google.android.gms.wearable.PutDataMapRequest;
+import com.google.android.gms.wearable.Wearable;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Creates a sound on the paired phone to find it.
+ */
+public class FindPhoneService extends IntentService implements GoogleApiClient.ConnectionCallbacks,
+ GoogleApiClient.OnConnectionFailedListener {
+
+ private static final String TAG = "ExampleFindPhoneApp";
+
+ private static final String FIELD_ALARM_ON = "alarm_on";
+ private static final String PATH_SOUND_ALARM = "/sound_alarm";
+ public static final String ACTION_TOGGLE_ALARM = "action_toggle_alarm";
+ public static final String ACTION_CANCEL_ALARM = "action_alarm_off";
+
+ // Timeout for making a connection to GoogleApiClient (in milliseconds).
+ private static final long CONNECTION_TIME_OUT_MS = 100;
+ private GoogleApiClient mGoogleApiClient;
+
+ public FindPhoneService() {
+ super(FindPhoneService.class.getSimpleName());
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mGoogleApiClient = new GoogleApiClient.Builder(this)
+ .addApi(Wearable.API)
+ .addConnectionCallbacks(this)
+ .addOnConnectionFailedListener(this)
+ .build();
+ }
+
+ @Override
+ protected void onHandleIntent(Intent intent) {
+ mGoogleApiClient.blockingConnect(CONNECTION_TIME_OUT_MS, TimeUnit.MILLISECONDS);
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "FindPhoneService.onHandleIntent");
+ }
+ if (mGoogleApiClient.isConnected()) {
+ // Set the alarm off by default.
+ boolean alarmOn = false;
+ if (intent.getAction().equals(ACTION_TOGGLE_ALARM)) {
+ // Get current state of the alarm.
+ DataItemBuffer result = Wearable.DataApi.getDataItems(mGoogleApiClient).await();
+ if (result.getStatus().isSuccess()) {
+ if (result.getCount() == 1) {
+ alarmOn = DataMap.fromByteArray(result.get(0).getData())
+ .getBoolean(FIELD_ALARM_ON, false);
+ } else {
+ Log.e(TAG, "Unexpected number of DataItems found.\n"
+ + "\tExpected: 1\n"
+ + "\tActual: " + result.getCount());
+ }
+ } else if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "onHandleIntent: failed to get current alarm state");
+ }
+ result.close();
+ // Toggle alarm.
+ alarmOn = !alarmOn;
+ // Change notification text based on new value of alarmOn.
+ String notificationText = alarmOn ? getString(R.string.turn_alarm_off)
+ : getString(R.string.turn_alarm_on);
+ FindPhoneActivity.updateNotification(this, notificationText);
+ }
+ // Use alarmOn boolean to update the DataItem - phone will respond accordingly
+ // when it receives the change.
+ PutDataMapRequest putDataMapRequest = PutDataMapRequest.create(PATH_SOUND_ALARM);
+ putDataMapRequest.getDataMap().putBoolean(FIELD_ALARM_ON, alarmOn);
+ Wearable.DataApi.putDataItem(mGoogleApiClient, putDataMapRequest.asPutDataRequest())
+ .await();
+ } else {
+ Log.e(TAG, "Failed to toggle alarm on phone - Client disconnected from Google Play "
+ + "Services");
+ }
+ mGoogleApiClient.disconnect();
+ }
+
+ @Override
+ public void onConnected(Bundle connectionHint) {
+ }
+
+ @Override
+ public void onConnectionSuspended(int cause) {
+ }
+
+ @Override
+ public void onConnectionFailed(ConnectionResult result) {
+ }
+
+}
diff --git a/wearable/wear/FindMyPhone/Wearable/src/main/res/drawable-hdpi/alarm_action_icon.png b/wearable/wear/FindMyPhone/Wearable/src/main/res/drawable-hdpi/alarm_action_icon.png
new file mode 100644
index 0000000..4331a51
--- /dev/null
+++ b/wearable/wear/FindMyPhone/Wearable/src/main/res/drawable-hdpi/alarm_action_icon.png
Binary files differ
diff --git a/wearable/wear/FindMyPhone/Wearable/src/main/res/drawable-hdpi/ic_launcher.png b/wearable/wear/FindMyPhone/Wearable/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..43254bd
--- /dev/null
+++ b/wearable/wear/FindMyPhone/Wearable/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/FindMyPhone/Wearable/src/main/res/drawable-mdpi/ic_launcher.png b/wearable/wear/FindMyPhone/Wearable/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..de255d6
--- /dev/null
+++ b/wearable/wear/FindMyPhone/Wearable/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/FindMyPhone/Wearable/src/main/res/drawable-xhdpi/ic_launcher.png b/wearable/wear/FindMyPhone/Wearable/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..5a849da
--- /dev/null
+++ b/wearable/wear/FindMyPhone/Wearable/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/FindMyPhone/Wearable/src/main/res/drawable-xxhdpi/ic_launcher.png b/wearable/wear/FindMyPhone/Wearable/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..96a7cb8
--- /dev/null
+++ b/wearable/wear/FindMyPhone/Wearable/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/FindMyPhone/Wearable/src/main/res/values/strings.xml b/wearable/wear/FindMyPhone/Wearable/src/main/res/values/strings.xml
new file mode 100644
index 0000000..5c6debe
--- /dev/null
+++ b/wearable/wear/FindMyPhone/Wearable/src/main/res/values/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+
+ <string name="app_name">Find My Phone</string>
+ <string name="left_phone_title">Forgetting something?</string>
+ <string name="left_phone_content">You may have left your phone behind.</string>
+ <string name="turn_alarm_on">Tap to sound an alarm on phone.</string>
+ <string name="turn_alarm_off">Tap to stop the alarm.</string>
+
+</resources>
diff --git a/wearable/wear/FindMyPhone/build.gradle b/wearable/wear/FindMyPhone/build.gradle
new file mode 100644
index 0000000..be1fa82
--- /dev/null
+++ b/wearable/wear/FindMyPhone/build.gradle
@@ -0,0 +1,14 @@
+
+
+
+
+// BEGIN_EXCLUDE
+import com.example.android.samples.build.SampleGenPlugin
+apply plugin: SampleGenPlugin
+
+samplegen {
+ pathToBuild "../../../../../build"
+ pathToSamplesCommon "../../../common"
+}
+apply from: "../../../../../build/build.gradle"
+// END_EXCLUDE
diff --git a/wearable/wear/FindMyPhone/buildSrc/build.gradle b/wearable/wear/FindMyPhone/buildSrc/build.gradle
new file mode 100644
index 0000000..e344a8c
--- /dev/null
+++ b/wearable/wear/FindMyPhone/buildSrc/build.gradle
@@ -0,0 +1,18 @@
+
+
+
+repositories {
+ mavenCentral()
+}
+dependencies {
+ compile 'org.freemarker:freemarker:2.3.20'
+}
+
+sourceSets {
+ main {
+ groovy {
+ srcDir new File(rootDir, "../../../../../../build/buildSrc/src/main/groovy")
+ }
+ }
+}
+
diff --git a/wearable/wear/FindMyPhone/gradle/wrapper/gradle-wrapper.jar b/wearable/wear/FindMyPhone/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8c0fb64
--- /dev/null
+++ b/wearable/wear/FindMyPhone/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/wearable/wear/FindMyPhone/gradle/wrapper/gradle-wrapper.properties b/wearable/wear/FindMyPhone/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..d7f03cf
--- /dev/null
+++ b/wearable/wear/FindMyPhone/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=http\://services.gradle.org/distributions/gradle-1.12-bin.zip
diff --git a/wearable/wear/FindMyPhone/gradlew b/wearable/wear/FindMyPhone/gradlew
new file mode 100755
index 0000000..91a7e26
--- /dev/null
+++ b/wearable/wear/FindMyPhone/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/wearable/wear/FindMyPhone/gradlew.bat b/wearable/wear/FindMyPhone/gradlew.bat
new file mode 100644
index 0000000..8a0b282
--- /dev/null
+++ b/wearable/wear/FindMyPhone/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/wearable/wear/FindMyPhone/settings.gradle b/wearable/wear/FindMyPhone/settings.gradle
new file mode 100644
index 0000000..8522c57
--- /dev/null
+++ b/wearable/wear/FindMyPhone/settings.gradle
@@ -0,0 +1 @@
+include ':Application', ':Wearable', ':Shared'
diff --git a/wearable/wear/FindMyPhone/template-params.xml b/wearable/wear/FindMyPhone/template-params.xml
new file mode 100644
index 0000000..88b4529
--- /dev/null
+++ b/wearable/wear/FindMyPhone/template-params.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+
+
+<sample>
+ <name>FindMyPhone</name>
+ <group>Connectivity</group>
+ <package>com.example.android.findphone</package>
+
+
+
+ <!-- change minSdk if needed-->
+ <minSdk>20</minSdk>
+
+
+ <strings>
+ <intro>
+ <![CDATA[
+ This sample application notifies you when you may have left your phone behind
+ (specifically, when your companion and wearable disconnect). If you have misplaced your phone, but
+ it is still connected to your wearable, you can also start an activity on the wearable to sound an
+ alarm on your phone.
+ ]]>
+ </intro>
+ </strings>
+
+ <template src="base"/>
+ <template src="Wear"/>
+ <common src="logger"/>
+ <common src="activities"/>
+
+</sample>
diff --git a/wearable/wear/Flashlight/Application/.gitignore b/wearable/wear/Flashlight/Application/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/Flashlight/Application/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/Flashlight/Application/proguard-project.txt b/wearable/wear/Flashlight/Application/proguard-project.txt
new file mode 100644
index 0000000..0d8f171
--- /dev/null
+++ b/wearable/wear/Flashlight/Application/proguard-project.txt
@@ -0,0 +1,20 @@
+ To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# 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/wearable/wear/Flashlight/Application/src/main/AndroidManifest.xml b/wearable/wear/Flashlight/Application/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..2710313
--- /dev/null
+++ b/wearable/wear/Flashlight/Application/src/main/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.flashlight">
+
+ <uses-sdk android:minSdkVersion="19"
+ android:targetSdkVersion="19" />
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name">
+ </application>
+
+</manifest>
+
diff --git a/wearable/wear/Flashlight/CONTRIB.md b/wearable/wear/Flashlight/CONTRIB.md
new file mode 100644
index 0000000..14a4fcf
--- /dev/null
+++ b/wearable/wear/Flashlight/CONTRIB.md
@@ -0,0 +1,35 @@
+# How to become a contributor and submit your own code
+
+## Contributor License Agreements
+
+We'd love to accept your sample apps and patches! Before we can take them, we
+have to jump a couple of legal hurdles.
+
+Please fill out either the individual or corporate Contributor License Agreement (CLA).
+
+ * If you are an individual writing original source code and you're sure you
+ own the intellectual property, then you'll need to sign an [individual CLA]
+ (https://developers.google.com/open-source/cla/individual).
+ * If you work for a company that wants to allow you to contribute your work,
+ then you'll need to sign a [corporate CLA]
+ (https://developers.google.com/open-source/cla/corporate).
+
+Follow either of the two links above to access the appropriate CLA and
+instructions for how to sign and return it. Once we receive it, we'll be able to
+accept your pull requests.
+
+## Contributing A Patch
+
+1. Submit an issue describing your proposed change to the repo in question.
+1. The repo owner will respond to your issue promptly.
+1. If your proposed change is accepted, and you haven't already done so, sign a
+ Contributor License Agreement (see details above).
+1. Fork the desired repo, develop and test your code changes.
+1. Ensure that your code adheres to the existing style in the sample to which
+ you are contributing. Refer to the
+ [Android Code Style Guide]
+ (https://source.android.com/source/code-style.html) for the
+ recommended coding standards for this organization.
+1. Ensure that your code has an appropriate set of unit tests which all pass.
+1. Submit a pull request.
+
diff --git a/wearable/wear/Flashlight/LICENSE b/wearable/wear/Flashlight/LICENSE
new file mode 100644
index 0000000..1af981f
--- /dev/null
+++ b/wearable/wear/Flashlight/LICENSE
@@ -0,0 +1,201 @@
+ 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 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/wearable/wear/Flashlight/README-wear.txt b/wearable/wear/Flashlight/README-wear.txt
new file mode 100644
index 0000000..17523d7
--- /dev/null
+++ b/wearable/wear/Flashlight/README-wear.txt
@@ -0,0 +1,30 @@
+<#--
+ Copyright 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.
+-->
+
+Steps to use Wear template on top of an existing sample:
+- In template-params.xml.ftl:
+ - Add the following template:
+ <template src="Wear"/>
+
+- Refresh your project (./gradlew refresh)
+- Add Wearable-specific code to Wearable directory
+- Add code to be shared among the main application and the wearable to Shared
+ directory
+
+Note that you still need the main application sample code. This is usually
+achieved by adding another template, like "base" for example.
+
+
diff --git a/wearable/wear/Flashlight/Shared/.gitignore b/wearable/wear/Flashlight/Shared/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/Flashlight/Shared/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/Flashlight/Shared/src/main/AndroidManifest.xml b/wearable/wear/Flashlight/Shared/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..c7893c7
--- /dev/null
+++ b/wearable/wear/Flashlight/Shared/src/main/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.flashlight.common">
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name">
+ </application>
+
+</manifest>
diff --git a/wearable/wear/Flashlight/Shared/src/main/res/values/strings.xml b/wearable/wear/Flashlight/Shared/src/main/res/values/strings.xml
new file mode 100644
index 0000000..0f2bb90
--- /dev/null
+++ b/wearable/wear/Flashlight/Shared/src/main/res/values/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+ <string name="app_name">Shared</string>
+</resources>
diff --git a/wearable/wear/Flashlight/Wearable/.gitignore b/wearable/wear/Flashlight/Wearable/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/Flashlight/Wearable/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/Flashlight/Wearable/src/main/AndroidManifest.xml b/wearable/wear/Flashlight/Wearable/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..f22e1ab
--- /dev/null
+++ b/wearable/wear/Flashlight/Wearable/src/main/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.flashlight" >
+
+ <uses-sdk android:minSdkVersion="20"
+ android:targetSdkVersion="20" />
+
+ <uses-feature android:name="android.hardware.type.watch" />
+
+ <application
+ android:label="@string/app_name"
+ android:icon="@drawable/ic_launcher"
+ android:theme="@android:style/Theme.DeviceDefault" >
+ <activity android:name=".MainActivity"
+ android:label="@string/app_name"
+ android:launchMode="singleTop"
+ android:configChanges="orientation|keyboardHidden">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/wearable/wear/Flashlight/Wearable/src/main/java/com/example/android/flashlight/MainActivity.java b/wearable/wear/Flashlight/Wearable/src/main/java/com/example/android/flashlight/MainActivity.java
new file mode 100644
index 0000000..9e4bae5
--- /dev/null
+++ b/wearable/wear/Flashlight/Wearable/src/main/java/com/example/android/flashlight/MainActivity.java
@@ -0,0 +1,125 @@
+/*
+ * 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.android.flashlight;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.os.Bundle;
+import android.support.v13.app.FragmentPagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.support.v4.view.ViewPager.OnPageChangeListener;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.ArrayList;
+
+/**
+ * Let there be light.
+ */
+public class MainActivity extends Activity {
+
+ private ViewPager mViewPager;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.main);
+ mViewPager = (ViewPager) findViewById(R.id.pager);
+ final LightFragmentAdapter adapter = new LightFragmentAdapter(getFragmentManager());
+ adapter.addFragment(new WhiteLightFragment());
+ final PartyLightFragment partyFragment = new PartyLightFragment();
+ adapter.addFragment(partyFragment);
+ mViewPager.setAdapter(adapter);
+ mViewPager.setOnPageChangeListener(new OnPageChangeListener() {
+
+ @Override
+ public void onPageSelected(int position) {
+ if (position == 1) {
+ partyFragment.startCycling();
+ } else {
+ partyFragment.stopCycling();
+ }
+ }
+
+ @Override
+ public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int state) {
+ }
+ });
+ }
+
+ static class LightFragmentAdapter extends FragmentPagerAdapter {
+ private ArrayList<Fragment> mFragments;
+
+ public LightFragmentAdapter(FragmentManager fm) {
+ super(fm);
+ mFragments = new ArrayList<Fragment>();
+ }
+
+ @Override
+ public Fragment getItem(int position) {
+ return mFragments.get(position);
+ }
+
+ @Override
+ public int getCount() {
+ return mFragments.size();
+ }
+
+ public void addFragment(Fragment fragment) {
+ mFragments.add(fragment);
+ // Update the pager when adding a fragment.
+ notifyDataSetChanged();
+ }
+ }
+
+ public static class WhiteLightFragment extends Fragment {
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.white_light, container, false);
+ }
+ }
+
+ public static class PartyLightFragment extends Fragment {
+
+ private PartyLightView mView;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ mView = (PartyLightView) inflater.inflate(R.layout.party_light, container, false);
+ return mView;
+ }
+
+ public void startCycling() {
+ mView.startCycling();
+ }
+
+ public void stopCycling() {
+ mView.stopCycling();
+ }
+
+ }
+}
diff --git a/wearable/wear/Flashlight/Wearable/src/main/java/com/example/android/flashlight/PartyLightView.java b/wearable/wear/Flashlight/Wearable/src/main/java/com/example/android/flashlight/PartyLightView.java
new file mode 100644
index 0000000..02247d6
--- /dev/null
+++ b/wearable/wear/Flashlight/Wearable/src/main/java/com/example/android/flashlight/PartyLightView.java
@@ -0,0 +1,120 @@
+/*
+ * 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.android.flashlight;
+
+import android.animation.ArgbEvaluator;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.os.Handler;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.view.View;
+
+/**
+ * Flashing party lights!
+ */
+public class PartyLightView extends View {
+
+ private int[] mColors = new int[] {
+ Color.RED,
+ Color.GREEN,
+ Color.BLUE,
+ Color.CYAN,
+ Color.MAGENTA
+ };
+
+ private int mFromColorIndex;
+ private int mToColorIndex;
+
+ /**
+ * Value b/t 0 and 1.
+ */
+ private float mProgress;
+
+ private ArgbEvaluator mEvaluator;
+
+ private int mCurrentColor;
+
+ private Handler mHandler;
+
+ public PartyLightView(Context context) {
+ super(context);
+ init();
+ }
+
+ public PartyLightView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ canvas.drawColor(mCurrentColor);
+ super.onDraw(canvas);
+ }
+
+ public void startCycling() {
+ mHandler.sendEmptyMessage(0);
+ }
+
+ public void stopCycling() {
+ mHandler.removeMessages(0);
+ }
+
+ private void init() {
+ mEvaluator = new ArgbEvaluator();
+ mHandler = new Handler() {
+
+ @Override
+ public void handleMessage(Message msg) {
+ mCurrentColor = getColor(mProgress, mColors[mFromColorIndex],
+ mColors[mToColorIndex]);
+ postInvalidate();
+ mProgress += 0.1;
+ if (mProgress > 1.0) {
+ mFromColorIndex = mToColorIndex;
+ // Find a new color.
+ mToColorIndex++;
+ if (mToColorIndex >= mColors.length) {
+ mToColorIndex = 0;
+ }
+ }
+ mHandler.sendEmptyMessageDelayed(0, 100);
+ }
+ };
+ }
+
+ private int getColor(float fraction, int colorStart, int colorEnd) {
+ int startInt = colorStart;
+ int startA = (startInt >> 24) & 0xff;
+ int startR = (startInt >> 16) & 0xff;
+ int startG = (startInt >> 8) & 0xff;
+ int startB = startInt & 0xff;
+
+ int endInt = colorEnd;
+ int endA = (endInt >> 24) & 0xff;
+ int endR = (endInt >> 16) & 0xff;
+ int endG = (endInt >> 8) & 0xff;
+ int endB = endInt & 0xff;
+
+ return (startA + (int)(fraction * (endA - startA))) << 24 |
+ (startR + (int)(fraction * (endR - startR))) << 16 |
+ (startG + (int)(fraction * (endG - startG))) << 8 |
+ ((startB + (int)(fraction * (endB - startB))));
+ }
+}
diff --git a/wearable/wear/Flashlight/Wearable/src/main/res/drawable-hdpi/ic_launcher.png b/wearable/wear/Flashlight/Wearable/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100755
index 0000000..589f229
--- /dev/null
+++ b/wearable/wear/Flashlight/Wearable/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Flashlight/Wearable/src/main/res/drawable-mdpi/ic_launcher.png b/wearable/wear/Flashlight/Wearable/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100755
index 0000000..77dd571
--- /dev/null
+++ b/wearable/wear/Flashlight/Wearable/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Flashlight/Wearable/src/main/res/drawable-xhdpi/ic_launcher.png b/wearable/wear/Flashlight/Wearable/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100755
index 0000000..fe34ebe
--- /dev/null
+++ b/wearable/wear/Flashlight/Wearable/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Flashlight/Wearable/src/main/res/drawable-xxhdpi/ic_launcher.png b/wearable/wear/Flashlight/Wearable/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100755
index 0000000..ab80bcd
--- /dev/null
+++ b/wearable/wear/Flashlight/Wearable/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Flashlight/Wearable/src/main/res/layout/main.xml b/wearable/wear/Flashlight/Wearable/src/main/res/layout/main.xml
new file mode 100644
index 0000000..1e10f5a
--- /dev/null
+++ b/wearable/wear/Flashlight/Wearable/src/main/res/layout/main.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<android.support.v4.view.ViewPager
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/pager"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="#000"
+ android:keepScreenOn="true"
+ />
diff --git a/wearable/wear/Flashlight/Wearable/src/main/res/layout/party_light.xml b/wearable/wear/Flashlight/Wearable/src/main/res/layout/party_light.xml
new file mode 100644
index 0000000..b29ef94
--- /dev/null
+++ b/wearable/wear/Flashlight/Wearable/src/main/res/layout/party_light.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<com.example.android.wearable.flashlight.PartyLightView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ />
diff --git a/wearable/wear/Flashlight/Wearable/src/main/res/layout/white_light.xml b/wearable/wear/Flashlight/Wearable/src/main/res/layout/white_light.xml
new file mode 100644
index 0000000..94353a2
--- /dev/null
+++ b/wearable/wear/Flashlight/Wearable/src/main/res/layout/white_light.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<View xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="#fff"
+ />
diff --git a/wearable/wear/Flashlight/Wearable/src/main/res/values/strings.xml b/wearable/wear/Flashlight/Wearable/src/main/res/values/strings.xml
new file mode 100644
index 0000000..6790e2d
--- /dev/null
+++ b/wearable/wear/Flashlight/Wearable/src/main/res/values/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Name of the wearable app [CHAR LIMIT=NONE] -->
+ <string name="app_name">Flashlight</string>
+
+</resources>
diff --git a/wearable/wear/Flashlight/build.gradle b/wearable/wear/Flashlight/build.gradle
new file mode 100644
index 0000000..be1fa82
--- /dev/null
+++ b/wearable/wear/Flashlight/build.gradle
@@ -0,0 +1,14 @@
+
+
+
+
+// BEGIN_EXCLUDE
+import com.example.android.samples.build.SampleGenPlugin
+apply plugin: SampleGenPlugin
+
+samplegen {
+ pathToBuild "../../../../../build"
+ pathToSamplesCommon "../../../common"
+}
+apply from: "../../../../../build/build.gradle"
+// END_EXCLUDE
diff --git a/wearable/wear/Flashlight/buildSrc/build.gradle b/wearable/wear/Flashlight/buildSrc/build.gradle
new file mode 100644
index 0000000..e344a8c
--- /dev/null
+++ b/wearable/wear/Flashlight/buildSrc/build.gradle
@@ -0,0 +1,18 @@
+
+
+
+repositories {
+ mavenCentral()
+}
+dependencies {
+ compile 'org.freemarker:freemarker:2.3.20'
+}
+
+sourceSets {
+ main {
+ groovy {
+ srcDir new File(rootDir, "../../../../../../build/buildSrc/src/main/groovy")
+ }
+ }
+}
+
diff --git a/wearable/wear/Flashlight/gradle/wrapper/gradle-wrapper.jar b/wearable/wear/Flashlight/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8c0fb64
--- /dev/null
+++ b/wearable/wear/Flashlight/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/wearable/wear/Flashlight/gradle/wrapper/gradle-wrapper.properties b/wearable/wear/Flashlight/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..d7f03cf
--- /dev/null
+++ b/wearable/wear/Flashlight/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=http\://services.gradle.org/distributions/gradle-1.12-bin.zip
diff --git a/wearable/wear/Flashlight/gradlew b/wearable/wear/Flashlight/gradlew
new file mode 100755
index 0000000..91a7e26
--- /dev/null
+++ b/wearable/wear/Flashlight/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/wearable/wear/Flashlight/gradlew.bat b/wearable/wear/Flashlight/gradlew.bat
new file mode 100644
index 0000000..8a0b282
--- /dev/null
+++ b/wearable/wear/Flashlight/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/wearable/wear/Flashlight/settings.gradle b/wearable/wear/Flashlight/settings.gradle
new file mode 100644
index 0000000..8522c57
--- /dev/null
+++ b/wearable/wear/Flashlight/settings.gradle
@@ -0,0 +1 @@
+include ':Application', ':Wearable', ':Shared'
diff --git a/wearable/wear/Flashlight/template-params.xml b/wearable/wear/Flashlight/template-params.xml
new file mode 100644
index 0000000..da0fe1a
--- /dev/null
+++ b/wearable/wear/Flashlight/template-params.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+
+
+<sample>
+ <name>Flashlight</name>
+ <group>Connectivity</group>
+ <package>com.example.android.flashlight</package>
+
+
+
+ <!-- change minSdk if needed-->
+ <minSdk>20</minSdk>
+
+
+ <strings>
+ <intro>
+ <![CDATA[
+ Wearable activity that uses your wearable screen as a flashlight. There is also
+ a party-mode option, if you want to make things interesting.
+ ]]>
+ </intro>
+ </strings>
+
+ <template src="base"/>
+ <template src="Wear"/>
+ <common src="logger"/>
+ <common src="activities"/>
+
+</sample>
diff --git a/wearable/wear/Geofencing/Application/.gitignore b/wearable/wear/Geofencing/Application/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/Geofencing/Application/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/Geofencing/Application/proguard-project.txt b/wearable/wear/Geofencing/Application/proguard-project.txt
new file mode 100644
index 0000000..0d8f171
--- /dev/null
+++ b/wearable/wear/Geofencing/Application/proguard-project.txt
@@ -0,0 +1,20 @@
+ To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# 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/wearable/wear/Geofencing/Application/src/main/AndroidManifest.xml b/wearable/wear/Geofencing/Application/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..519aa14
--- /dev/null
+++ b/wearable/wear/Geofencing/Application/src/main/AndroidManifest.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.geofencing">
+
+ <uses-sdk android:minSdkVersion="19"
+ android:targetSdkVersion="19" />
+
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@android:style/Theme.Holo.Light"
+ android:allowBackup="true">
+
+ <meta-data
+ android:name="com.google.android.gms.version"
+ android:value="@integer/google_play_services_version"/>
+
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name"
+ android:theme="@android:style/Theme.Translucent.NoTitleBar"
+ android:excludeFromRecents="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+
+ <service
+ android:name=".GeofenceTransitionsIntentService"
+ android:exported="false">
+ </service>
+ </application>
+</manifest>
diff --git a/wearable/wear/Geofencing/Application/src/main/java/com/example/android/geofencing/Constants.java b/wearable/wear/Geofencing/Application/src/main/java/com/example/android/geofencing/Constants.java
new file mode 100644
index 0000000..b90aa3b
--- /dev/null
+++ b/wearable/wear/Geofencing/Application/src/main/java/com/example/android/geofencing/Constants.java
@@ -0,0 +1,77 @@
+/*
+ * 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.android.geofencing;
+
+import android.net.Uri;
+
+import com.google.android.gms.location.Geofence;
+
+/** Constants used in companion app. */
+public final class Constants {
+
+ private Constants() {
+ }
+
+ public static final String TAG = "ExampleGeofencingApp";
+
+ // Request code to attempt to resolve Google Play services connection failures.
+ public final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
+ // Timeout for making a connection to GoogleApiClient (in milliseconds).
+ public static final long CONNECTION_TIME_OUT_MS = 100;
+
+ // For the purposes of this demo, the geofences are hard-coded and should not expire.
+ // An app with dynamically-created geofences would want to include a reasonable expiration time.
+ public static final long GEOFENCE_EXPIRATION_TIME = Geofence.NEVER_EXPIRE;
+
+ // Geofence parameters for the Android building on Google's main campus in Mountain View.
+ public static final String ANDROID_BUILDING_ID = "1";
+ public static final double ANDROID_BUILDING_LATITUDE = 37.420092;
+ public static final double ANDROID_BUILDING_LONGITUDE = -122.083648;
+ public static final float ANDROID_BUILDING_RADIUS_METERS = 60.0f;
+
+ // Geofence parameters for the Yerba Buena Gardens near the Moscone Center in San Francisco.
+ public static final String YERBA_BUENA_ID = "2";
+ public static final double YERBA_BUENA_LATITUDE = 37.784886;
+ public static final double YERBA_BUENA_LONGITUDE = -122.402671;
+ public static final float YERBA_BUENA_RADIUS_METERS = 72.0f;
+
+
+ // The constants below are less interesting than those above.
+
+ // Path for the DataItem containing the last geofence id entered.
+ public static final String GEOFENCE_DATA_ITEM_PATH = "/geofenceid";
+ public static final Uri GEOFENCE_DATA_ITEM_URI =
+ new Uri.Builder().scheme("wear").path(GEOFENCE_DATA_ITEM_PATH).build();
+ public static final String KEY_GEOFENCE_ID = "geofence_id";
+
+ // Keys for flattened geofences stored in SharedPreferences.
+ public static final String KEY_LATITUDE = "com.example.wearable.geofencing.KEY_LATITUDE";
+ public static final String KEY_LONGITUDE = "com.example.wearable.geofencing.KEY_LONGITUDE";
+ public static final String KEY_RADIUS = "com.example.wearable.geofencing.KEY_RADIUS";
+ public static final String KEY_EXPIRATION_DURATION =
+ "com.example.wearable.geofencing.KEY_EXPIRATION_DURATION";
+ public static final String KEY_TRANSITION_TYPE =
+ "com.example.wearable.geofencing.KEY_TRANSITION_TYPE";
+ // The prefix for flattened geofence keys.
+ public static final String KEY_PREFIX = "com.example.wearable.geofencing.KEY";
+
+ // Invalid values, used to test geofence storage when retrieving geofences.
+ public static final long INVALID_LONG_VALUE = -999l;
+ public static final float INVALID_FLOAT_VALUE = -999.0f;
+ public static final int INVALID_INT_VALUE = -999;
+
+}
diff --git a/wearable/wear/Geofencing/Application/src/main/java/com/example/android/geofencing/GeofenceTransitionsIntentService.java b/wearable/wear/Geofencing/Application/src/main/java/com/example/android/geofencing/GeofenceTransitionsIntentService.java
new file mode 100644
index 0000000..1af7bc6
--- /dev/null
+++ b/wearable/wear/Geofencing/Application/src/main/java/com/example/android/geofencing/GeofenceTransitionsIntentService.java
@@ -0,0 +1,119 @@
+/*
+ * 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.android.geofencing;
+
+import static com.example.android.geofencing.Constants.CONNECTION_TIME_OUT_MS;
+import static com.example.android.geofencing.Constants.GEOFENCE_DATA_ITEM_PATH;
+import static com.example.android.geofencing.Constants.GEOFENCE_DATA_ITEM_URI;
+import static com.example.android.geofencing.Constants.KEY_GEOFENCE_ID;
+import static com.example.android.geofencing.Constants.TAG;
+
+import android.app.IntentService;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.google.android.gms.common.ConnectionResult;
+import com.google.android.gms.common.api.GoogleApiClient;
+import com.google.android.gms.location.Geofence;
+import com.google.android.gms.location.LocationClient;
+import com.google.android.gms.wearable.PutDataMapRequest;
+import com.google.android.gms.wearable.Wearable;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Listens for geofence transition changes.
+ */
+public class GeofenceTransitionsIntentService extends IntentService
+ implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
+
+ private GoogleApiClient mGoogleApiClient;
+
+ public GeofenceTransitionsIntentService() {
+ super(GeofenceTransitionsIntentService.class.getSimpleName());
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mGoogleApiClient = new GoogleApiClient.Builder(this)
+ .addApi(Wearable.API)
+ .addConnectionCallbacks(this)
+ .addOnConnectionFailedListener(this)
+ .build();
+ }
+
+ /**
+ * Handles incoming intents.
+ * @param intent The Intent sent by Location Services. This Intent is provided to Location
+ * Services (inside a PendingIntent) when addGeofences() is called.
+ */
+ @Override
+ protected void onHandleIntent(Intent intent) {
+ // First check for errors.
+ if (LocationClient.hasError(intent)) {
+ int errorCode = LocationClient.getErrorCode(intent);
+ Log.e(TAG, "Location Services error: " + errorCode);
+ } else {
+ // Get the type of geofence transition (i.e. enter or exit in this sample).
+ int transitionType = LocationClient.getGeofenceTransition(intent);
+ // Create a DataItem when a user enters one of the geofences. The wearable app will
+ // receive this and create a notification to prompt him/her to check in.
+ if (Geofence.GEOFENCE_TRANSITION_ENTER == transitionType) {
+ // Connect to the Google Api service in preparation for sending a DataItem.
+ mGoogleApiClient.blockingConnect(CONNECTION_TIME_OUT_MS, TimeUnit.MILLISECONDS);
+ // Get the geofence id triggered. Note that only one geofence can be triggered at a
+ // time in this example, but in some cases you might want to consider the full list
+ // of geofences triggered.
+ String triggeredGeofenceId = LocationClient.getTriggeringGeofences(intent).get(0)
+ .getRequestId();
+ // Create a DataItem with this geofence's id. The wearable can use this to create
+ // a notification.
+ final PutDataMapRequest putDataMapRequest =
+ PutDataMapRequest.create(GEOFENCE_DATA_ITEM_PATH);
+ putDataMapRequest.getDataMap().putString(KEY_GEOFENCE_ID, triggeredGeofenceId);
+ if (mGoogleApiClient.isConnected()) {
+ Wearable.DataApi.putDataItem(
+ mGoogleApiClient, putDataMapRequest.asPutDataRequest()).await();
+ } else {
+ Log.e(TAG, "Failed to send data item: " + putDataMapRequest
+ + " - Client disconnected from Google Play Services");
+ }
+ mGoogleApiClient.disconnect();
+ } else if (Geofence.GEOFENCE_TRANSITION_EXIT == transitionType) {
+ // Delete the data item when leaving a geofence region.
+ mGoogleApiClient.blockingConnect(CONNECTION_TIME_OUT_MS, TimeUnit.MILLISECONDS);
+ Wearable.DataApi.deleteDataItems(mGoogleApiClient, GEOFENCE_DATA_ITEM_URI).await();
+ mGoogleApiClient.disconnect();
+ }
+ }
+ }
+
+ @Override
+ public void onConnected(Bundle connectionHint) {
+ }
+
+ @Override
+ public void onConnectionSuspended(int cause) {
+ }
+
+ @Override
+ public void onConnectionFailed(ConnectionResult result) {
+ }
+
+}
diff --git a/wearable/wear/Geofencing/Application/src/main/java/com/example/android/geofencing/MainActivity.java b/wearable/wear/Geofencing/Application/src/main/java/com/example/android/geofencing/MainActivity.java
new file mode 100644
index 0000000..67dcd07
--- /dev/null
+++ b/wearable/wear/Geofencing/Application/src/main/java/com/example/android/geofencing/MainActivity.java
@@ -0,0 +1,240 @@
+/*
+ * 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.android.geofencing;
+
+import static com.example.android.geofencing.Constants.ANDROID_BUILDING_ID;
+import static com.example.android.geofencing.Constants.ANDROID_BUILDING_LATITUDE;
+import static com.example.android.geofencing.Constants.ANDROID_BUILDING_LONGITUDE;
+import static com.example.android.geofencing.Constants.ANDROID_BUILDING_RADIUS_METERS;
+import static com.example.android.geofencing.Constants.CONNECTION_FAILURE_RESOLUTION_REQUEST;
+import static com.example.android.geofencing.Constants.GEOFENCE_EXPIRATION_TIME;
+import static com.example.android.geofencing.Constants.TAG;
+import static com.example.android.geofencing.Constants.YERBA_BUENA_ID;
+import static com.example.android.geofencing.Constants.YERBA_BUENA_LATITUDE;
+import static com.example.android.geofencing.Constants.YERBA_BUENA_LONGITUDE;
+import static com.example.android.geofencing.Constants.YERBA_BUENA_RADIUS_METERS;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.content.IntentSender;
+import android.os.Bundle;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.google.android.gms.common.ConnectionResult;
+import com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks;
+import com.google.android.gms.common.GooglePlayServicesUtil;
+import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
+import com.google.android.gms.location.Geofence;
+import com.google.android.gms.location.LocationClient;
+import com.google.android.gms.location.LocationClient.OnAddGeofencesResultListener;
+import com.google.android.gms.location.LocationStatusCodes;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class MainActivity extends Activity implements ConnectionCallbacks,
+ OnConnectionFailedListener, OnAddGeofencesResultListener {
+
+ // Internal List of Geofence objects. In a real app, these might be provided by an API based on
+ // locations within the user's proximity.
+ List<Geofence> mGeofenceList;
+
+ // These will store hard-coded geofences in this sample app.
+ private SimpleGeofence mAndroidBuildingGeofence;
+ private SimpleGeofence mYerbaBuenaGeofence;
+
+ // Persistent storage for geofences.
+ private SimpleGeofenceStore mGeofenceStorage;
+
+ private LocationClient mLocationClient;
+ // Stores the PendingIntent used to request geofence monitoring.
+ private PendingIntent mGeofenceRequestIntent;
+
+ // Defines the allowable request types (in this example, we only add geofences).
+ private enum REQUEST_TYPE {ADD}
+ private REQUEST_TYPE mRequestType;
+ // Flag that indicates if a request is underway.
+ private boolean mInProgress;
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ // Rather than displayng this activity, simply display a toast indicating that the geofence
+ // service is being created. This should happen in less than a second.
+ Toast.makeText(this, getString(R.string.start_geofence_service), Toast.LENGTH_SHORT).show();
+
+ // Instantiate a new geofence storage area.
+ mGeofenceStorage = new SimpleGeofenceStore(this);
+ // Instantiate the current List of geofences.
+ mGeofenceList = new ArrayList<Geofence>();
+ // Start with the request flag set to false.
+ mInProgress = false;
+
+ createGeofences();
+ addGeofences();
+
+ finish();
+ }
+
+ /**
+ * In this sample, the geofences are predetermined and are hard-coded here. A real app might
+ * dynamically create geofences based on the user's location.
+ */
+ public void createGeofences() {
+ // Create internal "flattened" objects containing the geofence data.
+ mAndroidBuildingGeofence = new SimpleGeofence(
+ ANDROID_BUILDING_ID, // geofenceId.
+ ANDROID_BUILDING_LATITUDE,
+ ANDROID_BUILDING_LONGITUDE,
+ ANDROID_BUILDING_RADIUS_METERS,
+ GEOFENCE_EXPIRATION_TIME,
+ Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT
+ );
+ mYerbaBuenaGeofence = new SimpleGeofence(
+ YERBA_BUENA_ID, // geofenceId.
+ YERBA_BUENA_LATITUDE,
+ YERBA_BUENA_LONGITUDE,
+ YERBA_BUENA_RADIUS_METERS,
+ GEOFENCE_EXPIRATION_TIME,
+ Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT
+ );
+
+ // Store these flat versions in SharedPreferences and add them to the geofence list.
+ mGeofenceStorage.setGeofence(ANDROID_BUILDING_ID, mAndroidBuildingGeofence);
+ mGeofenceStorage.setGeofence(YERBA_BUENA_ID, mYerbaBuenaGeofence);
+ mGeofenceList.add(mAndroidBuildingGeofence.toGeofence());
+ mGeofenceList.add(mYerbaBuenaGeofence.toGeofence());
+ }
+
+ /**
+ * Start a request for geofence monitoring by calling LocationClient.connect().
+ */
+ public void addGeofences() {
+ // Start a request to add geofences.
+ mRequestType = REQUEST_TYPE.ADD;
+ // Test for Google Play services after setting the request type.
+ if (!isGooglePlayServicesAvailable()) {
+ Log.e(TAG, "Unable to add geofences - Google Play services unavailable.");
+ return;
+ }
+ // Create a new location client object. Since this activity class implements
+ // ConnectionCallbacks and OnConnectionFailedListener, it can be used as the listener for
+ // both parameters.
+ mLocationClient = new LocationClient(this, this, this);
+ // If a request is not already underway.
+ if (!mInProgress) {
+ // Indicate that a request is underway.
+ mInProgress = true;
+ // Request a connection from the client to Location Services.
+ mLocationClient.connect();
+ // A request is already underway, so disconnect the client and retry the request.
+ } else {
+ mLocationClient.disconnect();
+ mLocationClient.connect();
+ }
+ }
+
+ @Override
+ public void onConnectionFailed(ConnectionResult connectionResult) {
+ mInProgress = false;
+ // If the error has a resolution, start a Google Play services activity to resolve it.
+ if (connectionResult.hasResolution()) {
+ try {
+ connectionResult.startResolutionForResult(this,
+ CONNECTION_FAILURE_RESOLUTION_REQUEST);
+ } catch (IntentSender.SendIntentException e) {
+ Log.e(TAG, "Exception while resolving connection error.", e);
+ }
+ } else {
+ int errorCode = connectionResult.getErrorCode();
+ Log.e(TAG, "Connection to Google Play services failed with error code " + errorCode);
+ }
+ }
+
+ /**
+ * Called by Location Services if the location client disconnects.
+ */
+ @Override
+ public void onDisconnected() {
+ // Turn off the request flag.
+ mInProgress = false;
+ // Destroy the current location client.
+ mLocationClient = null;
+ }
+
+ /**
+ * Once the connection is available, send a request to add the Geofences.
+ */
+ @Override
+ public void onConnected(Bundle connectionHint) {
+ // Use mRequestType to determine what action to take. Only ADD is used in this sample.
+ if (REQUEST_TYPE.ADD == mRequestType) {
+ // Get the PendingIntent for the geofence monitoring request.
+ mGeofenceRequestIntent = getGeofenceTransitionPendingIntent();
+ // Send a request to add the current geofences.
+ mLocationClient.addGeofences(mGeofenceList, mGeofenceRequestIntent, this);
+ }
+ }
+
+ /**
+ * Called when request to add geofences is complete, with a result status code.
+ */
+ @Override
+ public void onAddGeofencesResult(int statusCode, String[] geofenceRequestIds) {
+ // Log if adding the geofences was successful.
+ if (LocationStatusCodes.SUCCESS == statusCode) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Added geofences successfully.");
+ }
+ } else {
+ Log.e(TAG, "Failed to add geofences. Status code: " + statusCode);
+ }
+ // Turn off the in progress flag and disconnect the client.
+ mInProgress = false;
+ mLocationClient.disconnect();
+ }
+
+ /**
+ * Checks if Google Play services is available.
+ * @return true if it is.
+ */
+ private boolean isGooglePlayServicesAvailable() {
+ int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
+ if (ConnectionResult.SUCCESS == resultCode) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Google Play services is available.");
+ }
+ return true;
+ } else {
+ Log.e(TAG, "Google Play services is unavailable.");
+ return false;
+ }
+ }
+
+ /**
+ * Create a PendingIntent that triggers GeofenceTransitionIntentService when a geofence
+ * transition occurs.
+ */
+ private PendingIntent getGeofenceTransitionPendingIntent() {
+ Intent intent = new Intent(this, GeofenceTransitionsIntentService.class);
+ return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ }
+
+}
diff --git a/wearable/wear/Geofencing/Application/src/main/java/com/example/android/geofencing/SimpleGeofence.java b/wearable/wear/Geofencing/Application/src/main/java/com/example/android/geofencing/SimpleGeofence.java
new file mode 100644
index 0000000..8e17526
--- /dev/null
+++ b/wearable/wear/Geofencing/Application/src/main/java/com/example/android/geofencing/SimpleGeofence.java
@@ -0,0 +1,87 @@
+/*
+ * 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.android.geofencing;
+
+import com.google.android.gms.location.Geofence;
+
+/**
+ * A single Geofence object, defined by its center and radius.
+ */
+public class SimpleGeofence {
+
+ // Instance variables
+ private final String mId;
+ private final double mLatitude;
+ private final double mLongitude;
+ private final float mRadius;
+ private long mExpirationDuration;
+ private int mTransitionType;
+
+ /**
+ * @param geofenceId The Geofence's request ID.
+ * @param latitude Latitude of the Geofence's center in degrees.
+ * @param longitude Longitude of the Geofence's center in degrees.
+ * @param radius Radius of the geofence circle in meters.
+ * @param expiration Geofence expiration duration.
+ * @param transition Type of Geofence transition.
+ */
+ public SimpleGeofence(String geofenceId, double latitude, double longitude, float radius,
+ long expiration, int transition) {
+ // Set the instance fields from the constructor.
+ this.mId = geofenceId;
+ this.mLatitude = latitude;
+ this.mLongitude = longitude;
+ this.mRadius = radius;
+ this.mExpirationDuration = expiration;
+ this.mTransitionType = transition;
+ }
+
+ // Instance field getters.
+ public String getId() {
+ return mId;
+ }
+ public double getLatitude() {
+ return mLatitude;
+ }
+ public double getLongitude() {
+ return mLongitude;
+ }
+ public float getRadius() {
+ return mRadius;
+ }
+ public long getExpirationDuration() {
+ return mExpirationDuration;
+ }
+ public int getTransitionType() {
+ return mTransitionType;
+ }
+
+ /**
+ * Creates a Location Services Geofence object from a SimpleGeofence.
+ * @return A Geofence object.
+ */
+ public Geofence toGeofence() {
+ // Build a new Geofence object.
+ return new Geofence.Builder()
+ .setRequestId(mId)
+ .setTransitionTypes(mTransitionType)
+ .setCircularRegion(mLatitude, mLongitude, mRadius)
+ .setExpirationDuration(mExpirationDuration)
+ .build();
+ }
+
+}
diff --git a/wearable/wear/Geofencing/Application/src/main/java/com/example/android/geofencing/SimpleGeofenceStore.java b/wearable/wear/Geofencing/Application/src/main/java/com/example/android/geofencing/SimpleGeofenceStore.java
new file mode 100644
index 0000000..fcdf8f8
--- /dev/null
+++ b/wearable/wear/Geofencing/Application/src/main/java/com/example/android/geofencing/SimpleGeofenceStore.java
@@ -0,0 +1,124 @@
+/*
+ * 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.android.geofencing;
+
+import static com.example.android.geofencing.Constants.INVALID_FLOAT_VALUE;
+import static com.example.android.geofencing.Constants.INVALID_INT_VALUE;
+import static com.example.android.geofencing.Constants.INVALID_LONG_VALUE;
+import static com.example.android.geofencing.Constants.KEY_EXPIRATION_DURATION;
+import static com.example.android.geofencing.Constants.KEY_LATITUDE;
+import static com.example.android.geofencing.Constants.KEY_LONGITUDE;
+import static com.example.android.geofencing.Constants.KEY_PREFIX;
+import static com.example.android.geofencing.Constants.KEY_RADIUS;
+import static com.example.android.geofencing.Constants.KEY_TRANSITION_TYPE;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+
+/**
+ * Storage for geofence values, implemented in SharedPreferences.
+ */
+public class SimpleGeofenceStore {
+
+ // The SharedPreferences object in which geofences are stored.
+ private final SharedPreferences mPrefs;
+ // The name of the SharedPreferences.
+ private static final String SHARED_PREFERENCES = "SharedPreferences";
+
+ /**
+ * Create the SharedPreferences storage with private access only.
+ */
+ public SimpleGeofenceStore(Context context) {
+ mPrefs = context.getSharedPreferences(SHARED_PREFERENCES, Context.MODE_PRIVATE);
+ }
+
+ /**
+ * Returns a stored geofence by its id, or returns null if it's not found.
+ * @param id The ID of a stored geofence.
+ * @return A SimpleGeofence defined by its center and radius, or null if the ID is invalid.
+ */
+ public SimpleGeofence getGeofence(String id) {
+ // Get the latitude for the geofence identified by id, or INVALID_FLOAT_VALUE if it doesn't
+ // exist (similarly for the other values that follow).
+ double lat = mPrefs.getFloat(getGeofenceFieldKey(id, KEY_LATITUDE),
+ INVALID_FLOAT_VALUE);
+ double lng = mPrefs.getFloat(getGeofenceFieldKey(id, KEY_LONGITUDE),
+ INVALID_FLOAT_VALUE);
+ float radius = mPrefs.getFloat(getGeofenceFieldKey(id, KEY_RADIUS),
+ INVALID_FLOAT_VALUE);
+ long expirationDuration =
+ mPrefs.getLong(getGeofenceFieldKey(id, KEY_EXPIRATION_DURATION),
+ INVALID_LONG_VALUE);
+ int transitionType = mPrefs.getInt(getGeofenceFieldKey(id, KEY_TRANSITION_TYPE),
+ INVALID_INT_VALUE);
+ // If none of the values is incorrect, return the object.
+ if (lat != INVALID_FLOAT_VALUE
+ && lng != INVALID_FLOAT_VALUE
+ && radius != INVALID_FLOAT_VALUE
+ && expirationDuration != INVALID_LONG_VALUE
+ && transitionType != INVALID_INT_VALUE) {
+ return new SimpleGeofence(id, lat, lng, radius, expirationDuration, transitionType);
+ }
+ // Otherwise, return null.
+ return null;
+ }
+
+ /**
+ * Save a geofence.
+ * @param geofence The SimpleGeofence with the values you want to save in SharedPreferences.
+ */
+ public void setGeofence(String id, SimpleGeofence geofence) {
+ // Get a SharedPreferences editor instance. Among other things, SharedPreferences
+ // ensures that updates are atomic and non-concurrent.
+ SharedPreferences.Editor prefs = mPrefs.edit();
+ // Write the Geofence values to SharedPreferences.
+ prefs.putFloat(getGeofenceFieldKey(id, KEY_LATITUDE), (float) geofence.getLatitude());
+ prefs.putFloat(getGeofenceFieldKey(id, KEY_LONGITUDE), (float) geofence.getLongitude());
+ prefs.putFloat(getGeofenceFieldKey(id, KEY_RADIUS), geofence.getRadius());
+ prefs.putLong(getGeofenceFieldKey(id, KEY_EXPIRATION_DURATION),
+ geofence.getExpirationDuration());
+ prefs.putInt(getGeofenceFieldKey(id, KEY_TRANSITION_TYPE),
+ geofence.getTransitionType());
+ // Commit the changes.
+ prefs.commit();
+ }
+
+ /**
+ * Remove a flattened geofence object from storage by removing all of its keys.
+ */
+ public void clearGeofence(String id) {
+ SharedPreferences.Editor prefs = mPrefs.edit();
+ prefs.remove(getGeofenceFieldKey(id, KEY_LATITUDE));
+ prefs.remove(getGeofenceFieldKey(id, KEY_LONGITUDE));
+ prefs.remove(getGeofenceFieldKey(id, KEY_RADIUS));
+ prefs.remove(getGeofenceFieldKey(id, KEY_EXPIRATION_DURATION));
+ prefs.remove(getGeofenceFieldKey(id, KEY_TRANSITION_TYPE));
+ prefs.commit();
+ }
+
+ /**
+ * Given a Geofence object's ID and the name of a field (for example, KEY_LATITUDE), return
+ * the key name of the object's values in SharedPreferences.
+ * @param id The ID of a Geofence object.
+ * @param fieldName The field represented by the key.
+ * @return The full key name of a value in SharedPreferences.
+ */
+ private String getGeofenceFieldKey(String id, String fieldName) {
+ return KEY_PREFIX + "_" + id + "_" + fieldName;
+ }
+
+}
diff --git a/wearable/wear/Geofencing/Application/src/main/res/drawable-hdpi/ic_launcher.png b/wearable/wear/Geofencing/Application/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..4e3e000
--- /dev/null
+++ b/wearable/wear/Geofencing/Application/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Geofencing/Application/src/main/res/drawable-mdpi/ic_launcher.png b/wearable/wear/Geofencing/Application/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..b405cb2
--- /dev/null
+++ b/wearable/wear/Geofencing/Application/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Geofencing/Application/src/main/res/drawable-xhdpi/ic_launcher.png b/wearable/wear/Geofencing/Application/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..61f9d88
--- /dev/null
+++ b/wearable/wear/Geofencing/Application/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Geofencing/Application/src/main/res/drawable-xxhdpi/ic_launcher.png b/wearable/wear/Geofencing/Application/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..81c1008
--- /dev/null
+++ b/wearable/wear/Geofencing/Application/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Geofencing/Application/src/main/res/values/strings.xml b/wearable/wear/Geofencing/Application/src/main/res/values/strings.xml
new file mode 100644
index 0000000..ad9717b
--- /dev/null
+++ b/wearable/wear/Geofencing/Application/src/main/res/values/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="start_geofence_service">Starting geofence transition service</string>
+</resources>
diff --git a/wearable/wear/Geofencing/CONTRIB.md b/wearable/wear/Geofencing/CONTRIB.md
new file mode 100644
index 0000000..14a4fcf
--- /dev/null
+++ b/wearable/wear/Geofencing/CONTRIB.md
@@ -0,0 +1,35 @@
+# How to become a contributor and submit your own code
+
+## Contributor License Agreements
+
+We'd love to accept your sample apps and patches! Before we can take them, we
+have to jump a couple of legal hurdles.
+
+Please fill out either the individual or corporate Contributor License Agreement (CLA).
+
+ * If you are an individual writing original source code and you're sure you
+ own the intellectual property, then you'll need to sign an [individual CLA]
+ (https://developers.google.com/open-source/cla/individual).
+ * If you work for a company that wants to allow you to contribute your work,
+ then you'll need to sign a [corporate CLA]
+ (https://developers.google.com/open-source/cla/corporate).
+
+Follow either of the two links above to access the appropriate CLA and
+instructions for how to sign and return it. Once we receive it, we'll be able to
+accept your pull requests.
+
+## Contributing A Patch
+
+1. Submit an issue describing your proposed change to the repo in question.
+1. The repo owner will respond to your issue promptly.
+1. If your proposed change is accepted, and you haven't already done so, sign a
+ Contributor License Agreement (see details above).
+1. Fork the desired repo, develop and test your code changes.
+1. Ensure that your code adheres to the existing style in the sample to which
+ you are contributing. Refer to the
+ [Android Code Style Guide]
+ (https://source.android.com/source/code-style.html) for the
+ recommended coding standards for this organization.
+1. Ensure that your code has an appropriate set of unit tests which all pass.
+1. Submit a pull request.
+
diff --git a/wearable/wear/Geofencing/LICENSE b/wearable/wear/Geofencing/LICENSE
new file mode 100644
index 0000000..1af981f
--- /dev/null
+++ b/wearable/wear/Geofencing/LICENSE
@@ -0,0 +1,201 @@
+ 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 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/wearable/wear/Geofencing/README-wear.txt b/wearable/wear/Geofencing/README-wear.txt
new file mode 100644
index 0000000..17523d7
--- /dev/null
+++ b/wearable/wear/Geofencing/README-wear.txt
@@ -0,0 +1,30 @@
+<#--
+ Copyright 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.
+-->
+
+Steps to use Wear template on top of an existing sample:
+- In template-params.xml.ftl:
+ - Add the following template:
+ <template src="Wear"/>
+
+- Refresh your project (./gradlew refresh)
+- Add Wearable-specific code to Wearable directory
+- Add code to be shared among the main application and the wearable to Shared
+ directory
+
+Note that you still need the main application sample code. This is usually
+achieved by adding another template, like "base" for example.
+
+
diff --git a/wearable/wear/Geofencing/Shared/.gitignore b/wearable/wear/Geofencing/Shared/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/Geofencing/Shared/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/Geofencing/Shared/src/main/AndroidManifest.xml b/wearable/wear/Geofencing/Shared/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..2b60180
--- /dev/null
+++ b/wearable/wear/Geofencing/Shared/src/main/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.geofencing.common">
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name">
+ </application>
+
+</manifest>
diff --git a/wearable/wear/Geofencing/Shared/src/main/res/values/strings.xml b/wearable/wear/Geofencing/Shared/src/main/res/values/strings.xml
new file mode 100644
index 0000000..0f2bb90
--- /dev/null
+++ b/wearable/wear/Geofencing/Shared/src/main/res/values/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+ <string name="app_name">Shared</string>
+</resources>
diff --git a/wearable/wear/Geofencing/Wearable/.gitignore b/wearable/wear/Geofencing/Wearable/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/Geofencing/Wearable/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/Geofencing/Wearable/src/main/AndroidManifest.xml b/wearable/wear/Geofencing/Wearable/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..85c41cd
--- /dev/null
+++ b/wearable/wear/Geofencing/Wearable/src/main/AndroidManifest.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.geofencing" >
+
+ <uses-sdk android:minSdkVersion="20"
+ android:targetSdkVersion="20" />
+
+ <uses-feature android:name="android.hardware.type.watch" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:allowBackup="true">
+
+ <meta-data
+ android:name="com.google.android.gms.version"
+ android:value="@integer/google_play_services_version" />
+
+ <service
+ android:name="com.example.android.geofencing.HomeListenerService" >
+ <intent-filter>
+ <action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
+ </intent-filter>
+ </service>
+ <service android:name=".CheckInAndDeleteDataItemsService"/>
+
+ <activity android:name="android.support.wearable.activity.ConfirmationActivity"/>
+ </application>
+</manifest>
diff --git a/wearable/wear/Geofencing/Wearable/src/main/java/com/example/android/geofencing/CheckInAndDeleteDataItemsService.java b/wearable/wear/Geofencing/Wearable/src/main/java/com/example/android/geofencing/CheckInAndDeleteDataItemsService.java
new file mode 100644
index 0000000..1cc9baf
--- /dev/null
+++ b/wearable/wear/Geofencing/Wearable/src/main/java/com/example/android/geofencing/CheckInAndDeleteDataItemsService.java
@@ -0,0 +1,124 @@
+/*
+ * 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.android.geofencing;
+
+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.Wearable;
+
+import android.app.IntentService;
+import android.app.NotificationManager;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.wearable.activity.ConfirmationActivity;
+import android.util.Log;
+
+import java.util.concurrent.TimeUnit;
+
+import static com.example.android.geofencing.Constants.ACTION_CHECK_IN;
+import static com.example.android.geofencing.Constants.ACTION_DELETE_DATA_ITEM;
+import static com.example.android.geofencing.Constants.CONNECTION_TIME_OUT_MS;
+import static com.example.android.geofencing.Constants.NOTIFICATION_ID;
+import static com.example.android.geofencing.Constants.TAG;
+
+/**
+ * Handles "Check In" action on the location-based notification. Also deletes orphan DataItems
+ * when a notification is dismissed from the wearable.
+ */
+public class CheckInAndDeleteDataItemsService extends IntentService
+ implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
+
+ private GoogleApiClient mGoogleApiClient;
+
+ public CheckInAndDeleteDataItemsService() {
+ super(CheckInAndDeleteDataItemsService.class.getSimpleName());
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mGoogleApiClient = new GoogleApiClient.Builder(this)
+ .addApi(Wearable.API)
+ .addConnectionCallbacks(this)
+ .addOnConnectionFailedListener(this)
+ .build();
+ }
+
+ @Override
+ protected void onHandleIntent(Intent intent) {
+ if (ACTION_CHECK_IN.equals(intent.getAction())) {
+ // In a real app, code for checking in would go here. For this sample, we will simply
+ // display a success animation.
+ startConfirmationActivity(ConfirmationActivity.SUCCESS_ANIMATION,
+ getString(R.string.check_in_success));
+ // Dismiss the check-in notification.
+ ((NotificationManager) getSystemService(NOTIFICATION_SERVICE)).cancel(NOTIFICATION_ID);
+ } else if (!ACTION_DELETE_DATA_ITEM.equals(intent.getAction())) {
+ // The only possible actions should be checking in or dismissing the notification
+ // (which causes an intent with ACTION_DELETE_DATA_ITEM).
+ Log.e(TAG, "Unrecognized action: " + intent.getAction());
+ return;
+ }
+ // Regardless of the action, delete the DataItem (we are only be handling intents
+ // if the notification is dismissed or if the user has chosen to check in, either of which
+ // would be completed at this point).
+ mGoogleApiClient.blockingConnect(CONNECTION_TIME_OUT_MS, TimeUnit.MILLISECONDS);
+ Uri dataItemUri = intent.getData();
+ if (mGoogleApiClient.isConnected()) {
+ DataApi.DeleteDataItemsResult result = Wearable.DataApi
+ .deleteDataItems(mGoogleApiClient, dataItemUri).await();
+ if (!result.getStatus().isSuccess()) {
+ Log.e(TAG, "CheckInAndDeleteDataItemsService.onHandleIntent: "
+ + "Failed to delete dataItem: " + dataItemUri);
+ } else if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Successfully deleted data item: " + dataItemUri);
+ }
+ } else {
+ Log.e(TAG, "Failed to delete data item: " + dataItemUri
+ + " - Client disconnected from Google Play Services");
+ }
+ mGoogleApiClient.disconnect();
+ }
+
+ /**
+ * Helper method to create confirmation animations on the wearable.
+ * @param animationType Defined by constants in ConfirmationActivity.
+ * @param message The message to display with the animation.
+ */
+ private void startConfirmationActivity(int animationType, String message) {
+ Intent confirmationActivity = new Intent(this, ConfirmationActivity.class)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION)
+ .putExtra(ConfirmationActivity.EXTRA_ANIMATION_TYPE, animationType)
+ .putExtra(ConfirmationActivity.EXTRA_MESSAGE, message);
+ startActivity(confirmationActivity);
+ }
+
+ @Override
+ public void onConnected(Bundle connectionHint) {
+ }
+
+ @Override
+ public void onConnectionSuspended(int cause) {
+ }
+
+ @Override
+ public void onConnectionFailed(ConnectionResult result) {
+ }
+
+}
diff --git a/wearable/wear/Geofencing/Wearable/src/main/java/com/example/android/geofencing/Constants.java b/wearable/wear/Geofencing/Wearable/src/main/java/com/example/android/geofencing/Constants.java
new file mode 100644
index 0000000..23ee99e
--- /dev/null
+++ b/wearable/wear/Geofencing/Wearable/src/main/java/com/example/android/geofencing/Constants.java
@@ -0,0 +1,38 @@
+/*
+ * 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.android.geofencing;
+
+/** Constants used in wearable app. */
+public final class Constants {
+
+ private Constants() {
+ }
+
+ public static final String TAG = "ExampleGeofencingApp";
+
+ // Timeout for making a connection to GoogleApiClient (in milliseconds).
+ public static final long CONNECTION_TIME_OUT_MS = 100;
+
+ public static final int NOTIFICATION_ID = 1;
+ public static final String ANDROID_BUILDING_ID = "1";
+ public static final String YERBA_BUENA_ID = "2";
+
+ public static final String ACTION_CHECK_IN = "check_in";
+ public static final String ACTION_DELETE_DATA_ITEM = "delete_data_item";
+ public static final String KEY_GEOFENCE_ID = "geofence_id";
+
+}
diff --git a/wearable/wear/Geofencing/Wearable/src/main/java/com/example/android/geofencing/HomeListenerService.java b/wearable/wear/Geofencing/Wearable/src/main/java/com/example/android/geofencing/HomeListenerService.java
new file mode 100644
index 0000000..b0b1b13
--- /dev/null
+++ b/wearable/wear/Geofencing/Wearable/src/main/java/com/example/android/geofencing/HomeListenerService.java
@@ -0,0 +1,152 @@
+/*
+ * 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.android.geofencing;
+
+import static com.example.android.geofencing.Constants.ACTION_CHECK_IN;
+import static com.example.android.geofencing.Constants.ACTION_DELETE_DATA_ITEM;
+import static com.example.android.geofencing.Constants.ANDROID_BUILDING_ID;
+import static com.example.android.geofencing.Constants.KEY_GEOFENCE_ID;
+import static com.example.android.geofencing.Constants.NOTIFICATION_ID;
+import static com.example.android.geofencing.Constants.TAG;
+import static com.example.android.geofencing.Constants.YERBA_BUENA_ID;
+
+import android.app.Notification;
+import android.app.Notification.Action;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.style.RelativeSizeSpan;
+import android.util.Log;
+
+import com.google.android.gms.common.api.GoogleApiClient;
+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.Wearable;
+import com.google.android.gms.wearable.WearableListenerService;
+
+/**
+ * Listens to DataItem events on the wearable device.
+ */
+public class HomeListenerService extends WearableListenerService {
+
+ private GoogleApiClient mGoogleApiClient;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mGoogleApiClient = new GoogleApiClient.Builder(this.getApplicationContext())
+ .addApi(Wearable.API)
+ .build();
+ mGoogleApiClient.connect();
+ }
+
+ /**
+ * Listen for DataItems added/deleted from the geofence service running on the companion.
+ */
+ @Override
+ public void onDataChanged(DataEventBuffer dataEvents) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "onDataChanged: " + dataEvents + " for " + getPackageName());
+ }
+ for (DataEvent event : dataEvents) {
+ if (event.getType() == DataEvent.TYPE_DELETED) {
+ cancelNotificationForDataItem(event.getDataItem());
+ } else if (event.getType() == DataEvent.TYPE_CHANGED) {
+ // The user has entered a geofence - post a notification!
+ String geofenceId = DataMap.fromByteArray(event.getDataItem().getData())
+ .getString(KEY_GEOFENCE_ID);
+ postNotificationForGeofenceId(geofenceId, event.getDataItem().getUri());
+ }
+ }
+ dataEvents.close();
+ }
+
+ /**
+ * Deletes the check-in notification when the DataItem is deleted.
+ * @param dataItem Used only for logging in this sample, but could be used to identify which
+ * notification to cancel (in this case, there is at most 1 notification).
+ */
+ private void cancelNotificationForDataItem(DataItem dataItem) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "onDataItemDeleted:DataItem=" + dataItem.getUri());
+ }
+ ((NotificationManager) getSystemService(NOTIFICATION_SERVICE)).cancel(NOTIFICATION_ID);
+ }
+
+ /**
+ * Posts a local notification for the given geofence id, with an option to check in.
+ * @param geofenceId The geofence id that the user has triggered.
+ * @param dataItemUri The Uri for the DataItem that triggered this notification. Used to delete
+ * this DataItem when the notification is dismissed.
+ */
+ private void postNotificationForGeofenceId(String geofenceId, Uri dataItemUri) {
+ // Use the geofenceId to determine the title and background of the check-in notification.
+ // A SpannableString is used for the notification title for resizing capabilities.
+ SpannableString checkInTitle;
+ Bitmap notificationBackground;
+ if (ANDROID_BUILDING_ID.equals(geofenceId)) {
+ checkInTitle = new SpannableString(getText(R.string.android_building_title));
+ notificationBackground =
+ BitmapFactory.decodeResource(getResources(), R.drawable.android_building);
+ } else if (YERBA_BUENA_ID.equals(geofenceId)) {
+ checkInTitle = new SpannableString(getText(R.string.yerba_buena_title));
+ notificationBackground =
+ BitmapFactory.decodeResource(getResources(), R.drawable.yerba_buena);
+ } else {
+ Log.e(TAG, "Unrecognized geofence id: " + geofenceId);
+ return;
+ }
+ // Resize the title to avoid truncation.
+ checkInTitle.setSpan(new RelativeSizeSpan(0.8f), 0, checkInTitle.length(),
+ Spannable.SPAN_POINT_MARK);
+
+ Intent checkInOperation =
+ new Intent(this, CheckInAndDeleteDataItemsService.class).setData(dataItemUri);
+ PendingIntent checkInIntent = PendingIntent.getService(this, 0,
+ checkInOperation.setAction(ACTION_CHECK_IN), PendingIntent.FLAG_CANCEL_CURRENT);
+ PendingIntent deleteDataItemIntent = PendingIntent.getService(this, 1,
+ checkInOperation.setAction(ACTION_DELETE_DATA_ITEM),
+ PendingIntent.FLAG_CANCEL_CURRENT);
+ // This action will be embedded into the notification.
+ Action checkInAction = new Action(R.drawable.ic_action_check_in,
+ getText(R.string.check_in_prompt), checkInIntent);
+
+ Notification notification = new Notification.Builder(this)
+ .setContentTitle(checkInTitle)
+ .setContentText(getText(R.string.check_in_prompt))
+ .setSmallIcon(R.drawable.ic_launcher)
+ .setDeleteIntent(deleteDataItemIntent)
+ .extend(new Notification.WearableExtender()
+ .setBackground(notificationBackground)
+ .addAction(checkInAction)
+ .setContentAction(0)
+ .setHintHideIcon(true))
+ .setLocalOnly(true)
+ .build();
+
+ ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
+ .notify(NOTIFICATION_ID, notification);
+ }
+
+}
diff --git a/wearable/wear/Geofencing/Wearable/src/main/res/drawable-hdpi/ic_action_check_in.png b/wearable/wear/Geofencing/Wearable/src/main/res/drawable-hdpi/ic_action_check_in.png
new file mode 100644
index 0000000..f94a1c4
--- /dev/null
+++ b/wearable/wear/Geofencing/Wearable/src/main/res/drawable-hdpi/ic_action_check_in.png
Binary files differ
diff --git a/wearable/wear/Geofencing/Wearable/src/main/res/drawable-hdpi/ic_launcher.png b/wearable/wear/Geofencing/Wearable/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..4e3e000
--- /dev/null
+++ b/wearable/wear/Geofencing/Wearable/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Geofencing/Wearable/src/main/res/drawable-mdpi/ic_launcher.png b/wearable/wear/Geofencing/Wearable/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..b405cb2
--- /dev/null
+++ b/wearable/wear/Geofencing/Wearable/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Geofencing/Wearable/src/main/res/drawable-nodpi/android_building.png b/wearable/wear/Geofencing/Wearable/src/main/res/drawable-nodpi/android_building.png
new file mode 100644
index 0000000..2a28bd4
--- /dev/null
+++ b/wearable/wear/Geofencing/Wearable/src/main/res/drawable-nodpi/android_building.png
Binary files differ
diff --git a/wearable/wear/Geofencing/Wearable/src/main/res/drawable-nodpi/yerba_buena.png b/wearable/wear/Geofencing/Wearable/src/main/res/drawable-nodpi/yerba_buena.png
new file mode 100644
index 0000000..04f39f8
--- /dev/null
+++ b/wearable/wear/Geofencing/Wearable/src/main/res/drawable-nodpi/yerba_buena.png
Binary files differ
diff --git a/wearable/wear/Geofencing/Wearable/src/main/res/drawable-xhdpi/ic_launcher.png b/wearable/wear/Geofencing/Wearable/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..61f9d88
--- /dev/null
+++ b/wearable/wear/Geofencing/Wearable/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Geofencing/Wearable/src/main/res/drawable-xxhdpi/ic_launcher.png b/wearable/wear/Geofencing/Wearable/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..81c1008
--- /dev/null
+++ b/wearable/wear/Geofencing/Wearable/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Geofencing/Wearable/src/main/res/values/strings.xml b/wearable/wear/Geofencing/Wearable/src/main/res/values/strings.xml
new file mode 100644
index 0000000..49fb2b3
--- /dev/null
+++ b/wearable/wear/Geofencing/Wearable/src/main/res/values/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name">Android Wear Geofencing Example Application</string>
+ <string name="android_building_title">Android Building</string>
+ <string name="yerba_buena_title">Yerba Buena Gardens</string>
+ <string name="check_in_prompt">Check in here?</string>
+ <string name="check_in_success">Checked In</string>
+</resources>
diff --git a/wearable/wear/Geofencing/build.gradle b/wearable/wear/Geofencing/build.gradle
new file mode 100644
index 0000000..be1fa82
--- /dev/null
+++ b/wearable/wear/Geofencing/build.gradle
@@ -0,0 +1,14 @@
+
+
+
+
+// BEGIN_EXCLUDE
+import com.example.android.samples.build.SampleGenPlugin
+apply plugin: SampleGenPlugin
+
+samplegen {
+ pathToBuild "../../../../../build"
+ pathToSamplesCommon "../../../common"
+}
+apply from: "../../../../../build/build.gradle"
+// END_EXCLUDE
diff --git a/wearable/wear/Geofencing/buildSrc/build.gradle b/wearable/wear/Geofencing/buildSrc/build.gradle
new file mode 100644
index 0000000..e344a8c
--- /dev/null
+++ b/wearable/wear/Geofencing/buildSrc/build.gradle
@@ -0,0 +1,18 @@
+
+
+
+repositories {
+ mavenCentral()
+}
+dependencies {
+ compile 'org.freemarker:freemarker:2.3.20'
+}
+
+sourceSets {
+ main {
+ groovy {
+ srcDir new File(rootDir, "../../../../../../build/buildSrc/src/main/groovy")
+ }
+ }
+}
+
diff --git a/wearable/wear/Geofencing/gradle/wrapper/gradle-wrapper.jar b/wearable/wear/Geofencing/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8c0fb64
--- /dev/null
+++ b/wearable/wear/Geofencing/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/wearable/wear/Geofencing/gradle/wrapper/gradle-wrapper.properties b/wearable/wear/Geofencing/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..d7f03cf
--- /dev/null
+++ b/wearable/wear/Geofencing/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=http\://services.gradle.org/distributions/gradle-1.12-bin.zip
diff --git a/wearable/wear/Geofencing/gradlew b/wearable/wear/Geofencing/gradlew
new file mode 100755
index 0000000..91a7e26
--- /dev/null
+++ b/wearable/wear/Geofencing/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/wearable/wear/Geofencing/gradlew.bat b/wearable/wear/Geofencing/gradlew.bat
new file mode 100644
index 0000000..8a0b282
--- /dev/null
+++ b/wearable/wear/Geofencing/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/wearable/wear/Geofencing/settings.gradle b/wearable/wear/Geofencing/settings.gradle
new file mode 100644
index 0000000..8522c57
--- /dev/null
+++ b/wearable/wear/Geofencing/settings.gradle
@@ -0,0 +1 @@
+include ':Application', ':Wearable', ':Shared'
diff --git a/wearable/wear/Geofencing/template-params.xml b/wearable/wear/Geofencing/template-params.xml
new file mode 100644
index 0000000..f4db505
--- /dev/null
+++ b/wearable/wear/Geofencing/template-params.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+
+
+<sample>
+ <name>Geofencing</name>
+ <group>Connectivity</group>
+ <package>com.example.android.geofencing</package>
+
+
+
+ <!-- change minSdk if needed-->
+ <minSdk>20</minSdk>
+
+
+ <strings>
+ <intro>
+ <![CDATA[
+ When a user enters the vicinity of the Android building (B44) or the Yerba Buena
+ Gardens near the Moscone center in San Francisco, a notification silently appears on his/her
+ wearable with an option to check in. This notification automatically disappears when he/she leaves
+ the area, and reappears the next time he/she is at one of these locations.
+ ]]>
+ </intro>
+ </strings>
+
+ <template src="base"/>
+ <template src="Wear"/>
+ <common src="logger"/>
+ <common src="activities"/>
+
+</sample>
diff --git a/wearable/wear/GridViewPager/Application/.gitignore b/wearable/wear/GridViewPager/Application/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/GridViewPager/Application/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/GridViewPager/Application/proguard-project.txt b/wearable/wear/GridViewPager/Application/proguard-project.txt
new file mode 100644
index 0000000..0d8f171
--- /dev/null
+++ b/wearable/wear/GridViewPager/Application/proguard-project.txt
@@ -0,0 +1,20 @@
+ To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# 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/wearable/wear/GridViewPager/Application/src/main/AndroidManifest.xml b/wearable/wear/GridViewPager/Application/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..eaa91d7
--- /dev/null
+++ b/wearable/wear/GridViewPager/Application/src/main/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.gridviewpager">
+
+ <uses-sdk android:minSdkVersion="19"
+ android:targetSdkVersion="19" />
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name">
+ </application>
+
+</manifest>
+
diff --git a/wearable/wear/GridViewPager/CONTRIB.md b/wearable/wear/GridViewPager/CONTRIB.md
new file mode 100644
index 0000000..14a4fcf
--- /dev/null
+++ b/wearable/wear/GridViewPager/CONTRIB.md
@@ -0,0 +1,35 @@
+# How to become a contributor and submit your own code
+
+## Contributor License Agreements
+
+We'd love to accept your sample apps and patches! Before we can take them, we
+have to jump a couple of legal hurdles.
+
+Please fill out either the individual or corporate Contributor License Agreement (CLA).
+
+ * If you are an individual writing original source code and you're sure you
+ own the intellectual property, then you'll need to sign an [individual CLA]
+ (https://developers.google.com/open-source/cla/individual).
+ * If you work for a company that wants to allow you to contribute your work,
+ then you'll need to sign a [corporate CLA]
+ (https://developers.google.com/open-source/cla/corporate).
+
+Follow either of the two links above to access the appropriate CLA and
+instructions for how to sign and return it. Once we receive it, we'll be able to
+accept your pull requests.
+
+## Contributing A Patch
+
+1. Submit an issue describing your proposed change to the repo in question.
+1. The repo owner will respond to your issue promptly.
+1. If your proposed change is accepted, and you haven't already done so, sign a
+ Contributor License Agreement (see details above).
+1. Fork the desired repo, develop and test your code changes.
+1. Ensure that your code adheres to the existing style in the sample to which
+ you are contributing. Refer to the
+ [Android Code Style Guide]
+ (https://source.android.com/source/code-style.html) for the
+ recommended coding standards for this organization.
+1. Ensure that your code has an appropriate set of unit tests which all pass.
+1. Submit a pull request.
+
diff --git a/wearable/wear/GridViewPager/LICENSE b/wearable/wear/GridViewPager/LICENSE
new file mode 100644
index 0000000..1af981f
--- /dev/null
+++ b/wearable/wear/GridViewPager/LICENSE
@@ -0,0 +1,201 @@
+ 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 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/wearable/wear/GridViewPager/README-wear.txt b/wearable/wear/GridViewPager/README-wear.txt
new file mode 100644
index 0000000..17523d7
--- /dev/null
+++ b/wearable/wear/GridViewPager/README-wear.txt
@@ -0,0 +1,30 @@
+<#--
+ Copyright 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.
+-->
+
+Steps to use Wear template on top of an existing sample:
+- In template-params.xml.ftl:
+ - Add the following template:
+ <template src="Wear"/>
+
+- Refresh your project (./gradlew refresh)
+- Add Wearable-specific code to Wearable directory
+- Add code to be shared among the main application and the wearable to Shared
+ directory
+
+Note that you still need the main application sample code. This is usually
+achieved by adding another template, like "base" for example.
+
+
diff --git a/wearable/wear/GridViewPager/Shared/.gitignore b/wearable/wear/GridViewPager/Shared/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/GridViewPager/Shared/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/GridViewPager/Shared/src/main/AndroidManifest.xml b/wearable/wear/GridViewPager/Shared/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..1be08aa
--- /dev/null
+++ b/wearable/wear/GridViewPager/Shared/src/main/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.gridviewpager.common">
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name">
+ </application>
+
+</manifest>
diff --git a/wearable/wear/GridViewPager/Shared/src/main/res/values/strings.xml b/wearable/wear/GridViewPager/Shared/src/main/res/values/strings.xml
new file mode 100644
index 0000000..0f2bb90
--- /dev/null
+++ b/wearable/wear/GridViewPager/Shared/src/main/res/values/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+ <string name="app_name">Shared</string>
+</resources>
diff --git a/wearable/wear/GridViewPager/Wearable/.gitignore b/wearable/wear/GridViewPager/Wearable/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/AndroidManifest.xml b/wearable/wear/GridViewPager/Wearable/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..baadee2
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.gridviewpager" >
+
+ <uses-sdk android:minSdkVersion="20"
+ android:targetSdkVersion="20" />
+
+ <uses-feature android:name="android.hardware.type.watch" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@android:style/Theme.DeviceDefault.Light" >
+ <activity
+ android:name="com.example.android.gridviewpager.MainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/java/com/example/android/gridviewpager/MainActivity.java b/wearable/wear/GridViewPager/Wearable/src/main/java/com/example/android/gridviewpager/MainActivity.java
new file mode 100644
index 0000000..9a7de92
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/java/com/example/android/gridviewpager/MainActivity.java
@@ -0,0 +1,51 @@
+/*
+ * 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.android.gridviewpager;
+
+import android.app.Activity;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.support.wearable.view.GridViewPager;
+import android.view.View;
+import android.view.View.OnApplyWindowInsetsListener;
+import android.view.WindowInsets;
+
+public class MainActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ final Resources res = getResources();
+ final GridViewPager pager = (GridViewPager) findViewById(R.id.pager);
+ pager.setOnApplyWindowInsetsListener(new OnApplyWindowInsetsListener() {
+ @Override
+ public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
+ // Adjust page margins:
+ // A little extra horizontal spacing between pages looks a bit
+ // less crowded on a round display.
+ final boolean round = insets.isRound();
+ int rowMargin = res.getDimensionPixelOffset(R.dimen.page_row_margin);
+ int colMargin = res.getDimensionPixelOffset(round ?
+ R.dimen.page_column_margin_round : R.dimen.page_column_margin);
+ pager.setPageMargins(rowMargin, colMargin);
+ return insets;
+ }
+ });
+ pager.setAdapter(new SampleGridPagerAdapter(this, getFragmentManager()));
+ }
+}
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/java/com/example/android/gridviewpager/SampleGridPagerAdapter.java b/wearable/wear/GridViewPager/Wearable/src/main/java/com/example/android/gridviewpager/SampleGridPagerAdapter.java
new file mode 100644
index 0000000..c9dde07
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/java/com/example/android/gridviewpager/SampleGridPagerAdapter.java
@@ -0,0 +1,134 @@
+/*
+ * 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.android.gridviewpager;
+
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.content.Context;
+import android.support.wearable.view.CardFragment;
+import android.support.wearable.view.FragmentGridPagerAdapter;
+import android.support.wearable.view.ImageReference;
+import android.view.Gravity;
+
+/**
+ * Constructs fragments as requested by the GridViewPager. For each row a
+ * different background is provided.
+ */
+public class SampleGridPagerAdapter extends FragmentGridPagerAdapter {
+
+ private final Context mContext;
+
+ public SampleGridPagerAdapter(Context ctx, FragmentManager fm) {
+ super(fm);
+ mContext = ctx;
+ }
+
+ static final int[] BG_IMAGES = new int[] {
+ R.drawable.debug_background_1,
+ R.drawable.debug_background_2,
+ R.drawable.debug_background_3,
+ R.drawable.debug_background_4,
+ R.drawable.debug_background_5
+ };
+
+ /** A simple container for static data in each page */
+ private static class Page {
+ int titleRes;
+ int textRes;
+ int iconRes;
+ int cardGravity = Gravity.BOTTOM;
+ boolean expansionEnabled = true;
+ float expansionFactor = 1.0f;
+ int expansionDirection = CardFragment.EXPAND_DOWN;
+
+ public Page(int titleRes, int textRes, boolean expansion) {
+ this(titleRes, textRes, 0);
+ this.expansionEnabled = expansion;
+ }
+
+ public Page(int titleRes, int textRes, boolean expansion, float expansionFactor) {
+ this(titleRes, textRes, 0);
+ this.expansionEnabled = expansion;
+ this.expansionFactor = expansionFactor;
+ }
+
+ public Page(int titleRes, int textRes, int iconRes) {
+ this.titleRes = titleRes;
+ this.textRes = textRes;
+ this.iconRes = iconRes;
+ }
+
+ public Page(int titleRes, int textRes, int iconRes, int gravity) {
+ this.titleRes = titleRes;
+ this.textRes = textRes;
+ this.iconRes = iconRes;
+ this.cardGravity = gravity;
+ }
+ }
+
+ private final Page[][] PAGES = {
+ {
+ new Page(R.string.welcome_title, R.string.welcome_text, R.drawable.bugdroid,
+ Gravity.CENTER_VERTICAL),
+ },
+ {
+ new Page(R.string.about_title, R.string.about_text, false),
+ },
+ {
+ new Page(R.string.cards_title, R.string.cards_text, true, 2),
+ new Page(R.string.expansion_title, R.string.expansion_text, true, 10),
+ },
+ {
+ new Page(R.string.backgrounds_title, R.string.backgrounds_text, true, 2),
+ new Page(R.string.columns_title, R.string.columns_text, true, 2)
+ },
+ {
+ new Page(R.string.dismiss_title, R.string.dismiss_text, R.drawable.bugdroid,
+ Gravity.CENTER_VERTICAL),
+ },
+
+ };
+
+ @Override
+ public Fragment getFragment(int row, int col) {
+ Page page = PAGES[row][col];
+ String title = page.titleRes != 0 ? mContext.getString(page.titleRes) : null;
+ String text = page.textRes != 0 ? mContext.getString(page.textRes) : null;
+ CardFragment fragment = CardFragment.create(title, text, page.iconRes);
+ // Advanced settings
+ fragment.setCardGravity(page.cardGravity);
+ fragment.setExpansionEnabled(page.expansionEnabled);
+ fragment.setExpansionDirection(page.expansionDirection);
+ fragment.setExpansionFactor(page.expansionFactor);
+ return fragment;
+ }
+
+ @Override
+ public ImageReference getBackground(int row, int column) {
+ return ImageReference.forDrawable(BG_IMAGES[row % BG_IMAGES.length]);
+ }
+
+ @Override
+ public int getRowCount() {
+ return PAGES.length;
+ }
+
+ @Override
+ public int getColumnCount(int rowNum) {
+ return PAGES[rowNum].length;
+ }
+}
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-hdpi/bugdroid.png b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-hdpi/bugdroid.png
new file mode 100644
index 0000000..7cbe661
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-hdpi/bugdroid.png
Binary files differ
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-hdpi/ic_launcher.png b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..589f229
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-hdpi/ic_swipe_arrow_left.png b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-hdpi/ic_swipe_arrow_left.png
new file mode 100644
index 0000000..88a497f
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-hdpi/ic_swipe_arrow_left.png
Binary files differ
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-hdpi/ic_swipe_arrow_right.png b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-hdpi/ic_swipe_arrow_right.png
new file mode 100644
index 0000000..5bf0e47
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-hdpi/ic_swipe_arrow_right.png
Binary files differ
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-hdpi/ic_swipe_arrow_up.png b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-hdpi/ic_swipe_arrow_up.png
new file mode 100644
index 0000000..9a3256a
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-hdpi/ic_swipe_arrow_up.png
Binary files differ
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-mdpi/bugdroid.png b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-mdpi/bugdroid.png
new file mode 100644
index 0000000..8bf7596
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-mdpi/bugdroid.png
Binary files differ
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-mdpi/ic_launcher.png b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..77dd571
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-mdpi/ic_swipe_arrow_left.png b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-mdpi/ic_swipe_arrow_left.png
new file mode 100644
index 0000000..ba36d9d
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-mdpi/ic_swipe_arrow_left.png
Binary files differ
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-mdpi/ic_swipe_arrow_right.png b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-mdpi/ic_swipe_arrow_right.png
new file mode 100644
index 0000000..e5930ac
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-mdpi/ic_swipe_arrow_right.png
Binary files differ
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-mdpi/ic_swipe_arrow_up.png b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-mdpi/ic_swipe_arrow_up.png
new file mode 100644
index 0000000..5ded1c3
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-mdpi/ic_swipe_arrow_up.png
Binary files differ
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-xhdpi/ic_launcher.png b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..fe34ebe
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-xhdpi/ic_swipe_arrow_left.png b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-xhdpi/ic_swipe_arrow_left.png
new file mode 100644
index 0000000..f02901b
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-xhdpi/ic_swipe_arrow_left.png
Binary files differ
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-xhdpi/ic_swipe_arrow_right.png b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-xhdpi/ic_swipe_arrow_right.png
new file mode 100644
index 0000000..154a87e
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-xhdpi/ic_swipe_arrow_right.png
Binary files differ
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-xhdpi/ic_swipe_arrow_up.png b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-xhdpi/ic_swipe_arrow_up.png
new file mode 100644
index 0000000..e99d982
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-xhdpi/ic_swipe_arrow_up.png
Binary files differ
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-xxhdpi/ic_launcher.png b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100755
index 0000000..ab80bcd
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/drawable/debug_background_1.png b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable/debug_background_1.png
new file mode 100644
index 0000000..7e6437b
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable/debug_background_1.png
Binary files differ
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/drawable/debug_background_2.png b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable/debug_background_2.png
new file mode 100644
index 0000000..4fdc5c9
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable/debug_background_2.png
Binary files differ
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/drawable/debug_background_3.png b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable/debug_background_3.png
new file mode 100644
index 0000000..20faf46
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable/debug_background_3.png
Binary files differ
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/drawable/debug_background_4.png b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable/debug_background_4.png
new file mode 100644
index 0000000..1fd25c6
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable/debug_background_4.png
Binary files differ
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/drawable/debug_background_5.png b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable/debug_background_5.png
new file mode 100644
index 0000000..eecdb2c
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable/debug_background_5.png
Binary files differ
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/layout/activity_main.xml b/wearable/wear/GridViewPager/Wearable/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..abc3b30
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/layout/activity_main.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<android.support.wearable.view.GridViewPager
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/pager"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:keepScreenOn="true" />
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/values/dimens.xml b/wearable/wear/GridViewPager/Wearable/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..47ab217
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/values/dimens.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+ <dimen name="page_row_margin">100dp</dimen>
+ <dimen name="page_column_margin">10dp</dimen>
+ <dimen name="page_column_margin_round">50dp</dimen>
+</resources>
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/values/strings.xml b/wearable/wear/GridViewPager/Wearable/src/main/res/values/strings.xml
new file mode 100644
index 0000000..404119b
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/values/strings.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+
+ <string name="app_name">GridViewPager Sample</string>
+ <string name="welcome_title">GridViewPager</string>
+ <string name="welcome_text">Welcome!</string>
+
+ <string name="about_title">About</string>
+ <string name="about_text">Content is organized into multiple pages. Swipe
+ between cards to view other content.</string>
+
+ <string name="cards_title">Cards</string>
+ <string name="cards_text">Each page is created using a CardFragment. A
+ layout is placed inside the card and the rest is handled
+ automatically.</string>
+
+ <string name="expansion_title">Expansion</string>
+ <string name="expansion_text">By default, each card will grow taller to
+ accommodate extra content. Tall cards can be scrolled through
+ like any scrollable view. The maximum height is controlled by
+ setExpansionFactor() with a default of 10 pages. After that
+ you\'ll notice a faded edge to indicate there is more. Expansion
+ can be disabled completely using setExpansionEnabled(false).
+ With this, the content will be clipped if it\'s taller than one
+ page.</string>
+
+ <string name="backgrounds_title">Backgrounds</string>
+ <string name="backgrounds_text">Backgrounds are supplied by the adapter\'s
+ getBackground method. Parallax and crossfade effects are applied
+ automatically.</string>
+
+ <string name="columns_title">Columns</string>
+ <string name="columns_text">When moving between rows, the pager always
+ returns to column 0. This is adjustable in the adapter. See
+ method getCurrentColumnForRow().</string>
+
+ <string name="dismiss_title">Dismiss</string>
+ <string name="dismiss_text">To exit the application, swipe from left to
+ right.</string>
+
+</resources>
diff --git a/wearable/wear/GridViewPager/build.gradle b/wearable/wear/GridViewPager/build.gradle
new file mode 100644
index 0000000..be1fa82
--- /dev/null
+++ b/wearable/wear/GridViewPager/build.gradle
@@ -0,0 +1,14 @@
+
+
+
+
+// BEGIN_EXCLUDE
+import com.example.android.samples.build.SampleGenPlugin
+apply plugin: SampleGenPlugin
+
+samplegen {
+ pathToBuild "../../../../../build"
+ pathToSamplesCommon "../../../common"
+}
+apply from: "../../../../../build/build.gradle"
+// END_EXCLUDE
diff --git a/wearable/wear/GridViewPager/buildSrc/build.gradle b/wearable/wear/GridViewPager/buildSrc/build.gradle
new file mode 100644
index 0000000..e344a8c
--- /dev/null
+++ b/wearable/wear/GridViewPager/buildSrc/build.gradle
@@ -0,0 +1,18 @@
+
+
+
+repositories {
+ mavenCentral()
+}
+dependencies {
+ compile 'org.freemarker:freemarker:2.3.20'
+}
+
+sourceSets {
+ main {
+ groovy {
+ srcDir new File(rootDir, "../../../../../../build/buildSrc/src/main/groovy")
+ }
+ }
+}
+
diff --git a/wearable/wear/GridViewPager/gradle/wrapper/gradle-wrapper.jar b/wearable/wear/GridViewPager/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8c0fb64
--- /dev/null
+++ b/wearable/wear/GridViewPager/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/wearable/wear/GridViewPager/gradle/wrapper/gradle-wrapper.properties b/wearable/wear/GridViewPager/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..d7f03cf
--- /dev/null
+++ b/wearable/wear/GridViewPager/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=http\://services.gradle.org/distributions/gradle-1.12-bin.zip
diff --git a/wearable/wear/GridViewPager/gradlew b/wearable/wear/GridViewPager/gradlew
new file mode 100755
index 0000000..91a7e26
--- /dev/null
+++ b/wearable/wear/GridViewPager/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/wearable/wear/GridViewPager/gradlew.bat b/wearable/wear/GridViewPager/gradlew.bat
new file mode 100644
index 0000000..8a0b282
--- /dev/null
+++ b/wearable/wear/GridViewPager/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/wearable/wear/GridViewPager/settings.gradle b/wearable/wear/GridViewPager/settings.gradle
new file mode 100644
index 0000000..8522c57
--- /dev/null
+++ b/wearable/wear/GridViewPager/settings.gradle
@@ -0,0 +1 @@
+include ':Application', ':Wearable', ':Shared'
diff --git a/wearable/wear/GridViewPager/template-params.xml b/wearable/wear/GridViewPager/template-params.xml
new file mode 100644
index 0000000..ca8043f
--- /dev/null
+++ b/wearable/wear/GridViewPager/template-params.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+
+
+<sample>
+ <name>GridViewPager</name>
+ <group>Connectivity</group>
+ <package>com.example.android.gridviewpager</package>
+
+
+
+ <!-- change minSdk if needed-->
+ <minSdk>20</minSdk>
+
+
+ <strings>
+ <intro>
+ <![CDATA[
+ Demonstrates how to implement a GridViewPager in your wearable app.
+ ]]>
+ </intro>
+ </strings>
+
+ <template src="base"/>
+ <template src="Wear"/>
+ <common src="logger"/>
+ <common src="activities"/>
+
+</sample>
diff --git a/wearable/wear/JumpingJack/Application/.gitignore b/wearable/wear/JumpingJack/Application/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/JumpingJack/Application/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/JumpingJack/Application/proguard-project.txt b/wearable/wear/JumpingJack/Application/proguard-project.txt
new file mode 100644
index 0000000..0d8f171
--- /dev/null
+++ b/wearable/wear/JumpingJack/Application/proguard-project.txt
@@ -0,0 +1,20 @@
+ To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# 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/wearable/wear/JumpingJack/Application/src/main/AndroidManifest.xml b/wearable/wear/JumpingJack/Application/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..652f895
--- /dev/null
+++ b/wearable/wear/JumpingJack/Application/src/main/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.jumpingjack">
+
+ <uses-sdk android:minSdkVersion="19"
+ android:targetSdkVersion="19" />
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name">
+ </application>
+
+</manifest>
+
diff --git a/wearable/wear/JumpingJack/CONTRIB.md b/wearable/wear/JumpingJack/CONTRIB.md
new file mode 100644
index 0000000..14a4fcf
--- /dev/null
+++ b/wearable/wear/JumpingJack/CONTRIB.md
@@ -0,0 +1,35 @@
+# How to become a contributor and submit your own code
+
+## Contributor License Agreements
+
+We'd love to accept your sample apps and patches! Before we can take them, we
+have to jump a couple of legal hurdles.
+
+Please fill out either the individual or corporate Contributor License Agreement (CLA).
+
+ * If you are an individual writing original source code and you're sure you
+ own the intellectual property, then you'll need to sign an [individual CLA]
+ (https://developers.google.com/open-source/cla/individual).
+ * If you work for a company that wants to allow you to contribute your work,
+ then you'll need to sign a [corporate CLA]
+ (https://developers.google.com/open-source/cla/corporate).
+
+Follow either of the two links above to access the appropriate CLA and
+instructions for how to sign and return it. Once we receive it, we'll be able to
+accept your pull requests.
+
+## Contributing A Patch
+
+1. Submit an issue describing your proposed change to the repo in question.
+1. The repo owner will respond to your issue promptly.
+1. If your proposed change is accepted, and you haven't already done so, sign a
+ Contributor License Agreement (see details above).
+1. Fork the desired repo, develop and test your code changes.
+1. Ensure that your code adheres to the existing style in the sample to which
+ you are contributing. Refer to the
+ [Android Code Style Guide]
+ (https://source.android.com/source/code-style.html) for the
+ recommended coding standards for this organization.
+1. Ensure that your code has an appropriate set of unit tests which all pass.
+1. Submit a pull request.
+
diff --git a/wearable/wear/JumpingJack/LICENSE b/wearable/wear/JumpingJack/LICENSE
new file mode 100644
index 0000000..1af981f
--- /dev/null
+++ b/wearable/wear/JumpingJack/LICENSE
@@ -0,0 +1,201 @@
+ 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 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/wearable/wear/JumpingJack/README-wear.txt b/wearable/wear/JumpingJack/README-wear.txt
new file mode 100644
index 0000000..17523d7
--- /dev/null
+++ b/wearable/wear/JumpingJack/README-wear.txt
@@ -0,0 +1,30 @@
+<#--
+ Copyright 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.
+-->
+
+Steps to use Wear template on top of an existing sample:
+- In template-params.xml.ftl:
+ - Add the following template:
+ <template src="Wear"/>
+
+- Refresh your project (./gradlew refresh)
+- Add Wearable-specific code to Wearable directory
+- Add code to be shared among the main application and the wearable to Shared
+ directory
+
+Note that you still need the main application sample code. This is usually
+achieved by adding another template, like "base" for example.
+
+
diff --git a/wearable/wear/JumpingJack/Shared/.gitignore b/wearable/wear/JumpingJack/Shared/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/JumpingJack/Shared/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/JumpingJack/Shared/src/main/AndroidManifest.xml b/wearable/wear/JumpingJack/Shared/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..7ba3326
--- /dev/null
+++ b/wearable/wear/JumpingJack/Shared/src/main/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.jumpingjack.common">
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name">
+ </application>
+
+</manifest>
diff --git a/wearable/wear/JumpingJack/Shared/src/main/res/values/strings.xml b/wearable/wear/JumpingJack/Shared/src/main/res/values/strings.xml
new file mode 100644
index 0000000..0f2bb90
--- /dev/null
+++ b/wearable/wear/JumpingJack/Shared/src/main/res/values/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+ <string name="app_name">Shared</string>
+</resources>
diff --git a/wearable/wear/JumpingJack/Wearable/.gitignore b/wearable/wear/JumpingJack/Wearable/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/JumpingJack/Wearable/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/JumpingJack/Wearable/src/main/AndroidManifest.xml b/wearable/wear/JumpingJack/Wearable/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..e0448d9
--- /dev/null
+++ b/wearable/wear/JumpingJack/Wearable/src/main/AndroidManifest.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.jumpingjack">
+
+ <uses-sdk android:minSdkVersion="20"
+ android:targetSdkVersion="20" />
+
+ <uses-feature android:name="android.hardware.type.watch" />
+
+ <uses-permission android:name="android.permission.VIBRATE"/>
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@android:style/Theme.DeviceDefault.Light">
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/wearable/wear/JumpingJack/Wearable/src/main/java/com/example/android/jumpingjack/MainActivity.java b/wearable/wear/JumpingJack/Wearable/src/main/java/com/example/android/jumpingjack/MainActivity.java
new file mode 100644
index 0000000..4fe2e79
--- /dev/null
+++ b/wearable/wear/JumpingJack/Wearable/src/main/java/com/example/android/jumpingjack/MainActivity.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2014 Google Inc. All Rights Reserved.
+ *
+ * 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.android.jumpingjack;
+
+import com.example.android.jumpingjack.fragments.CounterFragment;
+import com.example.android.jumpingjack.fragments.SettingsFragment;
+
+import android.app.Activity;
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.v4.view.ViewPager;
+import android.util.Log;
+import android.view.WindowManager;
+import android.widget.ImageView;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+/**
+ * The main activity for the Jumping Jack application. This activity registers itself to receive
+ * sensor values. Since on wearable devices a full screen activity is very short-lived, we set the
+ * FLAG_KEEP_SCREEN_ON to give user adequate time for taking actions but since we don't want to
+ * keep screen on for an extended period of time, there is a SCREEN_ON_TIMEOUT_MS that is enforced
+ * if no interaction is discovered.
+ *
+ * This activity includes a {@link android.support.v4.view.ViewPager} with two pages, one that
+ * shows the current count and one that allows user to reset the counter. the current value of the
+ * counter is persisted so that upon re-launch, the counter picks up from the last value. At any
+ * stage, user can set this counter to 0.
+ */
+public class MainActivity extends Activity
+ implements SensorEventListener {
+
+ private static final String TAG = "JJMainActivity";
+
+ /** How long to keep the screen on when no activity is happening **/
+ private static final long SCREEN_ON_TIMEOUT_MS = 20000; // in milliseconds
+
+ /** an up-down movement that takes more than this will not be registered as such **/
+ private static final long TIME_THRESHOLD_NS = 2000000000; // in nanoseconds (= 2sec)
+
+ /**
+ * Earth gravity is around 9.8 m/s^2 but user may not completely direct his/her hand vertical
+ * during the exercise so we leave some room. Basically if the x-component of gravity, as
+ * measured by the Gravity sensor, changes with a variation (delta) > GRAVITY_THRESHOLD,
+ * we consider that a successful count.
+ */
+ private static final float GRAVITY_THRESHOLD = 7.0f;
+
+ private SensorManager mSensorManager;
+ private Sensor mSensor;
+ private long mLastTime = 0;
+ private boolean mUp = false;
+ private int mJumpCounter = 0;
+ private ViewPager mPager;
+ private CounterFragment mCounterPage;
+ private SettingsFragment mSettingPage;
+ private ImageView mSecondIndicator;
+ private ImageView mFirstIndicator;
+ private Timer mTimer;
+ private TimerTask mTimerTask;
+ private Handler mHandler;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.jj_layout);
+ setupViews();
+ mHandler = new Handler();
+ mJumpCounter = Utils.getCounterFromPreference(this);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ renewTimer();
+ mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
+ mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
+ }
+
+ private void setupViews() {
+ mPager = (ViewPager) findViewById(R.id.pager);
+ mFirstIndicator = (ImageView) findViewById(R.id.indicator_0);
+ mSecondIndicator = (ImageView) findViewById(R.id.indicator_1);
+ final PagerAdapter adapter = new PagerAdapter(getFragmentManager());
+ mCounterPage = new CounterFragment();
+ mSettingPage = new SettingsFragment(this);
+ adapter.addFragment(mCounterPage);
+ adapter.addFragment(mSettingPage);
+ setIndicator(0);
+ mPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
+ @Override
+ public void onPageScrolled(int i, float v, int i2) {
+ }
+
+ @Override
+ public void onPageSelected(int i) {
+ setIndicator(i);
+ renewTimer();
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int i) {
+ }
+ });
+
+ mPager.setAdapter(adapter);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ if (mSensorManager.registerListener(this, mSensor,
+ SensorManager.SENSOR_DELAY_NORMAL)) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Successfully registered for the sensor updates");
+ }
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mSensorManager.unregisterListener(this);
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Unregistered for sensor events");
+ }
+ }
+
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ detectJump(event.values[0], event.timestamp);
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ }
+
+ /**
+ * A simple algorithm to detect a successful up-down movement of hand(s). The algorithm is
+ * based on the assumption that when a person is wearing the watch, the x-component of gravity
+ * as measured by the Gravity Sensor is +9.8 when the hand is downward and -9.8 when the hand
+ * is upward (signs are reversed if the watch is worn on the right hand). Since the upward or
+ * downward may not be completely accurate, we leave some room and instead of 9.8, we use
+ * GRAVITY_THRESHOLD. We also consider the up <-> down movement successful if it takes less than
+ * TIME_THRESHOLD_NS.
+ */
+ private void detectJump(float xValue, long timestamp) {
+ if ((Math.abs(xValue) > GRAVITY_THRESHOLD)) {
+ if(timestamp - mLastTime < TIME_THRESHOLD_NS && mUp != (xValue > 0)) {
+ onJumpDetected(!mUp);
+ }
+ mUp = xValue > 0;
+ mLastTime = timestamp;
+ }
+ }
+
+ /**
+ * Called on detection of a successful down -> up or up -> down movement of hand.
+ */
+ private void onJumpDetected(boolean up) {
+ // we only count a pair of up and down as one successful movement
+ if (up) {
+ return;
+ }
+ mJumpCounter++;
+ setCounter(mJumpCounter);
+ renewTimer();
+ }
+
+ /**
+ * Updates the counter on UI, saves it to preferences and vibrates the watch when counter
+ * reaches a multiple of 10.
+ */
+ private void setCounter(int i) {
+ mCounterPage.setCounter(i);
+ Utils.saveCounterToPreference(this, i);
+ if (i > 0 && i % 10 == 0) {
+ Utils.vibrate(this, 0);
+ }
+ }
+
+ public void resetCounter() {
+ setCounter(0);
+ renewTimer();
+ }
+
+ /**
+ * Starts a timer to clear the flag FLAG_KEEP_SCREEN_ON.
+ */
+ private void renewTimer() {
+ if (null != mTimer) {
+ mTimer.cancel();
+ }
+ mTimerTask = new TimerTask() {
+ @Override
+ public void run() {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG,
+ "Removing the FLAG_KEEP_SCREEN_ON flag to allow going to background");
+ }
+ resetFlag();
+ }
+ };
+ mTimer = new Timer();
+ mTimer.schedule(mTimerTask, SCREEN_ON_TIMEOUT_MS);
+ }
+
+ /**
+ * Resets the FLAG_KEEP_SCREEN_ON flag so activity can go into background.
+ */
+ private void resetFlag() {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Resetting FLAG_KEEP_SCREEN_ON flag to allow going to background");
+ }
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ finish();
+ }
+ });
+ }
+
+ /**
+ * Sets the page indicator for the ViewPager.
+ */
+ private void setIndicator(int i) {
+ switch (i) {
+ case 0:
+ mFirstIndicator.setImageResource(R.drawable.full_10);
+ mSecondIndicator.setImageResource(R.drawable.empty_10);
+ break;
+ case 1:
+ mFirstIndicator.setImageResource(R.drawable.empty_10);
+ mSecondIndicator.setImageResource(R.drawable.full_10);
+ break;
+ }
+ }
+
+
+}
diff --git a/wearable/wear/JumpingJack/Wearable/src/main/java/com/example/android/jumpingjack/PagerAdapter.java b/wearable/wear/JumpingJack/Wearable/src/main/java/com/example/android/jumpingjack/PagerAdapter.java
new file mode 100644
index 0000000..47fe86c
--- /dev/null
+++ b/wearable/wear/JumpingJack/Wearable/src/main/java/com/example/android/jumpingjack/PagerAdapter.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2014 Google Inc. All Rights Reserved.
+ *
+ * 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.android.jumpingjack;
+
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.support.v13.app.FragmentPagerAdapter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A simple adapter for the {@link android.support.v4.view.ViewPager}
+ */
+public class PagerAdapter extends FragmentPagerAdapter {
+
+ List<Fragment> mFragments = null;
+
+ public PagerAdapter(FragmentManager fm) {
+ super(fm);
+ mFragments = new ArrayList<Fragment>();
+ }
+
+ @Override
+ public Fragment getItem(int position) {
+ return mFragments.get(position);
+ }
+
+ @Override
+ public int getCount() {
+ return mFragments.size();
+ }
+
+ public void addFragment(Fragment fragment) {
+ mFragments.add(fragment);
+ notifyDataSetChanged();
+ }
+}
diff --git a/wearable/wear/JumpingJack/Wearable/src/main/java/com/example/android/jumpingjack/Utils.java b/wearable/wear/JumpingJack/Wearable/src/main/java/com/example/android/jumpingjack/Utils.java
new file mode 100644
index 0000000..90fc296
--- /dev/null
+++ b/wearable/wear/JumpingJack/Wearable/src/main/java/com/example/android/jumpingjack/Utils.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2014 Google Inc. All Rights Reserved.
+ *
+ * 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.android.jumpingjack;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Vibrator;
+import android.preference.PreferenceManager;
+
+/**
+ * A utility class for some helper methods.
+ */
+public class Utils {
+
+ private static final int DEFAULT_VIBRATION_DURATION_MS = 200; // in millis
+ private static final String PREF_KEY_COUNTER = "counter";
+
+ /**
+ * Causes device to vibrate for the given duration (in millis). If duration is set to 0, then it
+ * will use the <code>DEFAULT_VIBRATION_DURATION_MS</code>.
+ */
+ public final static void vibrate(Context context, int duration) {
+ if (duration == 0) {
+ duration = DEFAULT_VIBRATION_DURATION_MS;
+ }
+ Vibrator v = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
+ v.vibrate(duration);
+ }
+
+ /**
+ * Saves the counter value in the preference storage. If <code>value</code>
+ * is negative, then the value will be removed from the preferences.
+ */
+ public static void saveCounterToPreference(Context context, int value) {
+ SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
+ if (value < 0) {
+ // we want to remove
+ pref.edit().remove(PREF_KEY_COUNTER).apply();
+ } else {
+ pref.edit().putInt(PREF_KEY_COUNTER, value).apply();
+ }
+ }
+
+ /**
+ * Retrieves the value of counter from preference manager. If no value exists, it will return
+ * <code>0</code>.
+ */
+ public static int getCounterFromPreference(Context context) {
+ SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
+ return pref.getInt(PREF_KEY_COUNTER, 0);
+ }
+
+}
diff --git a/wearable/wear/JumpingJack/Wearable/src/main/java/com/example/android/jumpingjack/fragments/CounterFragment.java b/wearable/wear/JumpingJack/Wearable/src/main/java/com/example/android/jumpingjack/fragments/CounterFragment.java
new file mode 100644
index 0000000..aa6fa53
--- /dev/null
+++ b/wearable/wear/JumpingJack/Wearable/src/main/java/com/example/android/jumpingjack/fragments/CounterFragment.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2014 Google Inc. All Rights Reserved.
+ *
+ * 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.android.jumpingjack.fragments;
+
+import com.example.android.jumpingjack.R;
+import com.example.android.jumpingjack.Utils;
+
+import android.app.Fragment;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+/**
+ * A simple fragment for showing the count
+ */
+public class CounterFragment extends Fragment {
+
+ private static final long ANIMATION_INTERVAL_MS = 500; // in milliseconds
+ private TextView mCounterText;
+ private Timer mAnimationTimer;
+ private Handler mHandler;
+ private TimerTask mAnimationTask;
+ private boolean up = false;
+ private Drawable mDownDrawable;
+ private Drawable mUpDrawable;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.counter_layout, container, false);
+ mDownDrawable = getResources().getDrawable(R.drawable.jump_down_50);
+ mUpDrawable = getResources().getDrawable(R.drawable.jump_up_50);
+ mCounterText = (TextView) view.findViewById(R.id.counter);
+ mCounterText.setCompoundDrawablesWithIntrinsicBounds(mUpDrawable, null, null, null);
+ setCounter(Utils.getCounterFromPreference(getActivity()));
+ mHandler = new Handler();
+ startAnimation();
+ return view;
+ }
+
+ private void startAnimation() {
+ mAnimationTask = new TimerTask() {
+ @Override
+ public void run() {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCounterText.setCompoundDrawablesWithIntrinsicBounds(
+ up ? mUpDrawable : mDownDrawable, null, null, null);
+ up = !up;
+ }
+ });
+ }
+ };
+ mAnimationTimer = new Timer();
+ mAnimationTimer.scheduleAtFixedRate(mAnimationTask, ANIMATION_INTERVAL_MS,
+ ANIMATION_INTERVAL_MS);
+ }
+
+ public void setCounter(String text) {
+ mCounterText.setText(text);
+ }
+
+ public void setCounter(int i) {
+ setCounter(i < 0 ? "0" : String.valueOf(i));
+ }
+
+ @Override
+ public void onDetach() {
+ mAnimationTimer.cancel();
+ super.onDetach();
+ }
+}
diff --git a/wearable/wear/JumpingJack/Wearable/src/main/java/com/example/android/jumpingjack/fragments/SettingsFragment.java b/wearable/wear/JumpingJack/Wearable/src/main/java/com/example/android/jumpingjack/fragments/SettingsFragment.java
new file mode 100644
index 0000000..0ef7a43
--- /dev/null
+++ b/wearable/wear/JumpingJack/Wearable/src/main/java/com/example/android/jumpingjack/fragments/SettingsFragment.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 Google Inc. All Rights Reserved.
+ *
+ * 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.android.jumpingjack.fragments;
+
+import com.example.android.jumpingjack.MainActivity;
+import com.example.android.jumpingjack.R;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+/**
+ * A simple fragment that shows a button to reset the counter
+ */
+public class SettingsFragment extends Fragment {
+
+ private Button mButton;
+ private MainActivity mMainActivity;
+
+ public SettingsFragment(MainActivity mainActivity) {
+ mMainActivity = mainActivity;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.setting_layout, container, false);
+ mButton = (Button) view.findViewById(R.id.btn);
+ mButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mMainActivity.resetCounter();
+ }
+ });
+ return view;
+ }
+
+}
diff --git a/wearable/wear/JumpingJack/Wearable/src/main/res/drawable-hdpi/btn_reset_normal_200.png b/wearable/wear/JumpingJack/Wearable/src/main/res/drawable-hdpi/btn_reset_normal_200.png
new file mode 100644
index 0000000..e585202
--- /dev/null
+++ b/wearable/wear/JumpingJack/Wearable/src/main/res/drawable-hdpi/btn_reset_normal_200.png
Binary files differ
diff --git a/wearable/wear/JumpingJack/Wearable/src/main/res/drawable-hdpi/btn_reset_pressed_200.png b/wearable/wear/JumpingJack/Wearable/src/main/res/drawable-hdpi/btn_reset_pressed_200.png
new file mode 100644
index 0000000..0b83b6d
--- /dev/null
+++ b/wearable/wear/JumpingJack/Wearable/src/main/res/drawable-hdpi/btn_reset_pressed_200.png
Binary files differ
diff --git a/wearable/wear/JumpingJack/Wearable/src/main/res/drawable-hdpi/ic_launcher.png b/wearable/wear/JumpingJack/Wearable/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..2d0c37d
--- /dev/null
+++ b/wearable/wear/JumpingJack/Wearable/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/JumpingJack/Wearable/src/main/res/drawable-mdpi/ic_launcher.png b/wearable/wear/JumpingJack/Wearable/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..3211c9e
--- /dev/null
+++ b/wearable/wear/JumpingJack/Wearable/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/JumpingJack/Wearable/src/main/res/drawable-xhdpi/ic_launcher.png b/wearable/wear/JumpingJack/Wearable/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..4ead8a2
--- /dev/null
+++ b/wearable/wear/JumpingJack/Wearable/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/JumpingJack/Wearable/src/main/res/drawable-xxhdpi/ic_launcher.png b/wearable/wear/JumpingJack/Wearable/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..8b357e4
--- /dev/null
+++ b/wearable/wear/JumpingJack/Wearable/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/JumpingJack/Wearable/src/main/res/drawable-xxxhdpi/ic_launcher.png b/wearable/wear/JumpingJack/Wearable/src/main/res/drawable-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..da3c00a
--- /dev/null
+++ b/wearable/wear/JumpingJack/Wearable/src/main/res/drawable-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/JumpingJack/Wearable/src/main/res/drawable/empty_10.png b/wearable/wear/JumpingJack/Wearable/src/main/res/drawable/empty_10.png
new file mode 100644
index 0000000..78ee76b
--- /dev/null
+++ b/wearable/wear/JumpingJack/Wearable/src/main/res/drawable/empty_10.png
Binary files differ
diff --git a/wearable/wear/JumpingJack/Wearable/src/main/res/drawable/full_10.png b/wearable/wear/JumpingJack/Wearable/src/main/res/drawable/full_10.png
new file mode 100644
index 0000000..53b799e
--- /dev/null
+++ b/wearable/wear/JumpingJack/Wearable/src/main/res/drawable/full_10.png
Binary files differ
diff --git a/wearable/wear/JumpingJack/Wearable/src/main/res/drawable/jump_down_50.png b/wearable/wear/JumpingJack/Wearable/src/main/res/drawable/jump_down_50.png
new file mode 100644
index 0000000..28980f8
--- /dev/null
+++ b/wearable/wear/JumpingJack/Wearable/src/main/res/drawable/jump_down_50.png
Binary files differ
diff --git a/wearable/wear/JumpingJack/Wearable/src/main/res/drawable/jump_up_50.png b/wearable/wear/JumpingJack/Wearable/src/main/res/drawable/jump_up_50.png
new file mode 100644
index 0000000..86dcef5
--- /dev/null
+++ b/wearable/wear/JumpingJack/Wearable/src/main/res/drawable/jump_up_50.png
Binary files differ
diff --git a/wearable/wear/JumpingJack/Wearable/src/main/res/drawable/submit_button.xml b/wearable/wear/JumpingJack/Wearable/src/main/res/drawable/submit_button.xml
new file mode 100644
index 0000000..2ab9ba5
--- /dev/null
+++ b/wearable/wear/JumpingJack/Wearable/src/main/res/drawable/submit_button.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@drawable/btn_reset_pressed_200"
+ android:state_pressed="true" />
+ <item android:drawable="@drawable/btn_reset_pressed_200"
+ android:state_focused="true" />
+ <item android:drawable="@drawable/btn_reset_normal_200" />
+</selector>
diff --git a/wearable/wear/JumpingJack/Wearable/src/main/res/layout/counter_layout.xml b/wearable/wear/JumpingJack/Wearable/src/main/res/layout/counter_layout.xml
new file mode 100644
index 0000000..e443e34
--- /dev/null
+++ b/wearable/wear/JumpingJack/Wearable/src/main/res/layout/counter_layout.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/white">
+
+ <TextView
+ android:id="@+id/counter"
+ android:layout_centerInParent="true"
+ android:textSize="50sp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+</RelativeLayout>
diff --git a/wearable/wear/JumpingJack/Wearable/src/main/res/layout/jj_layout.xml b/wearable/wear/JumpingJack/Wearable/src/main/res/layout/jj_layout.xml
new file mode 100644
index 0000000..73af6e3
--- /dev/null
+++ b/wearable/wear/JumpingJack/Wearable/src/main/res/layout/jj_layout.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/white">
+
+ <android.support.v4.view.ViewPager
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/pager"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="#000"
+ />
+
+ <LinearLayout
+ android:layout_alignParentBottom="true"
+ android:layout_centerHorizontal="true"
+ android:layout_marginBottom="10dp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <ImageView
+ android:id="@+id/indicator_0"
+ android:layout_marginRight="5dp"
+ android:src="@drawable/full_10"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ <ImageView
+ android:id="@+id/indicator_1"
+ android:src="@drawable/empty_10"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+
+</RelativeLayout>
diff --git a/wearable/wear/JumpingJack/Wearable/src/main/res/layout/setting_layout.xml b/wearable/wear/JumpingJack/Wearable/src/main/res/layout/setting_layout.xml
new file mode 100644
index 0000000..1298409
--- /dev/null
+++ b/wearable/wear/JumpingJack/Wearable/src/main/res/layout/setting_layout.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/white">
+
+ <Button
+ android:id="@+id/btn"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="40dp"
+ android:layout_width="75dp"
+ android:layout_height="75dp"
+ android:background="@drawable/submit_button"/>
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/btn"
+ android:layout_marginTop="5dp"
+ android:gravity="center"
+ android:textColor="@color/blue"
+ android:text="@string/reset_counter"/>
+
+</RelativeLayout>
diff --git a/wearable/wear/JumpingJack/Wearable/src/main/res/values/colors.xml b/wearable/wear/JumpingJack/Wearable/src/main/res/values/colors.xml
new file mode 100644
index 0000000..eccbe6d
--- /dev/null
+++ b/wearable/wear/JumpingJack/Wearable/src/main/res/values/colors.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+ <color name="white">#ffffff</color>
+ <color name="blue">#3f51b5</color>
+</resources>
diff --git a/wearable/wear/JumpingJack/Wearable/src/main/res/values/dimens.xml b/wearable/wear/JumpingJack/Wearable/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..a1e9cfe
--- /dev/null
+++ b/wearable/wear/JumpingJack/Wearable/src/main/res/values/dimens.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+</resources>
diff --git a/wearable/wear/JumpingJack/Wearable/src/main/res/values/strings.xml b/wearable/wear/JumpingJack/Wearable/src/main/res/values/strings.xml
new file mode 100644
index 0000000..8ab0f86
--- /dev/null
+++ b/wearable/wear/JumpingJack/Wearable/src/main/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+
+ <string name="app_name">Jumping Jack</string>
+ <string name="reset_counter">Reset Counter</string>
+
+</resources>
diff --git a/wearable/wear/JumpingJack/build.gradle b/wearable/wear/JumpingJack/build.gradle
new file mode 100644
index 0000000..be1fa82
--- /dev/null
+++ b/wearable/wear/JumpingJack/build.gradle
@@ -0,0 +1,14 @@
+
+
+
+
+// BEGIN_EXCLUDE
+import com.example.android.samples.build.SampleGenPlugin
+apply plugin: SampleGenPlugin
+
+samplegen {
+ pathToBuild "../../../../../build"
+ pathToSamplesCommon "../../../common"
+}
+apply from: "../../../../../build/build.gradle"
+// END_EXCLUDE
diff --git a/wearable/wear/JumpingJack/buildSrc/build.gradle b/wearable/wear/JumpingJack/buildSrc/build.gradle
new file mode 100644
index 0000000..e344a8c
--- /dev/null
+++ b/wearable/wear/JumpingJack/buildSrc/build.gradle
@@ -0,0 +1,18 @@
+
+
+
+repositories {
+ mavenCentral()
+}
+dependencies {
+ compile 'org.freemarker:freemarker:2.3.20'
+}
+
+sourceSets {
+ main {
+ groovy {
+ srcDir new File(rootDir, "../../../../../../build/buildSrc/src/main/groovy")
+ }
+ }
+}
+
diff --git a/wearable/wear/JumpingJack/gradle/wrapper/gradle-wrapper.jar b/wearable/wear/JumpingJack/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8c0fb64
--- /dev/null
+++ b/wearable/wear/JumpingJack/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/wearable/wear/JumpingJack/gradle/wrapper/gradle-wrapper.properties b/wearable/wear/JumpingJack/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..d7f03cf
--- /dev/null
+++ b/wearable/wear/JumpingJack/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=http\://services.gradle.org/distributions/gradle-1.12-bin.zip
diff --git a/wearable/wear/JumpingJack/gradlew b/wearable/wear/JumpingJack/gradlew
new file mode 100755
index 0000000..91a7e26
--- /dev/null
+++ b/wearable/wear/JumpingJack/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/wearable/wear/JumpingJack/gradlew.bat b/wearable/wear/JumpingJack/gradlew.bat
new file mode 100644
index 0000000..8a0b282
--- /dev/null
+++ b/wearable/wear/JumpingJack/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/wearable/wear/JumpingJack/settings.gradle b/wearable/wear/JumpingJack/settings.gradle
new file mode 100644
index 0000000..8522c57
--- /dev/null
+++ b/wearable/wear/JumpingJack/settings.gradle
@@ -0,0 +1 @@
+include ':Application', ':Wearable', ':Shared'
diff --git a/wearable/wear/JumpingJack/template-params.xml b/wearable/wear/JumpingJack/template-params.xml
new file mode 100644
index 0000000..6918a4b
--- /dev/null
+++ b/wearable/wear/JumpingJack/template-params.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+
+
+<sample>
+ <name>JumpingJack</name>
+ <group>Connectivity</group>
+ <package>com.example.android.jumpingjack</package>
+
+
+
+ <!-- change minSdk if needed-->
+ <minSdk>20</minSdk>
+
+
+ <strings>
+ <intro>
+ <![CDATA[
+ Uses the Gravity sensor to count how many jumping jacks you have performed.
+ ]]>
+ </intro>
+ </strings>
+
+ <template src="base"/>
+ <template src="Wear"/>
+ <common src="logger"/>
+ <common src="activities"/>
+
+</sample>
diff --git a/wearable/wear/Notifications/Application/.gitignore b/wearable/wear/Notifications/Application/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/Notifications/Application/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/Notifications/Application/proguard-project.txt b/wearable/wear/Notifications/Application/proguard-project.txt
new file mode 100644
index 0000000..0d8f171
--- /dev/null
+++ b/wearable/wear/Notifications/Application/proguard-project.txt
@@ -0,0 +1,20 @@
+ To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# 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/wearable/wear/Notifications/Application/src/main/AndroidManifest.xml b/wearable/wear/Notifications/Application/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..005d745
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/AndroidManifest.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.notifications" >
+
+
+ <uses-sdk android:minSdkVersion="19"
+ android:targetSdkVersion="19" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name"
+ android:windowSoftInputMode="stateHidden" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <receiver android:name=".NotificationIntentReceiver"
+ android:exported="false">
+ <intent-filter>
+ <action android:name="com.example.android.notifications.ACTION_EXAMPLE" />
+ <action android:name="com.example.android.notifications.ACTION_ENABLE_MESSAGES" />
+ <action android:name="com.example.android.notifications.ACTION_DISABLE_MESSAGES" />
+ </intent-filter>
+ </receiver>
+
+ </application>
+
+</manifest>
diff --git a/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/ActionsPreset.java b/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/ActionsPreset.java
new file mode 100644
index 0000000..32be1a6
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/ActionsPreset.java
@@ -0,0 +1,33 @@
+/*
+ * 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.android.notifications;
+
+import android.content.Context;
+import android.support.v4.app.NotificationCompat;
+
+/**
+ * Base class for notification actions presets.
+ */
+public abstract class ActionsPreset extends NamedPreset {
+ public ActionsPreset(int nameResId) {
+ super(nameResId);
+ }
+
+ /** Apply the priority to a notification builder */
+ public abstract void apply(Context context, NotificationCompat.Builder builder,
+ NotificationCompat.WearableExtender wearableOptions);
+}
diff --git a/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/ActionsPresets.java b/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/ActionsPresets.java
new file mode 100644
index 0000000..2481ac8
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/ActionsPresets.java
@@ -0,0 +1,158 @@
+/*
+ * 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.android.notifications;
+
+import android.content.Context;
+import android.support.v4.app.NotificationCompat;
+import android.support.v4.app.RemoteInput;
+
+/**
+ * Collection of notification actions presets.
+ */
+public class ActionsPresets {
+ public static final ActionsPreset NO_ACTIONS_PRESET = new NoActionsPreset();
+ public static final ActionsPreset SINGLE_ACTION_PRESET = new SingleActionPreset();
+
+ public static final ActionsPreset[] PRESETS = new ActionsPreset[] {
+ NO_ACTIONS_PRESET,
+ SINGLE_ACTION_PRESET,
+ new ReplyActionPreset(),
+ new ReplyWithChoicesActionPreset(),
+ new DifferentActionsOnPhoneAndWearable(),
+ new LongTitleActionPreset()
+ };
+
+ private static class NoActionsPreset extends ActionsPreset {
+ public NoActionsPreset() {
+ super(R.string.no_actions);
+ }
+
+ @Override
+ public void apply(Context context, NotificationCompat.Builder builder,
+ NotificationCompat.WearableExtender wearableOptions) {
+ }
+ }
+
+ private static class SingleActionPreset extends ActionsPreset {
+ public SingleActionPreset() {
+ super(R.string.single_action);
+ }
+
+ @Override
+ public void apply(Context context, NotificationCompat.Builder builder,
+ NotificationCompat.WearableExtender wearableOptions) {
+ builder.addAction(R.drawable.ic_full_action,
+ context.getString(R.string.example_action),
+ NotificationUtil.getExamplePendingIntent(context,
+ R.string.example_action_clicked))
+ .build();
+ }
+ }
+
+ private static class LongTitleActionPreset extends ActionsPreset {
+ public LongTitleActionPreset() {
+ super(R.string.long_title_action);
+ }
+
+ @Override
+ public void apply(Context context, NotificationCompat.Builder builder,
+ NotificationCompat.WearableExtender wearableOptions) {
+ builder.addAction(R.drawable.ic_full_action,
+ context.getString(R.string.example_action_long_title),
+ NotificationUtil.getExamplePendingIntent(context,
+ R.string.example_action_clicked))
+ .build();
+ }
+ }
+
+ private static class ReplyActionPreset extends ActionsPreset {
+ public ReplyActionPreset() {
+ super(R.string.reply_action);
+ }
+
+ @Override
+ public void apply(Context context, NotificationCompat.Builder builder,
+ NotificationCompat.WearableExtender wearableOptions) {
+ RemoteInput remoteInput = new RemoteInput.Builder(NotificationUtil.EXTRA_REPLY)
+ .setLabel(context.getString(R.string.example_reply_label))
+ .build();
+ NotificationCompat.Action action = new NotificationCompat.Action.Builder(
+ R.drawable.ic_full_reply,
+ context.getString(R.string.example_reply_action),
+ NotificationUtil.getExamplePendingIntent(context,
+ R.string.example_reply_action_clicked))
+ .addRemoteInput(remoteInput)
+ .build();
+ builder.addAction(action);
+ }
+ }
+
+ private static class ReplyWithChoicesActionPreset extends ActionsPreset {
+ public ReplyWithChoicesActionPreset() {
+ super(R.string.reply_action_with_choices);
+ }
+
+ @Override
+ public void apply(Context context, NotificationCompat.Builder builder,
+ NotificationCompat.WearableExtender wearableOptions) {
+ RemoteInput remoteInput = new RemoteInput.Builder(NotificationUtil.EXTRA_REPLY)
+ .setLabel(context.getString(R.string.example_reply_answer_label))
+ .setChoices(new String[] { context.getString(R.string.yes),
+ context.getString(R.string.no), context.getString(R.string.maybe) })
+ .build();
+ NotificationCompat.Action action = new NotificationCompat.Action.Builder(
+ R.drawable.ic_full_reply,
+ context.getString(R.string.example_reply_action),
+ NotificationUtil.getExamplePendingIntent(context,
+ R.string.example_reply_action_clicked))
+ .addRemoteInput(remoteInput)
+ .build();
+ wearableOptions.addAction(action);
+ }
+ }
+
+ private static class DifferentActionsOnPhoneAndWearable extends ActionsPreset {
+ public DifferentActionsOnPhoneAndWearable() {
+ super(R.string.different_actions_on_phone_and_wearable);
+ }
+
+ @Override
+ public void apply(Context context, NotificationCompat.Builder builder,
+ NotificationCompat.WearableExtender wearableOptions) {
+ NotificationCompat.Action phoneAction = new NotificationCompat.Action.Builder(
+ R.drawable.ic_full_action,
+ context.getString(R.string.phone_action),
+ NotificationUtil.getExamplePendingIntent(context,
+ R.string.phone_action_clicked))
+ .build();
+ builder.addAction(phoneAction);
+
+ RemoteInput remoteInput = new RemoteInput.Builder(NotificationUtil.EXTRA_REPLY)
+ .setLabel(context.getString(R.string.example_reply_label))
+ .build();
+
+ NotificationCompat.Action wearableAction = new NotificationCompat.Action.Builder(
+ R.drawable.ic_full_reply,
+ context.getString(R.string.wearable_action),
+ NotificationUtil.getExamplePendingIntent(context,
+ R.string.wearable_action_clicked))
+ .addRemoteInput(remoteInput)
+ .build();
+ wearableOptions.addAction(wearableAction);
+ }
+ }
+}
diff --git a/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/BackgroundPickers.java b/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/BackgroundPickers.java
new file mode 100644
index 0000000..69263b2
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/BackgroundPickers.java
@@ -0,0 +1,140 @@
+/*
+ * 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.android.notifications;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Manages the background image pickers.
+ */
+public class BackgroundPickers {
+
+ public interface OnBackgroundPickersChangedListener {
+ public void onBackgroundPickersChanged(BackgroundPickers pickers);
+ }
+
+ private final ViewGroup mContainer;
+ private final OnPickedListener mOnPickedListener;
+ private final List<ViewGroup> mPickers;
+ private final OnBackgroundPickersChangedListener listener;
+
+ public BackgroundPickers(ViewGroup container, OnBackgroundPickersChangedListener listener) {
+ this.mContainer = container;
+ this.mOnPickedListener = new OnPickedListener();
+ this.mPickers = new ArrayList<ViewGroup>();
+ this.listener = listener;
+ }
+
+ /**
+ * Generates the pickers as necessary.
+ */
+ public void generatePickers(int count) {
+ // Clear existing containers.
+ clear();
+
+ // Fill in new pickers.
+ LayoutInflater inflater = LayoutInflater.from(mContainer.getContext());
+ Resources res = mContainer.getResources();
+ for (int i = 0; i < count; i++) {
+ View picker = inflater.inflate(R.layout.background_picker, mContainer, false);
+ TextView label = (TextView) picker.findViewById(R.id.bg_picker_label);
+ label.setText(String.format(res.getString(R.string.bg_picker_label), i+1));
+ ViewGroup pickerBox = (ViewGroup) picker.findViewById(R.id.bg_picker_container);
+ mPickers.add(pickerBox);
+ for (int j = 0; j < pickerBox.getChildCount(); j++) {
+ ImageView img = (ImageView) pickerBox.getChildAt(j);
+ img.setOnClickListener(mOnPickedListener);
+ }
+ mContainer.addView(picker);
+ }
+ }
+
+ /**
+ * Returns the background resource for the picker at the given index.
+ * @param position Index of the background picker.
+ * @return Id of the background image resource. null if no image is picked.
+ */
+ public Integer getRes(int position) {
+ String tag = (String) mPickers.get(position).getTag();
+ if (tag == null) {
+ return null;
+ }
+
+ Context context = mContainer.getContext();
+ return context.getResources().getIdentifier(tag, "drawable", context.getPackageName());
+ }
+
+ /**
+ * Returns the all the background resources for the pickers managed by this object. Returns null
+ * if no pickers exist.
+ */
+ public Integer[] getRes() {
+ if (mPickers.size() == 0) {
+ return null;
+ }
+
+ Integer[] res = new Integer[mPickers.size()];
+ for (int i = 0; i < mPickers.size(); i++) {
+ res[i] = getRes(i);
+ }
+ return res;
+ }
+
+ /**
+ * Clears the pickers.
+ */
+ public void clear() {
+ mContainer.removeAllViews();
+ mPickers.clear();
+ }
+
+ public int getCount() {
+ return mPickers.size();
+ }
+
+ private class OnPickedListener implements View.OnClickListener {
+
+ @Override
+ public void onClick(View view) {
+ ImageView pickedView = (ImageView) view;
+ ViewGroup pickerBox = (ViewGroup) view.getParent();
+
+ // Clear old selection.
+ for (int i = 0; i < pickerBox.getChildCount(); i++) {
+ ImageView childView = (ImageView) pickerBox.getChildAt(i);
+ childView.setBackgroundResource(R.drawable.unselected_background);
+ }
+
+ // Set new selection.
+ pickedView.setBackgroundResource(R.drawable.selected_background);
+ pickerBox.setTag(pickedView.getTag());
+
+ if (listener != null) {
+ listener.onBackgroundPickersChanged(BackgroundPickers.this);
+ }
+ }
+ }
+}
diff --git a/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/MainActivity.java b/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/MainActivity.java
new file mode 100644
index 0000000..22b1059
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/MainActivity.java
@@ -0,0 +1,352 @@
+/*
+ * 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.android.notifications;
+
+import android.app.Activity;
+import android.app.Notification;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.support.v4.app.NotificationManagerCompat;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.EditText;
+import android.widget.Spinner;
+import android.widget.TextView;
+
+import java.util.Arrays;
+
+/**
+ * Main activity which posts a notification when resumed, and allows customization
+ * of that notification via controls.
+ */
+public class MainActivity extends Activity implements Handler.Callback {
+ private static final int MSG_POST_NOTIFICATIONS = 0;
+ private static final long POST_NOTIFICATIONS_DELAY_MS = 200;
+
+ private Handler mHandler;
+ private Spinner mPresetSpinner;
+ private EditText mTitleEditText;
+ private EditText mTextEditText;
+ private TextWatcher mTextChangedListener;
+ private Spinner mPrioritySpinner;
+ private Spinner mActionsSpinner;
+ private CheckBox mIncludeLargeIconCheckbox;
+ private CheckBox mLocalOnlyCheckbox;
+ private CheckBox mIncludeContentIntentCheckbox;
+ private CheckBox mVibrateCheckbox;
+ private BackgroundPickers mBackgroundPickers;
+ private int postedNotificationCount = 0;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+
+ mHandler = new Handler(this);
+ mTextChangedListener = new UpdateNotificationsOnTextChangeListener();
+
+ initPresetSpinner();
+ initTitleEditText();
+ initTextEditText();
+ initPrioritySpinner();
+ initActionsSpinner();
+ initIncludeLargeIconCheckbox();
+ initLocalOnlyCheckbox();
+ initIncludeContentIntentCheckbox();
+ initVibrateCheckbox();
+ initBackgroundPickers();
+
+ NotificationPreset preset = NotificationPresets.PRESETS[
+ mPresetSpinner.getSelectedItemPosition()];
+ updateTextEditors(preset);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ updateNotifications(false /* cancelExisting */);
+ }
+
+ private void initPresetSpinner() {
+ mPresetSpinner = (Spinner) findViewById(R.id.preset_spinner);
+ mPresetSpinner.setAdapter(new NamedPresetSpinnerArrayAdapter(this,
+ NotificationPresets.PRESETS));
+ mPresetSpinner.post(new Runnable() {
+ @Override
+ public void run() {
+ mPresetSpinner.setOnItemSelectedListener(new PresetSpinnerListener());
+ }
+ });
+ }
+
+ private void initTitleEditText() {
+ mTitleEditText = (EditText) findViewById(R.id.title_editor);
+ }
+
+ private void initTextEditText() {
+ mTextEditText = (EditText) findViewById(R.id.text_editor);
+ }
+
+ private void initPrioritySpinner() {
+ mPrioritySpinner = (Spinner) findViewById(R.id.priority_spinner);
+ mPrioritySpinner.setAdapter(new NamedPresetSpinnerArrayAdapter(this,
+ PriorityPresets.PRESETS));
+ mPrioritySpinner.setSelection(Arrays.asList(PriorityPresets.PRESETS)
+ .indexOf(PriorityPresets.DEFAULT));
+ mPrioritySpinner.post(new Runnable() {
+ @Override
+ public void run() {
+ mPrioritySpinner.setOnItemSelectedListener(
+ new UpdateNotificationsOnItemSelectedListener(true /* cancelExisting */));
+ }
+ });
+ }
+
+ private void initActionsSpinner() {
+ mActionsSpinner = (Spinner) findViewById(R.id.actions_spinner);
+ mActionsSpinner.setAdapter(new NamedPresetSpinnerArrayAdapter(this,
+ ActionsPresets.PRESETS));
+ mActionsSpinner.post(new Runnable() {
+ @Override
+ public void run() {
+ mActionsSpinner.setOnItemSelectedListener(
+ new UpdateNotificationsOnItemSelectedListener(false /* cancelExisting */));
+ }
+ });
+ }
+
+ private void initIncludeLargeIconCheckbox() {
+ mIncludeLargeIconCheckbox = (CheckBox) findViewById(R.id.include_large_icon_checkbox);
+ mIncludeLargeIconCheckbox.setOnCheckedChangeListener(
+ new UpdateNotificationsOnCheckedChangeListener(false /* cancelExisting */));
+ }
+
+ private void initLocalOnlyCheckbox() {
+ mLocalOnlyCheckbox = (CheckBox) findViewById(R.id.local_only_checkbox);
+ mLocalOnlyCheckbox.setOnCheckedChangeListener(
+ new UpdateNotificationsOnCheckedChangeListener(false /* cancelExisting */));
+ }
+
+ private void initIncludeContentIntentCheckbox() {
+ mIncludeContentIntentCheckbox = (CheckBox) findViewById(
+ R.id.include_content_intent_checkbox);
+ mIncludeContentIntentCheckbox.setOnCheckedChangeListener(
+ new UpdateNotificationsOnCheckedChangeListener(false /* cancelExisting */));
+ }
+
+ private void initVibrateCheckbox() {
+ mVibrateCheckbox = (CheckBox) findViewById(R.id.vibrate_checkbox);
+ mVibrateCheckbox.setOnCheckedChangeListener(
+ new UpdateNotificationsOnCheckedChangeListener(false /* cancelExisting */));
+ }
+
+ private void initBackgroundPickers() {
+ mBackgroundPickers = new BackgroundPickers(
+ (ViewGroup) findViewById(R.id.background_pickers),
+ new BackgroundPickerListener());
+ }
+
+ private void updateTextEditors(NotificationPreset preset) {
+ if (preset == NotificationPresets.BASIC) {
+ findViewById(R.id.title_edit_field).setVisibility(View.VISIBLE);
+ mTitleEditText.setText(getString(preset.titleResId));
+ mTitleEditText.addTextChangedListener(mTextChangedListener);
+ findViewById(R.id.text_edit_field).setVisibility(View.VISIBLE);
+ mTextEditText.setText(getString(preset.textResId));
+ mTextEditText.addTextChangedListener(mTextChangedListener);
+ } else {
+ findViewById(R.id.title_edit_field).setVisibility(View.GONE);
+ mTitleEditText.removeTextChangedListener(mTextChangedListener);
+ findViewById(R.id.text_edit_field).setVisibility(View.GONE);
+ mTextEditText.removeTextChangedListener(mTextChangedListener);
+ }
+ }
+
+ /**
+ * Begin to re-post the sample notification(s).
+ */
+ private void updateNotifications(boolean cancelExisting) {
+ // Disable messages to skip notification deleted messages during cancel.
+ sendBroadcast(new Intent(NotificationIntentReceiver.ACTION_DISABLE_MESSAGES)
+ .setClass(this, NotificationIntentReceiver.class));
+
+ if (cancelExisting) {
+ // Cancel all existing notifications to trigger fresh-posting behavior: For example,
+ // switching from HIGH to LOW priority does not cause a reordering in Notification Shade.
+ NotificationManagerCompat.from(this).cancelAll();
+ postedNotificationCount = 0;
+
+ // Post the updated notifications on a delay to avoid a cancel+post race condition
+ // with notification manager.
+ mHandler.removeMessages(MSG_POST_NOTIFICATIONS);
+ mHandler.sendEmptyMessageDelayed(MSG_POST_NOTIFICATIONS, POST_NOTIFICATIONS_DELAY_MS);
+ } else {
+ postNotifications();
+ }
+ }
+
+ /**
+ * Post the sample notification(s) using current options.
+ */
+ private void postNotifications() {
+ sendBroadcast(new Intent(NotificationIntentReceiver.ACTION_ENABLE_MESSAGES)
+ .setClass(this, NotificationIntentReceiver.class));
+
+ NotificationPreset preset = NotificationPresets.PRESETS[
+ mPresetSpinner.getSelectedItemPosition()];
+ CharSequence titlePreset = mTitleEditText.getText();
+ CharSequence textPreset = mTextEditText.getText();
+ PriorityPreset priorityPreset = PriorityPresets.PRESETS[
+ mPrioritySpinner.getSelectedItemPosition()];
+ ActionsPreset actionsPreset = ActionsPresets.PRESETS[
+ mActionsSpinner.getSelectedItemPosition()];
+ if (preset.actionsRequired() && actionsPreset == ActionsPresets.NO_ACTIONS_PRESET) {
+ // If actions are required, but the no-actions preset was selected, change presets.
+ actionsPreset = ActionsPresets.SINGLE_ACTION_PRESET;
+ mActionsSpinner.setSelection(Arrays.asList(ActionsPresets.PRESETS).indexOf(
+ actionsPreset), true);
+ }
+ NotificationPreset.BuildOptions options = new NotificationPreset.BuildOptions(
+ titlePreset,
+ textPreset,
+ priorityPreset,
+ actionsPreset,
+ mIncludeLargeIconCheckbox.isChecked(),
+ mLocalOnlyCheckbox.isChecked(),
+ mIncludeContentIntentCheckbox.isChecked(),
+ mVibrateCheckbox.isChecked(),
+ mBackgroundPickers.getRes());
+ Notification[] notifications = preset.buildNotifications(this, options);
+
+ // Post new notifications
+ for (int i = 0; i < notifications.length; i++) {
+ NotificationManagerCompat.from(this).notify(i, notifications[i]);
+ }
+ // Cancel any that are beyond the current count.
+ for (int i = notifications.length; i < postedNotificationCount; i++) {
+ NotificationManagerCompat.from(this).cancel(i);
+ }
+ postedNotificationCount = notifications.length;
+ }
+
+ @Override
+ public boolean handleMessage(Message message) {
+ switch (message.what) {
+ case MSG_POST_NOTIFICATIONS:
+ postNotifications();
+ return true;
+ }
+ return false;
+ }
+
+ private class PresetSpinnerListener implements AdapterView.OnItemSelectedListener {
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ NotificationPreset preset = NotificationPresets.PRESETS[position];
+ mBackgroundPickers.generatePickers(preset.countBackgroundPickersRequired());
+ updateTextEditors(preset);
+ updateNotifications(false /* cancelExisting */);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> adapterView) {
+ }
+ }
+
+ private class UpdateNotificationsOnTextChangeListener implements TextWatcher {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ updateNotifications(false /* cancelExisting */);
+ }
+ }
+
+ private class UpdateNotificationsOnItemSelectedListener
+ implements AdapterView.OnItemSelectedListener {
+ private final boolean mCancelExisting;
+
+ public UpdateNotificationsOnItemSelectedListener(boolean cancelExisting) {
+ mCancelExisting = cancelExisting;
+ }
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ updateNotifications(mCancelExisting);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> adapterView) {
+ }
+ }
+
+ private class UpdateNotificationsOnCheckedChangeListener
+ implements CompoundButton.OnCheckedChangeListener {
+ private final boolean mCancelExisting;
+
+ public UpdateNotificationsOnCheckedChangeListener(boolean cancelExisting) {
+ mCancelExisting = cancelExisting;
+ }
+
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
+ updateNotifications(mCancelExisting);
+ }
+ }
+
+ private class BackgroundPickerListener
+ implements BackgroundPickers.OnBackgroundPickersChangedListener {
+ @Override
+ public void onBackgroundPickersChanged(BackgroundPickers pickers) {
+ updateNotifications(false /* cancelExisting */);
+ }
+ }
+
+ private class NamedPresetSpinnerArrayAdapter extends ArrayAdapter<NamedPreset> {
+ public NamedPresetSpinnerArrayAdapter(Context context, NamedPreset[] presets) {
+ super(context, R.layout.simple_spinner_item, presets);
+ }
+
+ @Override
+ public View getDropDownView(int position, View convertView, ViewGroup parent) {
+ TextView view = (TextView) super.getDropDownView(position, convertView, parent);
+ view.setText(getString(getItem(position).nameResId));
+ return view;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ TextView view = (TextView) getLayoutInflater().inflate(
+ android.R.layout.simple_spinner_item, parent, false);
+ view.setText(getString(getItem(position).nameResId));
+ return view;
+ }
+ }
+}
diff --git a/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/NamedPreset.java b/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/NamedPreset.java
new file mode 100644
index 0000000..b97bcb9
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/NamedPreset.java
@@ -0,0 +1,28 @@
+/*
+ * 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.android.notifications;
+
+/**
+ * Base class for presets that have a simple name to display.
+ */
+public abstract class NamedPreset {
+ public final int nameResId;
+
+ public NamedPreset(int nameResId) {
+ this.nameResId = nameResId;
+ }
+}
diff --git a/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/NotificationIntentReceiver.java b/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/NotificationIntentReceiver.java
new file mode 100644
index 0000000..8dabb34
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/NotificationIntentReceiver.java
@@ -0,0 +1,60 @@
+/*
+ * 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.android.notifications;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v4.app.RemoteInput;
+import android.widget.Toast;
+
+/**
+ * Broadcast receiver to post toast messages in response to notification intents firing.
+ */
+public class NotificationIntentReceiver extends BroadcastReceiver {
+ public static final String ACTION_EXAMPLE =
+ "com.example.android.notifications.ACTION_EXAMPLE";
+ public static final String ACTION_ENABLE_MESSAGES =
+ "com.example.android.notifications.ACTION_ENABLE_MESSAGES";
+ public static final String ACTION_DISABLE_MESSAGES =
+ "com.example.android.notifications.ACTION_DISABLE_MESSAGES";
+
+ private boolean mEnableMessages = true;
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction().equals(ACTION_EXAMPLE)) {
+ if (mEnableMessages) {
+ String message = intent.getStringExtra(NotificationUtil.EXTRA_MESSAGE);
+ Bundle remoteInputResults = RemoteInput.getResultsFromIntent(intent);
+ CharSequence replyMessage = null;
+ if (remoteInputResults != null) {
+ replyMessage = remoteInputResults.getCharSequence(NotificationUtil.EXTRA_REPLY);
+ }
+ if (replyMessage != null) {
+ message = message + ": \"" + replyMessage + "\"";
+ }
+ Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
+ }
+ } else if (intent.getAction().equals(ACTION_ENABLE_MESSAGES)) {
+ mEnableMessages = true;
+ } else if (intent.getAction().equals(ACTION_DISABLE_MESSAGES)) {
+ mEnableMessages = false;
+ }
+ }
+}
diff --git a/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/NotificationPreset.java b/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/NotificationPreset.java
new file mode 100644
index 0000000..3ab792b
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/NotificationPreset.java
@@ -0,0 +1,74 @@
+/*
+ * 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.android.notifications;
+
+import android.app.Notification;
+import android.content.Context;
+
+/**
+ * Base class for notification preset generators.
+ */
+public abstract class NotificationPreset extends NamedPreset {
+ public final int titleResId;
+ public final int textResId;
+
+ public NotificationPreset(int nameResId, int titleResId, int textResId) {
+ super(nameResId);
+ this.titleResId = titleResId;
+ this.textResId = textResId;
+ }
+
+ public static class BuildOptions {
+ public final CharSequence titlePreset;
+ public final CharSequence textPreset;
+ public final PriorityPreset priorityPreset;
+ public final ActionsPreset actionsPreset;
+ public final boolean includeLargeIcon;
+ public final boolean isLocalOnly;
+ public final boolean hasContentIntent;
+ public final boolean vibrate;
+ public final Integer[] backgroundIds;
+
+ public BuildOptions(CharSequence titlePreset, CharSequence textPreset,
+ PriorityPreset priorityPreset, ActionsPreset actionsPreset,
+ boolean includeLargeIcon, boolean isLocalOnly, boolean hasContentIntent,
+ boolean vibrate, Integer[] backgroundIds) {
+ this.titlePreset = titlePreset;
+ this.textPreset = textPreset;
+ this.priorityPreset = priorityPreset;
+ this.actionsPreset = actionsPreset;
+ this.includeLargeIcon = includeLargeIcon;
+ this.isLocalOnly = isLocalOnly;
+ this.hasContentIntent = hasContentIntent;
+ this.vibrate = vibrate;
+ this.backgroundIds = backgroundIds;
+ }
+ }
+
+ /** Build a notification with this preset and the provided options */
+ public abstract Notification[] buildNotifications(Context context, BuildOptions options);
+
+ /** Whether actions are required to use this preset. */
+ public boolean actionsRequired() {
+ return false;
+ }
+
+ /** Number of background pickers required */
+ public int countBackgroundPickersRequired() {
+ return 0;
+ }
+}
diff --git a/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/NotificationPresets.java b/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/NotificationPresets.java
new file mode 100644
index 0000000..b6fe24a
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/NotificationPresets.java
@@ -0,0 +1,479 @@
+/*
+ * 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.android.notifications;
+
+import android.app.Notification;
+import android.content.Context;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
+import android.graphics.Typeface;
+import android.support.v4.app.NotificationCompat;
+import android.text.SpannableStringBuilder;
+import android.text.style.ForegroundColorSpan;
+import android.text.style.RelativeSizeSpan;
+import android.text.style.StrikethroughSpan;
+import android.text.style.StyleSpan;
+import android.text.style.SubscriptSpan;
+import android.text.style.SuperscriptSpan;
+import android.text.style.TypefaceSpan;
+import android.text.style.UnderlineSpan;
+import android.view.Gravity;
+
+/**
+ * Collection of notification builder presets.
+ */
+public class NotificationPresets {
+ private static final String EXAMPLE_GROUP_KEY = "example";
+
+ public static final NotificationPreset BASIC = new BasicNotificationPreset();
+ public static final NotificationPreset STYLIZED_TEXT = new StylizedTextNotificationPreset();
+ public static final NotificationPreset INBOX = new InboxNotificationPreset();
+ public static final NotificationPreset BIG_PICTURE = new BigPictureNotificationPreset();
+ public static final NotificationPreset BIG_TEXT = new BigTextNotificationPreset();
+ public static final NotificationPreset BOTTOM_ALIGNED = new BottomAlignedNotificationPreset();
+ public static final NotificationPreset GRAVITY = new GravityNotificationPreset();
+ public static final NotificationPreset CONTENT_ACTION = new ContentActionNotificationPreset();
+ public static final NotificationPreset CONTENT_ICON = new ContentIconNotificationPreset();
+ public static final NotificationPreset MULTIPLE_PAGE = new MultiplePageNotificationPreset();
+ public static final NotificationPreset BUNDLE = new NotificationBundlePreset();
+
+ public static final NotificationPreset[] PRESETS = new NotificationPreset[] {
+ BASIC,
+ STYLIZED_TEXT,
+ INBOX,
+ BIG_PICTURE,
+ BIG_TEXT,
+ BOTTOM_ALIGNED,
+ GRAVITY,
+ CONTENT_ACTION,
+ CONTENT_ICON,
+ MULTIPLE_PAGE,
+ BUNDLE
+ };
+
+ private static NotificationCompat.Builder applyBasicOptions(Context context,
+ NotificationCompat.Builder builder, NotificationCompat.WearableExtender wearableOptions,
+ NotificationPreset.BuildOptions options) {
+ builder.setContentTitle(options.titlePreset)
+ .setContentText(options.textPreset)
+ .setSmallIcon(R.mipmap.ic_launcher)
+ .setDeleteIntent(NotificationUtil.getExamplePendingIntent(
+ context, R.string.example_notification_deleted));
+ options.actionsPreset.apply(context, builder, wearableOptions);
+ options.priorityPreset.apply(builder, wearableOptions);
+ if (options.includeLargeIcon) {
+ builder.setLargeIcon(BitmapFactory.decodeResource(
+ context.getResources(), R.drawable.example_large_icon));
+ }
+ if (options.isLocalOnly) {
+ builder.setLocalOnly(true);
+ }
+ if (options.hasContentIntent) {
+ builder.setContentIntent(NotificationUtil.getExamplePendingIntent(context,
+ R.string.content_intent_clicked));
+ }
+ if (options.vibrate) {
+ builder.setVibrate(new long[] {0, 100, 50, 100} );
+ }
+ return builder;
+ }
+
+ private static class BasicNotificationPreset extends NotificationPreset {
+ public BasicNotificationPreset() {
+ super(R.string.basic_example, R.string.example_content_title,
+ R.string.example_content_text);
+ }
+
+ @Override
+ public Notification[] buildNotifications(Context context, BuildOptions options) {
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
+ NotificationCompat.WearableExtender wearableOptions =
+ new NotificationCompat.WearableExtender();
+ applyBasicOptions(context, builder, wearableOptions, options);
+ builder.extend(wearableOptions);
+ return new Notification[] { builder.build() };
+ }
+ }
+
+ private static class StylizedTextNotificationPreset extends NotificationPreset {
+ public StylizedTextNotificationPreset() {
+ super(R.string.stylized_text_example, R.string.example_content_title,
+ R.string.example_content_text);
+ }
+
+ @Override
+ public Notification[] buildNotifications(Context context, BuildOptions options) {
+ NotificationCompat.BigTextStyle style = new NotificationCompat.BigTextStyle();
+
+ SpannableStringBuilder title = new SpannableStringBuilder();
+ appendStyled(title, "Stylized", new StyleSpan(Typeface.BOLD_ITALIC));
+ title.append(" title");
+ SpannableStringBuilder text = new SpannableStringBuilder("Stylized text: ");
+ appendStyled(text, "C", new ForegroundColorSpan(Color.RED));
+ appendStyled(text, "O", new ForegroundColorSpan(Color.GREEN));
+ appendStyled(text, "L", new ForegroundColorSpan(Color.BLUE));
+ appendStyled(text, "O", new ForegroundColorSpan(Color.YELLOW));
+ appendStyled(text, "R", new ForegroundColorSpan(Color.MAGENTA));
+ appendStyled(text, "S", new ForegroundColorSpan(Color.CYAN));
+ text.append("; ");
+ appendStyled(text, "1.25x size", new RelativeSizeSpan(1.25f));
+ text.append("; ");
+ appendStyled(text, "0.75x size", new RelativeSizeSpan(0.75f));
+ text.append("; ");
+ appendStyled(text, "underline", new UnderlineSpan());
+ text.append("; ");
+ appendStyled(text, "strikethrough", new StrikethroughSpan());
+ text.append("; ");
+ appendStyled(text, "bold", new StyleSpan(Typeface.BOLD));
+ text.append("; ");
+ appendStyled(text, "italic", new StyleSpan(Typeface.ITALIC));
+ text.append("; ");
+ appendStyled(text, "sans-serif-thin", new TypefaceSpan("sans-serif-thin"));
+ text.append("; ");
+ appendStyled(text, "monospace", new TypefaceSpan("monospace"));
+ text.append("; ");
+ appendStyled(text, "sub", new SubscriptSpan());
+ text.append("script");
+ appendStyled(text, "super", new SuperscriptSpan());
+
+ style.setBigContentTitle(title);
+ style.bigText(text);
+
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
+ .setStyle(style);
+ NotificationCompat.WearableExtender wearableOptions =
+ new NotificationCompat.WearableExtender();
+ applyBasicOptions(context, builder, wearableOptions, options);
+ builder.extend(wearableOptions);
+ return new Notification[] { builder.build() };
+ }
+
+ private void appendStyled(SpannableStringBuilder builder, String str, Object... spans) {
+ builder.append(str);
+ for (Object span : spans) {
+ builder.setSpan(span, builder.length() - str.length(), builder.length(), 0);
+ }
+ }
+ }
+
+ private static class InboxNotificationPreset extends NotificationPreset {
+ public InboxNotificationPreset() {
+ super(R.string.inbox_example, R.string.example_content_title,
+ R.string.example_content_text);
+ }
+
+ @Override
+ public Notification[] buildNotifications(Context context, BuildOptions options) {
+ NotificationCompat.InboxStyle style = new NotificationCompat.InboxStyle();
+ style.addLine(context.getString(R.string.inbox_style_example_line1));
+ style.addLine(context.getString(R.string.inbox_style_example_line2));
+ style.addLine(context.getString(R.string.inbox_style_example_line3));
+ style.setBigContentTitle(context.getString(R.string.inbox_style_example_title));
+ style.setSummaryText(context.getString(R.string.inbox_style_example_summary_text));
+
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
+ .setStyle(style);
+ NotificationCompat.WearableExtender wearableOptions =
+ new NotificationCompat.WearableExtender();
+ applyBasicOptions(context, builder, wearableOptions, options);
+ builder.extend(wearableOptions);
+ return new Notification[] { builder.build() };
+ }
+ }
+
+ private static class BigPictureNotificationPreset extends NotificationPreset {
+ public BigPictureNotificationPreset() {
+ super(R.string.big_picture_example, R.string.example_content_title,
+ R.string.example_content_text);
+ }
+
+ @Override
+ public Notification[] buildNotifications(Context context, BuildOptions options) {
+ NotificationCompat.BigPictureStyle style = new NotificationCompat.BigPictureStyle();
+ style.bigPicture(BitmapFactory.decodeResource(context.getResources(),
+ R.drawable.example_big_picture));
+ style.setBigContentTitle(context.getString(R.string.big_picture_style_example_title));
+ style.setSummaryText(context.getString(
+ R.string.big_picture_style_example_summary_text));
+
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
+ .setStyle(style);
+ NotificationCompat.WearableExtender wearableOptions =
+ new NotificationCompat.WearableExtender();
+ applyBasicOptions(context, builder, wearableOptions, options);
+ builder.extend(wearableOptions);
+ return new Notification[] { builder.build() };
+ }
+ }
+
+ private static class BigTextNotificationPreset extends NotificationPreset {
+ public BigTextNotificationPreset() {
+ super(R.string.big_text_example, R.string.example_content_title,
+ R.string.example_content_text);
+ }
+
+ @Override
+ public Notification[] buildNotifications(Context context, BuildOptions options) {
+ NotificationCompat.BigTextStyle style = new NotificationCompat.BigTextStyle();
+ style.bigText(context.getString(R.string.big_text_example_big_text));
+ style.setBigContentTitle(context.getString(R.string.big_text_example_title));
+ style.setSummaryText(context.getString(R.string.big_text_example_summary_text));
+
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
+ .setStyle(style);
+ NotificationCompat.WearableExtender wearableOptions =
+ new NotificationCompat.WearableExtender();
+ applyBasicOptions(context, builder, wearableOptions, options);
+ builder.extend(wearableOptions);
+ return new Notification[] { builder.build() };
+ }
+ }
+
+ private static class BottomAlignedNotificationPreset extends NotificationPreset {
+ public BottomAlignedNotificationPreset() {
+ super(R.string.bottom_aligned_example, R.string.example_content_title,
+ R.string.example_content_text);
+ }
+
+ @Override
+ public Notification[] buildNotifications(Context context, BuildOptions options) {
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
+ NotificationCompat.WearableExtender wearableOptions =
+ new NotificationCompat.WearableExtender();
+ applyBasicOptions(context, builder, wearableOptions, options);
+
+ NotificationCompat.Builder secondPageBuilder = new NotificationCompat.Builder(context);
+ secondPageBuilder.setContentTitle(
+ context.getString(R.string.second_page_content_title));
+ secondPageBuilder.setContentText(context.getString(R.string.big_text_example_big_text));
+ secondPageBuilder.extend(new NotificationCompat.WearableExtender()
+ .setStartScrollBottom(true));
+
+ wearableOptions.addPage(secondPageBuilder.build());
+ builder.extend(wearableOptions);
+ return new Notification[] { builder.build() };
+ }
+ }
+
+ private static class GravityNotificationPreset extends NotificationPreset {
+ public GravityNotificationPreset() {
+ super(R.string.gravity_example, R.string.example_content_title,
+ R.string.example_content_text);
+ }
+
+ @Override
+ public Notification[] buildNotifications(Context context, BuildOptions options) {
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
+ NotificationCompat.WearableExtender wearableOptions =
+ new NotificationCompat.WearableExtender();
+ applyBasicOptions(context, builder, wearableOptions, options);
+
+ NotificationCompat.Builder secondPageBuilder = new NotificationCompat.Builder(context)
+ .setContentTitle(options.titlePreset)
+ .setContentText(options.textPreset)
+ .extend(new NotificationCompat.WearableExtender()
+ .setGravity(Gravity.CENTER_VERTICAL));
+ wearableOptions.addPage(secondPageBuilder.build());
+
+ NotificationCompat.Builder thirdPageBuilder = new NotificationCompat.Builder(context)
+ .setContentTitle(options.titlePreset)
+ .setContentText(options.textPreset)
+ .extend(new NotificationCompat.WearableExtender()
+ .setGravity(Gravity.TOP));
+ wearableOptions.addPage(thirdPageBuilder.build());
+
+ wearableOptions.setGravity(Gravity.BOTTOM);
+ builder.extend(wearableOptions);
+ return new Notification[] { builder.build() };
+ }
+ }
+
+ private static class ContentActionNotificationPreset extends NotificationPreset {
+ public ContentActionNotificationPreset() {
+ super(R.string.content_action_example, R.string.example_content_title,
+ R.string.example_content_text);
+ }
+
+ @Override
+ public Notification[] buildNotifications(Context context, BuildOptions options) {
+ Notification secondPage = new NotificationCompat.Builder(context)
+ .setContentTitle(context.getString(R.string.second_page_content_title))
+ .setContentText(context.getString(R.string.second_page_content_text))
+ .extend(new NotificationCompat.WearableExtender()
+ .setContentAction(1))
+ .build();
+
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
+ NotificationCompat.Action action = new NotificationCompat.Action.Builder(
+ R.drawable.ic_result_open, null, NotificationUtil.getExamplePendingIntent(
+ context, R.string.example_content_action_clicked)).build();
+ NotificationCompat.Action action2 = new NotificationCompat.Action.Builder(
+ R.drawable.ic_result_open, null, NotificationUtil.getExamplePendingIntent(
+ context, R.string.example_content_action2_clicked)).build();
+ NotificationCompat.WearableExtender wearableOptions =
+ new NotificationCompat.WearableExtender()
+ .addAction(action)
+ .addAction(action2)
+ .addPage(secondPage)
+ .setContentAction(0)
+ .setHintHideIcon(true);
+ applyBasicOptions(context, builder, wearableOptions, options);
+ builder.extend(wearableOptions);
+ return new Notification[] { builder.build() };
+ }
+
+ @Override
+ public boolean actionsRequired() {
+ return true;
+ }
+ }
+
+ private static class ContentIconNotificationPreset extends NotificationPreset {
+ public ContentIconNotificationPreset() {
+ super(R.string.content_icon_example, R.string.example_content_title,
+ R.string.example_content_text);
+ }
+
+ @Override
+ public Notification[] buildNotifications(Context context, BuildOptions options) {
+ Notification secondPage = new NotificationCompat.Builder(context)
+ .setContentTitle(context.getString(R.string.second_page_content_title))
+ .setContentText(context.getString(R.string.second_page_content_text))
+ .extend(new NotificationCompat.WearableExtender()
+ .setContentIcon(R.drawable.content_icon_small)
+ .setContentIconGravity(Gravity.START))
+ .build();
+
+ Notification thirdPage = new NotificationCompat.Builder(context)
+ .setContentTitle(context.getString(R.string.third_page_content_title))
+ .setContentText(context.getString(R.string.third_page_content_text))
+ .extend(new NotificationCompat.WearableExtender()
+ .setContentIcon(R.drawable.content_icon_large))
+ .build();
+
+ Notification fourthPage = new NotificationCompat.Builder(context)
+ .setContentTitle(context.getString(R.string.fourth_page_content_title))
+ .setContentText(context.getString(R.string.fourth_page_content_text))
+ .extend(new NotificationCompat.WearableExtender()
+ .setContentIcon(R.drawable.content_icon_large)
+ .setContentIconGravity(Gravity.START))
+ .build();
+
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
+ NotificationCompat.WearableExtender wearableOptions =
+ new NotificationCompat.WearableExtender()
+ .setHintHideIcon(true)
+ .setContentIcon(R.drawable.content_icon_small)
+ .addPage(secondPage)
+ .addPage(thirdPage)
+ .addPage(fourthPage);
+ applyBasicOptions(context, builder, wearableOptions, options);
+ builder.extend(wearableOptions);
+ return new Notification[] { builder.build() };
+ }
+ }
+
+ private static class MultiplePageNotificationPreset extends NotificationPreset {
+ public MultiplePageNotificationPreset() {
+ super(R.string.multiple_page_example, R.string.example_content_title,
+ R.string.example_content_text);
+ }
+
+ @Override
+ public Notification[] buildNotifications(Context context, BuildOptions options) {
+ NotificationCompat.Builder secondPageBuilder = new NotificationCompat.Builder(context)
+ .setContentTitle(context.getString(R.string.second_page_content_title))
+ .setContentText(context.getString(R.string.second_page_content_text));
+
+ NotificationCompat.Builder firstPageBuilder = new NotificationCompat.Builder(context);
+ NotificationCompat.WearableExtender firstPageWearableOptions =
+ new NotificationCompat.WearableExtender();
+ applyBasicOptions(context, firstPageBuilder, firstPageWearableOptions, options);
+
+ Integer firstBackground = options.backgroundIds == null
+ ? null : options.backgroundIds[0];
+ if (firstBackground != null) {
+ NotificationCompat.BigPictureStyle style =
+ new NotificationCompat.BigPictureStyle();
+ style.bigPicture(BitmapFactory.decodeResource(context.getResources(),
+ firstBackground));
+ firstPageBuilder.setStyle(style);
+ }
+
+ Integer secondBackground = options.backgroundIds == null
+ ? null : options.backgroundIds[1];
+ if (secondBackground != null) {
+ NotificationCompat.BigPictureStyle style = new NotificationCompat.BigPictureStyle();
+ style.bigPicture(BitmapFactory.decodeResource(context.getResources(),
+ secondBackground));
+ secondPageBuilder.setStyle(style);
+ }
+
+ firstPageBuilder.extend(
+ firstPageWearableOptions.addPage(secondPageBuilder.build()));
+
+ return new Notification[]{ firstPageBuilder.build() };
+ }
+
+ @Override
+ public int countBackgroundPickersRequired() {
+ return 2; // This sample does 2 pages notifications.
+ }
+ }
+
+ private static class NotificationBundlePreset extends NotificationPreset {
+ public NotificationBundlePreset() {
+ super(R.string.bundle_example, R.string.example_content_title,
+ R.string.example_content_text);
+ }
+
+ @Override
+ public Notification[] buildNotifications(Context context, BuildOptions options) {
+ NotificationCompat.Builder childBuilder1 = new NotificationCompat.Builder(context)
+ .setContentTitle(context.getString(R.string.first_child_content_title))
+ .setContentText(context.getString(R.string.first_child_content_text))
+ .setSmallIcon(R.mipmap.ic_launcher)
+ .setLocalOnly(options.isLocalOnly)
+ .setGroup(EXAMPLE_GROUP_KEY)
+ .setSortKey("0");
+
+ NotificationCompat.Builder childBuilder2 = new NotificationCompat.Builder(context)
+ .setContentTitle(context.getString(R.string.second_child_content_title))
+ .setContentText(context.getString(R.string.second_child_content_text))
+ .setSmallIcon(R.mipmap.ic_launcher)
+ .addAction(R.mipmap.ic_launcher,
+ context.getString(R.string.second_child_action),
+ NotificationUtil.getExamplePendingIntent(
+ context, R.string.second_child_action_clicked))
+ .setLocalOnly(options.isLocalOnly)
+ .setGroup(EXAMPLE_GROUP_KEY)
+ .setSortKey("1");
+
+ NotificationCompat.Builder summaryBuilder = new NotificationCompat.Builder(context)
+ .setGroup(EXAMPLE_GROUP_KEY)
+ .setGroupSummary(true);
+
+ NotificationCompat.WearableExtender summaryWearableOptions =
+ new NotificationCompat.WearableExtender();
+ applyBasicOptions(context, summaryBuilder, summaryWearableOptions, options);
+ summaryBuilder.extend(summaryWearableOptions);
+
+ return new Notification[] { summaryBuilder.build(), childBuilder1.build(),
+ childBuilder2.build() };
+ }
+ }
+}
diff --git a/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/NotificationUtil.java b/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/NotificationUtil.java
new file mode 100644
index 0000000..b5c43e5
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/NotificationUtil.java
@@ -0,0 +1,36 @@
+/*
+ * 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.android.notifications;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+
+public class NotificationUtil {
+ public static final String EXTRA_MESSAGE =
+ "com.example.android.notifications.MESSAGE";
+ public static final String EXTRA_REPLY =
+ "com.example.android.notifications.REPLY";
+
+ public static PendingIntent getExamplePendingIntent(Context context, int messageResId) {
+ Intent intent = new Intent(NotificationIntentReceiver.ACTION_EXAMPLE)
+ .setClass(context, NotificationIntentReceiver.class);
+ intent.putExtra(EXTRA_MESSAGE, context.getString(messageResId));
+ return PendingIntent.getBroadcast(context, messageResId /* requestCode */, intent,
+ PendingIntent.FLAG_UPDATE_CURRENT);
+ }
+}
diff --git a/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/PriorityPreset.java b/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/PriorityPreset.java
new file mode 100644
index 0000000..eaddb83
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/PriorityPreset.java
@@ -0,0 +1,32 @@
+/*
+ * 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.android.notifications;
+
+import android.support.v4.app.NotificationCompat;
+
+/**
+ * Base class for notification priority presets.
+ */
+public abstract class PriorityPreset extends NamedPreset {
+ public PriorityPreset(int nameResId) {
+ super(nameResId);
+ }
+
+ /** Apply the priority to a notification builder */
+ public abstract void apply(NotificationCompat.Builder builder,
+ NotificationCompat.WearableExtender wearableOptions);
+}
diff --git a/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/PriorityPresets.java b/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/PriorityPresets.java
new file mode 100644
index 0000000..7d1ed7c
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/java/com/example/android/notifications/PriorityPresets.java
@@ -0,0 +1,55 @@
+/*
+ * 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.android.notifications;
+
+import android.app.Notification;
+import android.support.v4.app.NotificationCompat;
+
+/**
+ * Collection of notification priority presets.
+ */
+public class PriorityPresets {
+ public static final PriorityPreset DEFAULT = new SimplePriorityPreset(
+ R.string.default_priority, Notification.PRIORITY_DEFAULT);
+
+ public static final PriorityPreset[] PRESETS = new PriorityPreset[] {
+ new SimplePriorityPreset(R.string.min_priority, Notification.PRIORITY_MIN),
+ new SimplePriorityPreset(R.string.low_priority, Notification.PRIORITY_LOW),
+ DEFAULT,
+ new SimplePriorityPreset(R.string.high_priority, Notification.PRIORITY_HIGH),
+ new SimplePriorityPreset(R.string.max_priority, Notification.PRIORITY_MAX)
+ };
+
+ /**
+ * Simple notification priority preset that sets a priority using
+ * {@link android.support.v4.app.NotificationCompat.Builder#setPriority}
+ */
+ private static class SimplePriorityPreset extends PriorityPreset {
+ private final int mPriority;
+
+ public SimplePriorityPreset(int nameResId, int priority) {
+ super(nameResId);
+ mPriority = priority;
+ }
+
+ @Override
+ public void apply(NotificationCompat.Builder builder,
+ NotificationCompat.WearableExtender wearableOptions) {
+ builder.setPriority(mPriority);
+ }
+ }
+}
diff --git a/wearable/wear/Notifications/Application/src/main/res/drawable-hdpi/example_large_icon.png b/wearable/wear/Notifications/Application/src/main/res/drawable-hdpi/example_large_icon.png
new file mode 100644
index 0000000..545f8ce
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/drawable-hdpi/example_large_icon.png
Binary files differ
diff --git a/wearable/wear/Notifications/Application/src/main/res/drawable-hdpi/ic_full_action.png b/wearable/wear/Notifications/Application/src/main/res/drawable-hdpi/ic_full_action.png
new file mode 100644
index 0000000..1f27499
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/drawable-hdpi/ic_full_action.png
Binary files differ
diff --git a/wearable/wear/Notifications/Application/src/main/res/drawable-hdpi/ic_full_reply.png b/wearable/wear/Notifications/Application/src/main/res/drawable-hdpi/ic_full_reply.png
new file mode 100644
index 0000000..66388d5
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/drawable-hdpi/ic_full_reply.png
Binary files differ
diff --git a/wearable/wear/Notifications/Application/src/main/res/drawable-hdpi/ic_result_open.png b/wearable/wear/Notifications/Application/src/main/res/drawable-hdpi/ic_result_open.png
new file mode 100644
index 0000000..db8af57
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/drawable-hdpi/ic_result_open.png
Binary files differ
diff --git a/wearable/wear/Notifications/Application/src/main/res/drawable-mdpi/ic_full_action.png b/wearable/wear/Notifications/Application/src/main/res/drawable-mdpi/ic_full_action.png
new file mode 100644
index 0000000..b70b74f
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/drawable-mdpi/ic_full_action.png
Binary files differ
diff --git a/wearable/wear/Notifications/Application/src/main/res/drawable-mdpi/ic_full_reply.png b/wearable/wear/Notifications/Application/src/main/res/drawable-mdpi/ic_full_reply.png
new file mode 100644
index 0000000..60ce9f9
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/drawable-mdpi/ic_full_reply.png
Binary files differ
diff --git a/wearable/wear/Notifications/Application/src/main/res/drawable-mdpi/ic_result_open.png b/wearable/wear/Notifications/Application/src/main/res/drawable-mdpi/ic_result_open.png
new file mode 100644
index 0000000..860d7de
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/drawable-mdpi/ic_result_open.png
Binary files differ
diff --git a/wearable/wear/Notifications/Application/src/main/res/drawable-nodpi/bg_1.png b/wearable/wear/Notifications/Application/src/main/res/drawable-nodpi/bg_1.png
new file mode 100644
index 0000000..9c80794
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/drawable-nodpi/bg_1.png
Binary files differ
diff --git a/wearable/wear/Notifications/Application/src/main/res/drawable-nodpi/bg_2.png b/wearable/wear/Notifications/Application/src/main/res/drawable-nodpi/bg_2.png
new file mode 100644
index 0000000..23d7062
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/drawable-nodpi/bg_2.png
Binary files differ
diff --git a/wearable/wear/Notifications/Application/src/main/res/drawable-nodpi/bg_3.png b/wearable/wear/Notifications/Application/src/main/res/drawable-nodpi/bg_3.png
new file mode 100644
index 0000000..588318d
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/drawable-nodpi/bg_3.png
Binary files differ
diff --git a/wearable/wear/Notifications/Application/src/main/res/drawable-nodpi/bg_4.png b/wearable/wear/Notifications/Application/src/main/res/drawable-nodpi/bg_4.png
new file mode 100644
index 0000000..bd1dfee
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/drawable-nodpi/bg_4.png
Binary files differ
diff --git a/wearable/wear/Notifications/Application/src/main/res/drawable-nodpi/bg_5.png b/wearable/wear/Notifications/Application/src/main/res/drawable-nodpi/bg_5.png
new file mode 100644
index 0000000..aa1ad23
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/drawable-nodpi/bg_5.png
Binary files differ
diff --git a/wearable/wear/Notifications/Application/src/main/res/drawable-nodpi/content_icon_large.png b/wearable/wear/Notifications/Application/src/main/res/drawable-nodpi/content_icon_large.png
new file mode 100644
index 0000000..0eab3b1
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/drawable-nodpi/content_icon_large.png
Binary files differ
diff --git a/wearable/wear/Notifications/Application/src/main/res/drawable-nodpi/content_icon_small.png b/wearable/wear/Notifications/Application/src/main/res/drawable-nodpi/content_icon_small.png
new file mode 100644
index 0000000..9a9f4b4
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/drawable-nodpi/content_icon_small.png
Binary files differ
diff --git a/wearable/wear/Notifications/Application/src/main/res/drawable-nodpi/example_big_picture.jpg b/wearable/wear/Notifications/Application/src/main/res/drawable-nodpi/example_big_picture.jpg
new file mode 100644
index 0000000..68473ba
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/drawable-nodpi/example_big_picture.jpg
Binary files differ
diff --git a/wearable/wear/Notifications/Application/src/main/res/drawable-xhdpi/ic_full_action.png b/wearable/wear/Notifications/Application/src/main/res/drawable-xhdpi/ic_full_action.png
new file mode 100644
index 0000000..6a76952
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/drawable-xhdpi/ic_full_action.png
Binary files differ
diff --git a/wearable/wear/Notifications/Application/src/main/res/drawable-xhdpi/ic_full_reply.png b/wearable/wear/Notifications/Application/src/main/res/drawable-xhdpi/ic_full_reply.png
new file mode 100644
index 0000000..dba6fa7
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/drawable-xhdpi/ic_full_reply.png
Binary files differ
diff --git a/wearable/wear/Notifications/Application/src/main/res/drawable-xhdpi/ic_result_open.png b/wearable/wear/Notifications/Application/src/main/res/drawable-xhdpi/ic_result_open.png
new file mode 100644
index 0000000..7d3c785
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/drawable-xhdpi/ic_result_open.png
Binary files differ
diff --git a/wearable/wear/Notifications/Application/src/main/res/drawable/selected_background.xml b/wearable/wear/Notifications/Application/src/main/res/drawable/selected_background.xml
new file mode 100644
index 0000000..5852dd8
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/drawable/selected_background.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <padding
+ android:top="4dp"
+ android:bottom="4dp"
+ android:left="4dp"
+ android:right="4dp"/>
+ <stroke
+ android:width="4dp"
+ android:color="@android:color/holo_blue_bright" />
+</shape>
diff --git a/wearable/wear/Notifications/Application/src/main/res/drawable/unselected_background.xml b/wearable/wear/Notifications/Application/src/main/res/drawable/unselected_background.xml
new file mode 100644
index 0000000..1613167
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/drawable/unselected_background.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <padding
+ android:top="4dp"
+ android:bottom="4dp"
+ android:left="4dp"
+ android:right="4dp"/>
+ <stroke
+ android:width="4dp"
+ android:color="#ff000000" />
+</shape>
diff --git a/wearable/wear/Notifications/Application/src/main/res/layout/background_picker.xml b/wearable/wear/Notifications/Application/src/main/res/layout/background_picker.xml
new file mode 100644
index 0000000..03f77f1
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/layout/background_picker.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView
+ android:id="@+id/bg_picker_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="@dimen/editor_item_padding_top"
+ android:paddingTop="@dimen/editor_item_padding_top"
+ android:paddingBottom="@dimen/editor_item_padding_top"
+ android:text="@string/bg_picker_label"/>
+
+ <HorizontalScrollView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <LinearLayout
+ android:id="@+id/bg_picker_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <ImageView
+ android:id="@+id/bg_none"
+ android:background="@drawable/selected_background"
+ style="@style/bg_picker"
+ android:layout_width="@dimen/image_picker_item_side"
+ android:layout_height="@dimen/image_picker_item_side"
+ android:src="@android:color/background_light"/>
+ <ImageView
+ android:id="@+id/bg1"
+ style="@style/bg_picker"
+ android:layout_width="@dimen/image_picker_item_side"
+ android:layout_height="@dimen/image_picker_item_side"
+ android:tag="bg_1"
+ android:src="@drawable/bg_1"/>
+ <ImageView
+ android:id="@+id/bg2"
+ style="@style/bg_picker"
+ android:layout_width="@dimen/image_picker_item_side"
+ android:layout_height="@dimen/image_picker_item_side"
+ android:tag="bg_2"
+ android:src="@drawable/bg_2"/>
+ <ImageView
+ android:id="@+id/bg3"
+ style="@style/bg_picker"
+ android:layout_width="@dimen/image_picker_item_side"
+ android:layout_height="@dimen/image_picker_item_side"
+ android:tag="bg_3"
+ android:src="@drawable/bg_3"/>
+ <ImageView
+ android:id="@+id/bg4"
+ style="@style/bg_picker"
+ android:layout_width="@dimen/image_picker_item_side"
+ android:layout_height="@dimen/image_picker_item_side"
+ android:tag="bg_4"
+ android:src="@drawable/bg_4"/>
+ <ImageView
+ android:id="@+id/bg5"
+ style="@style/bg_picker"
+ android:layout_width="@dimen/image_picker_item_side"
+ android:layout_height="@dimen/image_picker_item_side"
+ android:tag="bg_5"
+ android:src="@drawable/bg_5"/>
+ </LinearLayout>
+
+ </HorizontalScrollView>
+
+</LinearLayout>
diff --git a/wearable/wear/Notifications/Application/src/main/res/layout/layout_divider.xml b/wearable/wear/Notifications/Application/src/main/res/layout/layout_divider.xml
new file mode 100644
index 0000000..82142b7
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/layout/layout_divider.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!--
+ Copyright 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.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/divider_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="3dp"
+ android:textAllCaps="true"
+ android:textColor="@color/divider_text"
+ android:textSize="@dimen/editor_text_size"
+ android:text="@string/properties"/>
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:layout_marginTop="3dp"
+ android:background="@color/divider_text" />
+
+</LinearLayout>
diff --git a/wearable/wear/Notifications/Application/src/main/res/layout/main.xml b/wearable/wear/Notifications/Application/src/main/res/layout/main.xml
new file mode 100644
index 0000000..3068ddc
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/layout/main.xml
@@ -0,0 +1,173 @@
+
+<!-- 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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ tools:context="com.example.android.support.wearable.notifications.MainActivity"
+ tools:ignore="MergeRootFrame">
+
+ <LinearLayout android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <include layout="@layout/layout_divider" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <TextView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:minWidth="@dimen/editor_spinner_caption_min_width"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall"
+ android:gravity="center_vertical"
+ android:text="@string/preset" />
+
+ <Spinner android:id="@+id/preset_spinner"
+ android:layout_marginLeft="10dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <TextView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:minWidth="@dimen/editor_spinner_caption_min_width"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall"
+ android:gravity="center_vertical"
+ android:text="@string/priority" />
+
+ <Spinner android:id="@+id/priority_spinner"
+ android:layout_marginLeft="10dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <TextView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:minWidth="@dimen/editor_spinner_caption_min_width"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall"
+ android:gravity="center_vertical"
+ android:text="@string/actions" />
+
+ <Spinner android:id="@+id/actions_spinner"
+ android:layout_marginLeft="10dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/title_edit_field"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <TextView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:minWidth="@dimen/editor_spinner_caption_min_width"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall"
+ android:gravity="center_vertical"
+ android:text="@string/title" />
+
+ <EditText android:id="@+id/title_editor"
+ android:layout_marginLeft="10dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/text_edit_field"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <TextView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:minWidth="@dimen/editor_spinner_caption_min_width"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall"
+ android:gravity="center_vertical"
+ android:text="@string/text" />
+
+ <EditText android:id="@+id/text_editor"
+ android:layout_marginLeft="10dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ </LinearLayout>
+
+ <CheckBox android:id="@+id/include_large_icon_checkbox"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:paddingTop="@dimen/editor_item_padding_top"
+ android:paddingBottom="@dimen/editor_item_padding_bottom"
+ android:text="@string/include_large_icon" />
+
+ <CheckBox android:id="@+id/local_only_checkbox"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:paddingTop="@dimen/editor_item_padding_top"
+ android:paddingBottom="@dimen/editor_item_padding_bottom"
+ android:text="@string/local_only" />
+
+ <CheckBox android:id="@+id/include_content_intent_checkbox"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:paddingTop="@dimen/editor_item_padding_top"
+ android:paddingBottom="@dimen/editor_item_padding_bottom"
+ android:text="@string/include_content_intent" />
+
+ <CheckBox android:id="@+id/vibrate_checkbox"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:paddingTop="@dimen/editor_item_padding_top"
+ android:paddingBottom="@dimen/editor_item_padding_bottom"
+ android:text="@string/vibrate" />
+
+ <LinearLayout android:id="@+id/background_pickers"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ </LinearLayout>
+
+ </LinearLayout>
+
+</ScrollView>
diff --git a/wearable/wear/Notifications/Application/src/main/res/layout/simple_spinner_item.xml b/wearable/wear/Notifications/Application/src/main/res/layout/simple_spinner_item.xml
new file mode 100644
index 0000000..342a130
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/layout/simple_spinner_item.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceListItemSmall"
+ android:gravity="center_vertical"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:background="?android:attr/activatedBackgroundIndicator"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall" />
diff --git a/wearable/wear/Notifications/Application/src/main/res/mipmap-hdpi/ic_launcher.png b/wearable/wear/Notifications/Application/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..41479de
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Notifications/Application/src/main/res/mipmap-mdpi/ic_launcher.png b/wearable/wear/Notifications/Application/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..380b02f
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Notifications/Application/src/main/res/mipmap-xhdpi/ic_launcher.png b/wearable/wear/Notifications/Application/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..b3e251e
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Notifications/Application/src/main/res/mipmap-xxhdpi/ic_launcher.png b/wearable/wear/Notifications/Application/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..1962289
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Notifications/Application/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/wearable/wear/Notifications/Application/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..163f1f0
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Notifications/Application/src/main/res/values/colors.xml b/wearable/wear/Notifications/Application/src/main/res/values/colors.xml
new file mode 100644
index 0000000..9464085
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/values/colors.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+ <color name="divider_text">@android:color/holo_blue_bright</color>
+</resources>
diff --git a/wearable/wear/Notifications/Application/src/main/res/values/dimens.xml b/wearable/wear/Notifications/Application/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..fd97910
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/values/dimens.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+
+ <dimen name="editor_text_size">12dp</dimen>
+ <dimen name="editor_item_padding_top">8dp</dimen>
+ <dimen name="editor_item_padding_bottom">8dp</dimen>
+ <dimen name="editor_spinner_caption_min_width">50dp</dimen>
+
+ <dimen name="image_picker_item_side">48dp</dimen>
+
+</resources>
diff --git a/wearable/wear/Notifications/Application/src/main/res/values/strings.xml b/wearable/wear/Notifications/Application/src/main/res/values/strings.xml
new file mode 100644
index 0000000..52f0f10
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/values/strings.xml
@@ -0,0 +1,192 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+
+ <string name="properties">Properties</string>
+ <string name="preset">Preset</string>
+ <string name="text">Text</string>
+ <string name="title">Title</string>
+ <string name="priority">Priority</string>
+ <string name="actions">Actions</string>
+ <string name="include_large_icon">Include large icon</string>
+ <string name="local_only">Local only</string>
+ <string name="include_content_intent">Include content intent</string>
+ <string name="vibrate">Vibrate</string>
+
+ <string name="basic_example">Basic example</string>
+ <string name="stylized_text_example">Stylized text example</string>
+ <string name="inbox_example">Inbox example</string>
+ <string name="big_picture_example">Big picture example</string>
+ <string name="big_text_example">Big text example</string>
+ <string name="bottom_aligned_example">Bottom-aligned example</string>
+ <string name="gravity_example">Gravity example</string>
+ <string name="content_action_example">Content action example</string>
+ <string name="content_icon_example">Content icon example</string>
+ <string name="multiple_page_example">Multiple page example</string>
+ <string name="bundle_example">Bundle example</string>
+
+ <string name="min_priority">Min priority</string>
+ <string name="low_priority">Low priority</string>
+ <string name="default_priority">Default priority</string>
+ <string name="high_priority">High priority</string>
+ <string name="max_priority">Max priority</string>
+
+ <string name="no_actions">No actions</string>
+ <string name="single_action">Single action</string>
+ <string name="long_title_action">Single action with a long title</string>
+ <string name="reply_action">Reply action</string>
+ <string name="reply_action_with_choices">Reply action with choices</string>
+ <string name="different_actions_on_phone_and_wearable">Different on phone and wearable</string>
+
+ <string name="example_action">Example action</string>
+ <string name="example_action_long_title">Example action with a long title which wraps</string>
+ <string name="example_reply_action">Example reply action</string>
+ <string name="phone_action">Phone action</string>
+ <string name="wearable_action">Wearable action</string>
+
+ <string name="example_action_clicked">Example action clicked</string>
+ <string name="example_reply_action_clicked">Example reply action clicked</string>
+ <string name="phone_action_clicked">Phone action clicked</string>
+ <string name="wearable_action_clicked">Wearable action clicked</string>
+ <string name="second_child_action_clicked">Second child action clicked</string>
+ <string name="content_intent_clicked">Content intent clicked</string>
+ <string name="example_content_action_clicked">Example content action clicked</string>
+ <string name="example_content_action2_clicked">Example content action 2 clicked</string>
+ <string name="example_notification_deleted">Example notification deleted</string>
+
+ <string name="example_content_title">Basic example title</string>
+ <string name="example_content_text">Basic example text</string>
+
+ <string name="big_text_example_title">Big text example title</string>
+ <string name="big_text_example_summary_text">Big text example summary</string>
+ <string name="big_text_example_big_text">
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
+ exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
+ dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
+ Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
+ anim id est laborum.
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
+ exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
+ dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
+ Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
+ anim id est laborum.
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
+ exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
+ dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
+ Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
+ anim id est laborum.
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
+ exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
+ dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
+ Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
+ anim id est laborum.
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
+ exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
+ dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
+ Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
+ anim id est laborum.
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
+ exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
+ dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
+ Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
+ anim id est laborum.
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
+ exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
+ dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
+ Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
+ anim id est laborum.
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
+ exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
+ dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
+ Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
+ anim id est laborum.
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
+ exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
+ dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
+ Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
+ anim id est laborum.
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
+ exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
+ dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
+ Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
+ anim id est laborum.
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
+ exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
+ dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
+ Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
+ anim id est laborum.
+ </string>
+
+ <string name="inbox_style_example_title">Inbox style example title</string>
+ <string name="inbox_style_example_summary_text">Inbox style example summary</string>
+ <string name="inbox_style_example_line1">Inbox style example line 1</string>
+ <string name="inbox_style_example_line2">Inbox style example line 2</string>
+ <string name="inbox_style_example_line3">Inbox style example line 3</string>
+
+ <string name="big_picture_style_example_title">Big picture style example title</string>
+ <string name="big_picture_style_example_summary_text">Big picture style example summary</string>
+
+ <string name="second_page_content_title">Second page title</string>
+ <string name="second_page_content_text">Second page text</string>
+
+ <string name="third_page_content_title">Third page title</string>
+ <string name="third_page_content_text">Third page text</string>
+
+ <string name="fourth_page_content_title">Fourth page title</string>
+ <string name="fourth_page_content_text">Fourth page text</string>
+
+ <string name="first_child_content_title">First child title</string>
+ <string name="first_child_content_text">
+ First child text. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
+ tempor incididunt ut labore et dolore magna aliqua.</string>
+ <string name="second_child_content_title">Second child title</string>
+ <string name="second_child_content_text">
+ Second child text. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
+ tempor incididunt ut labore et dolore magna aliqua.</string>
+ <string name="second_child_action">Second child action</string>
+
+ <string name="example_reply_label">Message?</string>
+
+ <string name="example_reply_answer_label">Answer?</string>
+ <string name="yes">Yes</string>
+ <string name="no">No</string>
+ <string name="maybe">Maybe</string>
+
+ <string name="bg_picker_label">Page %s background: </string>
+
+</resources>
diff --git a/wearable/wear/Notifications/Application/src/main/res/values/styles.xml b/wearable/wear/Notifications/Application/src/main/res/values/styles.xml
new file mode 100644
index 0000000..69f8dfa
--- /dev/null
+++ b/wearable/wear/Notifications/Application/src/main/res/values/styles.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+
+ <style name="bg_picker">
+ <item name="android:layout_marginLeft">16dp</item>
+ <item name="android:background">@drawable/unselected_background</item>
+ </style>
+
+</resources>
diff --git a/wearable/wear/Notifications/CONTRIB.md b/wearable/wear/Notifications/CONTRIB.md
new file mode 100644
index 0000000..14a4fcf
--- /dev/null
+++ b/wearable/wear/Notifications/CONTRIB.md
@@ -0,0 +1,35 @@
+# How to become a contributor and submit your own code
+
+## Contributor License Agreements
+
+We'd love to accept your sample apps and patches! Before we can take them, we
+have to jump a couple of legal hurdles.
+
+Please fill out either the individual or corporate Contributor License Agreement (CLA).
+
+ * If you are an individual writing original source code and you're sure you
+ own the intellectual property, then you'll need to sign an [individual CLA]
+ (https://developers.google.com/open-source/cla/individual).
+ * If you work for a company that wants to allow you to contribute your work,
+ then you'll need to sign a [corporate CLA]
+ (https://developers.google.com/open-source/cla/corporate).
+
+Follow either of the two links above to access the appropriate CLA and
+instructions for how to sign and return it. Once we receive it, we'll be able to
+accept your pull requests.
+
+## Contributing A Patch
+
+1. Submit an issue describing your proposed change to the repo in question.
+1. The repo owner will respond to your issue promptly.
+1. If your proposed change is accepted, and you haven't already done so, sign a
+ Contributor License Agreement (see details above).
+1. Fork the desired repo, develop and test your code changes.
+1. Ensure that your code adheres to the existing style in the sample to which
+ you are contributing. Refer to the
+ [Android Code Style Guide]
+ (https://source.android.com/source/code-style.html) for the
+ recommended coding standards for this organization.
+1. Ensure that your code has an appropriate set of unit tests which all pass.
+1. Submit a pull request.
+
diff --git a/wearable/wear/Notifications/LICENSE b/wearable/wear/Notifications/LICENSE
new file mode 100644
index 0000000..1af981f
--- /dev/null
+++ b/wearable/wear/Notifications/LICENSE
@@ -0,0 +1,201 @@
+ 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 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/wearable/wear/Notifications/README-wear.txt b/wearable/wear/Notifications/README-wear.txt
new file mode 100644
index 0000000..17523d7
--- /dev/null
+++ b/wearable/wear/Notifications/README-wear.txt
@@ -0,0 +1,30 @@
+<#--
+ Copyright 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.
+-->
+
+Steps to use Wear template on top of an existing sample:
+- In template-params.xml.ftl:
+ - Add the following template:
+ <template src="Wear"/>
+
+- Refresh your project (./gradlew refresh)
+- Add Wearable-specific code to Wearable directory
+- Add code to be shared among the main application and the wearable to Shared
+ directory
+
+Note that you still need the main application sample code. This is usually
+achieved by adding another template, like "base" for example.
+
+
diff --git a/wearable/wear/Notifications/Shared/.gitignore b/wearable/wear/Notifications/Shared/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/Notifications/Shared/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/Notifications/Shared/src/main/AndroidManifest.xml b/wearable/wear/Notifications/Shared/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..0054143
--- /dev/null
+++ b/wearable/wear/Notifications/Shared/src/main/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.notifications.common">
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name">
+ </application>
+
+</manifest>
diff --git a/wearable/wear/Notifications/Shared/src/main/res/values/strings.xml b/wearable/wear/Notifications/Shared/src/main/res/values/strings.xml
new file mode 100644
index 0000000..0f2bb90
--- /dev/null
+++ b/wearable/wear/Notifications/Shared/src/main/res/values/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+ <string name="app_name">Shared</string>
+</resources>
diff --git a/wearable/wear/Notifications/Wearable/.gitignore b/wearable/wear/Notifications/Wearable/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/Notifications/Wearable/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/Notifications/Wearable/src/main/AndroidManifest.xml b/wearable/wear/Notifications/Wearable/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..99640f5
--- /dev/null
+++ b/wearable/wear/Notifications/Wearable/src/main/AndroidManifest.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.notifications" >
+
+ <uses-sdk android:minSdkVersion="20"
+ android:targetSdkVersion="20" />
+
+ <uses-feature android:name="android.hardware.type.watch" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@android:style/Theme.DeviceDefault.Light" >
+
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity
+ android:name=".BasicNotificationDisplayActivity"
+ android:exported="true"
+ android:allowEmbedded="true"
+ android:label="@string/app_name"
+ android:taskAffinity="" />
+ <activity
+ android:name=".AnimatedNotificationDisplayActivity"
+ android:exported="true"
+ android:allowEmbedded="true"
+ android:label="@string/app_name"
+ android:taskAffinity="" />
+ </application>
+
+</manifest>
diff --git a/wearable/wear/Notifications/Wearable/src/main/java/com/example/android/notifications/AnimatedNotificationDisplayActivity.java b/wearable/wear/Notifications/Wearable/src/main/java/com/example/android/notifications/AnimatedNotificationDisplayActivity.java
new file mode 100644
index 0000000..f14acef
--- /dev/null
+++ b/wearable/wear/Notifications/Wearable/src/main/java/com/example/android/notifications/AnimatedNotificationDisplayActivity.java
@@ -0,0 +1,138 @@
+/*
+ * 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.android.notifications;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.util.Random;
+
+/**
+ * Custom display activity for an animated sample notification.
+ */
+public class AnimatedNotificationDisplayActivity extends Activity {
+ public static final String EXTRA_TITLE = "title";
+
+ private static final int BASE_ANIMATION_DURATION_MS = 2000;
+
+ private Random mRandom;
+ private int mAnimationRange;
+ private ImageView mImageView;
+ private Animator mAnimation;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_animated_notification_display);
+
+ mRandom = new Random(System.currentTimeMillis());
+ mAnimationRange = getResources().getDimensionPixelSize(R.dimen.animation_range);
+
+ String title = getIntent().getStringExtra(EXTRA_TITLE);
+ ((TextView) findViewById(R.id.title)).setText(title);
+
+ mImageView = new ImageView(this);
+ mImageView.setImageResource(R.drawable.example_big_picture);
+
+ ImageZoomView zoomView = new ImageZoomView(this, mImageView, mAnimationRange);
+ zoomView.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT));
+
+ ((FrameLayout) findViewById(R.id.container)).addView(zoomView, 0);
+
+ createNextAnimation(false);
+ }
+
+ private void createNextAnimation(boolean start) {
+ float startX = mImageView.getTranslationX();
+ float startY = mImageView.getTranslationY();
+ float endX = -mRandom.nextInt(mAnimationRange);
+ float endY = -mRandom.nextInt(mAnimationRange);
+ float distance = (float) Math.sqrt(Math.pow(endX - startX, 2) + Math.pow(endY - startY, 2));
+
+ mAnimation = ObjectAnimator.ofPropertyValuesHolder(mImageView,
+ PropertyValuesHolder.ofFloat("translationX", startX, endX),
+ PropertyValuesHolder.ofFloat("translationY", startY, endY));
+ mAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
+
+ mAnimation.setDuration(Math.max(BASE_ANIMATION_DURATION_MS / 10,
+ (int) (distance * BASE_ANIMATION_DURATION_MS / mAnimationRange)));
+
+ mAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ createNextAnimation(true);
+ }
+ });
+ if (start) {
+ mAnimation.start();
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mAnimation.start();
+ }
+
+ @Override
+ protected void onPause() {
+ mAnimation.pause();
+ super.onPause();
+ }
+
+ /** Helper view that zooms in on a child image view */
+ private static class ImageZoomView extends ViewGroup {
+ private final int mZoomLength;
+
+ public ImageZoomView(Context context, ImageView imageView, int zoomLength) {
+ super(context);
+ addView(imageView);
+ mZoomLength = zoomLength;
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ ImageView imageView = (ImageView) getChildAt(0);
+
+ // Resize the image view to be at least mZoomLength pixels larger in both
+ // dimensions than the containing view.
+ int imageWidth = imageView.getDrawable().getIntrinsicWidth();
+ int imageHeight = imageView.getDrawable().getIntrinsicHeight();
+ int minSize = Math.max(right - left, bottom - top) + mZoomLength;
+ if (imageWidth > imageHeight) {
+ imageWidth = minSize * imageWidth / imageHeight;
+ imageHeight = minSize;
+ } else {
+ imageHeight = minSize * imageHeight / imageWidth;
+ imageWidth = minSize;
+ }
+ imageView.layout(left, top, left + imageWidth, top + imageHeight);
+ }
+ }
+}
diff --git a/wearable/wear/Notifications/Wearable/src/main/java/com/example/android/notifications/BasicNotificationDisplayActivity.java b/wearable/wear/Notifications/Wearable/src/main/java/com/example/android/notifications/BasicNotificationDisplayActivity.java
new file mode 100644
index 0000000..a6cc5fb
--- /dev/null
+++ b/wearable/wear/Notifications/Wearable/src/main/java/com/example/android/notifications/BasicNotificationDisplayActivity.java
@@ -0,0 +1,38 @@
+/*
+ * 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.android.notifications;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+
+/**
+ * Custom display activity for a sample notification.
+ */
+public class BasicNotificationDisplayActivity extends Activity {
+ public static final String EXTRA_TITLE = "title";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_notification_display);
+
+ String title = getIntent().getStringExtra(EXTRA_TITLE);
+
+ ((TextView) findViewById(R.id.title)).setText(title);
+ }
+}
diff --git a/wearable/wear/Notifications/Wearable/src/main/java/com/example/android/notifications/MainActivity.java b/wearable/wear/Notifications/Wearable/src/main/java/com/example/android/notifications/MainActivity.java
new file mode 100644
index 0000000..fe7e134
--- /dev/null
+++ b/wearable/wear/Notifications/Wearable/src/main/java/com/example/android/notifications/MainActivity.java
@@ -0,0 +1,106 @@
+/*
+ * 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.android.notifications;
+
+import android.app.Activity;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.RemoteInput;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.wearable.view.WearableListView;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+import android.widget.TextView;
+import android.widget.Toast;
+
+public class MainActivity extends Activity implements WearableListView.ClickListener {
+ private static final int SAMPLE_NOTIFICATION_ID = 0;
+ public static final String KEY_REPLY = "reply";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ WearableListView listView = (WearableListView) findViewById(R.id.list);
+ listView.setAdapter(new Adapter(this));
+ listView.setClickListener(this);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ if (getIntent() != null) {
+ Bundle inputResults = RemoteInput.getResultsFromIntent(getIntent());
+ if (inputResults != null) {
+ CharSequence replyText = inputResults.getCharSequence(KEY_REPLY);
+ if (replyText != null) {
+ Toast.makeText(this, TextUtils.concat(getString(R.string.reply_was), replyText),
+ Toast.LENGTH_LONG).show();
+ }
+ }
+ }
+ }
+
+ /** Post a new or updated notification using the selected notification options. */
+ private void updateNotification(int presetIndex) {
+ NotificationPreset preset = NotificationPresets.PRESETS[presetIndex];
+ Notification notif = preset.buildNotification(this);
+ ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
+ .notify(SAMPLE_NOTIFICATION_ID, notif);
+ finish();
+ }
+
+ @Override
+ public void onClick(WearableListView.ViewHolder v) {
+ updateNotification((Integer) v.itemView.getTag());
+ }
+
+ @Override
+ public void onTopEmptyRegionClick() {
+ }
+
+ private static final class Adapter extends WearableListView.Adapter {
+ private final Context mContext;
+ private final LayoutInflater mInflater;
+
+ private Adapter(Context context) {
+ mContext = context;
+ mInflater = LayoutInflater.from(context);
+ }
+
+ @Override
+ public WearableListView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ return new WearableListView.ViewHolder(
+ mInflater.inflate(R.layout.notif_preset_list_item, null));
+ }
+
+ @Override
+ public void onBindViewHolder(WearableListView.ViewHolder holder, int position) {
+ TextView view = (TextView) holder.itemView.findViewById(R.id.name);
+ view.setText(mContext.getString(NotificationPresets.PRESETS[position].nameResId));
+ holder.itemView.setTag(position);
+ }
+
+ @Override
+ public int getItemCount() {
+ return NotificationPresets.PRESETS.length;
+ }
+ }
+}
diff --git a/wearable/wear/Notifications/Wearable/src/main/java/com/example/android/notifications/NotificationPreset.java b/wearable/wear/Notifications/Wearable/src/main/java/com/example/android/notifications/NotificationPreset.java
new file mode 100644
index 0000000..db15467
--- /dev/null
+++ b/wearable/wear/Notifications/Wearable/src/main/java/com/example/android/notifications/NotificationPreset.java
@@ -0,0 +1,34 @@
+/*
+ * 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.android.notifications;
+
+import android.app.Notification;
+import android.content.Context;
+
+/**
+ * Base class for notification preset generators.
+ */
+public abstract class NotificationPreset {
+ public final int nameResId;
+
+ public NotificationPreset(int nameResId) {
+ this.nameResId = nameResId;
+ }
+
+ /** Start building a notification with this preset */
+ public abstract Notification buildNotification(Context context);
+}
diff --git a/wearable/wear/Notifications/Wearable/src/main/java/com/example/android/notifications/NotificationPresets.java b/wearable/wear/Notifications/Wearable/src/main/java/com/example/android/notifications/NotificationPresets.java
new file mode 100644
index 0000000..04a4d15
--- /dev/null
+++ b/wearable/wear/Notifications/Wearable/src/main/java/com/example/android/notifications/NotificationPresets.java
@@ -0,0 +1,314 @@
+/*
+ * 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.android.notifications;
+
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.app.RemoteInput;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
+import android.graphics.Typeface;
+import android.net.Uri;
+import android.text.SpannableStringBuilder;
+import android.text.style.ForegroundColorSpan;
+import android.text.style.RelativeSizeSpan;
+import android.text.style.StrikethroughSpan;
+import android.text.style.StyleSpan;
+import android.text.style.SubscriptSpan;
+import android.text.style.SuperscriptSpan;
+import android.text.style.TypefaceSpan;
+import android.text.style.UnderlineSpan;
+import android.util.TypedValue;
+import android.view.Gravity;
+
+/**
+ * Collection of notification builder presets.
+ */
+public class NotificationPresets {
+ public static final NotificationPreset[] PRESETS = new NotificationPreset[] {
+ new BasicPreset(),
+ new StylizedTextPreset(),
+ new DisplayIntentPreset(),
+ new MultiSizeDisplayIntentPreset(),
+ new AnimatedDisplayIntentPreset(),
+ new ContentIconPreset()
+ };
+
+ private static Notification.Builder buildBasicNotification(Context context) {
+ return new Notification.Builder(context)
+ .setContentTitle(context.getString(R.string.example_content_title))
+ .setContentText(context.getString(R.string.example_content_text))
+ // Set a content intent to return to this sample
+ .setContentIntent(PendingIntent.getActivity(context, 0,
+ new Intent(context, MainActivity.class), 0))
+ .setSmallIcon(R.mipmap.ic_launcher);
+ }
+
+ private static class BasicPreset extends NotificationPreset {
+ public BasicPreset() {
+ super(R.string.basic_example);
+ }
+
+ @Override
+ public Notification buildNotification(Context context) {
+ PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
+ new Intent(context, MainActivity.class), 0);
+
+ Notification page2 = buildBasicNotification(context)
+ .extend(new Notification.WearableExtender()
+ .setHintShowBackgroundOnly(true)
+ .setBackground(BitmapFactory.decodeResource(context.getResources(),
+ R.drawable.example_big_picture)))
+ .build();
+
+ Notification page3 = buildBasicNotification(context)
+ .setContentTitle(context.getString(R.string.third_page))
+ .setContentText(null)
+ .extend(new Notification.WearableExtender()
+ .setContentAction(0 /* action A */))
+ .build();
+
+ SpannableStringBuilder choice2 = new SpannableStringBuilder(
+ "This choice is best");
+ choice2.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), 5, 11, 0);
+
+ return buildBasicNotification(context)
+ .extend(new Notification.WearableExtender()
+ .addAction(new Notification.Action(R.mipmap.ic_launcher,
+ context.getString(R.string.action_a), pendingIntent))
+ .addAction(new Notification.Action.Builder(R.mipmap.ic_launcher,
+ context.getString(R.string.reply), pendingIntent)
+ .addRemoteInput(new RemoteInput.Builder(MainActivity.KEY_REPLY)
+ .setChoices(new CharSequence[] {
+ context.getString(R.string.choice_1),
+ choice2 })
+ .build())
+ .build())
+ .addPage(page2)
+ .addPage(page3))
+ .build();
+ }
+ }
+
+ private static class StylizedTextPreset extends NotificationPreset {
+ public StylizedTextPreset() {
+ super(R.string.stylized_text_example);
+ }
+
+ @Override
+ public Notification buildNotification(Context context) {
+ Notification.Builder builder = buildBasicNotification(context);
+
+ Notification.BigTextStyle style = new Notification.BigTextStyle();
+
+ SpannableStringBuilder title = new SpannableStringBuilder();
+ appendStyled(title, "Stylized", new StyleSpan(Typeface.BOLD_ITALIC));
+ title.append(" title");
+ SpannableStringBuilder text = new SpannableStringBuilder("Stylized text: ");
+ appendStyled(text, "C", new ForegroundColorSpan(Color.RED));
+ appendStyled(text, "O", new ForegroundColorSpan(Color.GREEN));
+ appendStyled(text, "L", new ForegroundColorSpan(Color.BLUE));
+ appendStyled(text, "O", new ForegroundColorSpan(Color.YELLOW));
+ appendStyled(text, "R", new ForegroundColorSpan(Color.MAGENTA));
+ appendStyled(text, "S", new ForegroundColorSpan(Color.CYAN));
+ text.append("; ");
+ appendStyled(text, "1.25x size", new RelativeSizeSpan(1.25f));
+ text.append("; ");
+ appendStyled(text, "0.75x size", new RelativeSizeSpan(0.75f));
+ text.append("; ");
+ appendStyled(text, "underline", new UnderlineSpan());
+ text.append("; ");
+ appendStyled(text, "strikethrough", new StrikethroughSpan());
+ text.append("; ");
+ appendStyled(text, "bold", new StyleSpan(Typeface.BOLD));
+ text.append("; ");
+ appendStyled(text, "italic", new StyleSpan(Typeface.ITALIC));
+ text.append("; ");
+ appendStyled(text, "sans-serif-thin", new TypefaceSpan("sans-serif-thin"));
+ text.append("; ");
+ appendStyled(text, "monospace", new TypefaceSpan("monospace"));
+ text.append("; ");
+ appendStyled(text, "sub", new SubscriptSpan());
+ text.append("script");
+ appendStyled(text, "super", new SuperscriptSpan());
+
+ style.setBigContentTitle(title);
+ style.bigText(text);
+
+ builder.setStyle(style);
+ return builder.build();
+ }
+
+ private void appendStyled(SpannableStringBuilder builder, String str, Object... spans) {
+ builder.append(str);
+ for (Object span : spans) {
+ builder.setSpan(span, builder.length() - str.length(), builder.length(), 0);
+ }
+ }
+ }
+
+ private static class DisplayIntentPreset extends NotificationPreset {
+ public DisplayIntentPreset() {
+ super(R.string.display_intent_example);
+ }
+
+ @Override
+ public Notification buildNotification(Context context) {
+ Intent displayIntent = new Intent(context, BasicNotificationDisplayActivity.class);
+ displayIntent.putExtra(BasicNotificationDisplayActivity.EXTRA_TITLE,
+ context.getString(nameResId));
+ PendingIntent displayPendingIntent = PendingIntent.getActivity(context,
+ 0, displayIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ return buildBasicNotification(context)
+ .extend(new Notification.WearableExtender()
+ .setDisplayIntent(displayPendingIntent))
+ .build();
+ }
+ }
+
+ private static class MultiSizeDisplayIntentPreset extends NotificationPreset {
+ public MultiSizeDisplayIntentPreset() {
+ super(R.string.multisize_display_intent_example);
+ }
+
+ @Override
+ public Notification buildNotification(Context context) {
+ PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
+ new Intent(context, MainActivity.class), 0);
+ Intent displayIntent = new Intent(context, BasicNotificationDisplayActivity.class)
+ .putExtra(BasicNotificationDisplayActivity.EXTRA_TITLE,
+ context.getString(R.string.xsmall_sized_display));
+ return buildBasicNotification(context)
+ .extend(new Notification.WearableExtender()
+ .setDisplayIntent(PendingIntent.getActivity(context, 0, displayIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT))
+ .addPage(createPageForSizePreset(context,
+ Notification.WearableExtender.SIZE_SMALL,
+ R.string.small_sized_display, 0))
+ .addPage(createPageForSizePreset(context,
+ Notification.WearableExtender.SIZE_MEDIUM,
+ R.string.medium_sized_display, 1))
+ .addPage(createPageForSizePreset(context,
+ Notification.WearableExtender.SIZE_LARGE,
+ R.string.large_sized_display, 2))
+ .addPage(createPageForSizePreset(context,
+ Notification.WearableExtender.SIZE_FULL_SCREEN,
+ R.string.full_screen_display, 3))
+ .addPage(createPageForCustomHeight(context, 256,
+ R.string.dp256_height_display))
+ .addPage(createPageForCustomHeight(context, 512,
+ R.string.dp512_height_display))
+ .addAction(new Notification.Action(R.mipmap.ic_launcher,
+ context.getString(R.string.action_a), pendingIntent))
+ .addAction(new Notification.Action(R.mipmap.ic_launcher,
+ context.getString(R.string.action_b), pendingIntent))
+ .addAction(new Notification.Action(R.mipmap.ic_launcher,
+ context.getString(R.string.action_c), pendingIntent))
+ .addAction(new Notification.Action(R.mipmap.ic_launcher,
+ context.getString(R.string.action_d), pendingIntent))
+ .setCustomSizePreset(Notification.WearableExtender.SIZE_XSMALL))
+ .build();
+ }
+
+ private Notification createPageForCustomHeight(Context context, int heightDisplayDp,
+ int pageNameResId) {
+ int contentHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+ heightDisplayDp, context.getResources().getDisplayMetrics());
+ Intent displayIntent = new Intent(context, BasicNotificationDisplayActivity.class)
+ .setData(Uri.fromParts("example", "height/" + heightDisplayDp, null))
+ .putExtra(BasicNotificationDisplayActivity.EXTRA_TITLE,
+ context.getString(pageNameResId));
+ return buildBasicNotification(context)
+ .extend(new Notification.WearableExtender()
+ .setDisplayIntent(PendingIntent.getActivity(context, 0, displayIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT))
+ .setCustomContentHeight(contentHeight))
+ .build();
+ }
+
+ private Notification createPageForSizePreset(Context context, int sizePreset,
+ int pageNameResId, int contentAction) {
+ Intent displayIntent = new Intent(context, BasicNotificationDisplayActivity.class)
+ .setData(Uri.fromParts("example", "size/" + sizePreset, null))
+ .putExtra(BasicNotificationDisplayActivity.EXTRA_TITLE,
+ context.getString(pageNameResId));
+ return buildBasicNotification(context)
+ .extend(new Notification.WearableExtender()
+ .setDisplayIntent(PendingIntent.getActivity(context, 0, displayIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT))
+ .setCustomSizePreset(sizePreset)
+ .setContentAction(contentAction))
+ .build();
+ }
+ }
+
+ private static class AnimatedDisplayIntentPreset extends NotificationPreset {
+ public AnimatedDisplayIntentPreset() {
+ super(R.string.animated_display_intent_example);
+ }
+
+ @Override
+ public Notification buildNotification(Context context) {
+ Intent displayIntent = new Intent(context, AnimatedNotificationDisplayActivity.class);
+ displayIntent.putExtra(BasicNotificationDisplayActivity.EXTRA_TITLE,
+ context.getString(nameResId));
+ PendingIntent displayPendingIntent = PendingIntent.getActivity(context,
+ 0, displayIntent, 0);
+ return buildBasicNotification(context)
+ .extend(new Notification.WearableExtender()
+ .setDisplayIntent(displayPendingIntent))
+ .build();
+ }
+ }
+
+ private static class ContentIconPreset extends NotificationPreset {
+ public ContentIconPreset() {
+ super(R.string.content_icon_example);
+ }
+
+ @Override
+ public Notification buildNotification(Context context) {
+ Notification page2 = buildBasicNotification(context)
+ .extend(new Notification.WearableExtender()
+ .setContentIcon(R.drawable.content_icon_small)
+ .setContentIconGravity(Gravity.START))
+ .build();
+
+ Notification page3 = buildBasicNotification(context)
+ .extend(new Notification.WearableExtender()
+ .setContentIcon(R.drawable.content_icon_large))
+ .build();
+
+ Notification page4 = buildBasicNotification(context)
+ .extend(new Notification.WearableExtender()
+ .setContentIcon(R.drawable.content_icon_large)
+ .setContentIconGravity(Gravity.START))
+ .build();
+
+ return buildBasicNotification(context)
+ .extend(new Notification.WearableExtender()
+ .setHintHideIcon(true)
+ .setContentIcon(R.drawable.content_icon_small)
+ .addPage(page2)
+ .addPage(page3)
+ .addPage(page4))
+ .build();
+ }
+ }
+}
diff --git a/wearable/wear/Notifications/Wearable/src/main/java/com/example/android/notifications/WearableListItemLayout.java b/wearable/wear/Notifications/Wearable/src/main/java/com/example/android/notifications/WearableListItemLayout.java
new file mode 100644
index 0000000..cb08a9c
--- /dev/null
+++ b/wearable/wear/Notifications/Wearable/src/main/java/com/example/android/notifications/WearableListItemLayout.java
@@ -0,0 +1,91 @@
+/*
+ * 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.android.notifications;
+
+import android.content.Context;
+import android.graphics.drawable.GradientDrawable;
+import android.support.wearable.view.WearableListView;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+public class WearableListItemLayout extends LinearLayout implements WearableListView.Item {
+
+ private final float mFadedTextAlpha;
+ private final int mFadedCircleColor;
+ private final int mChosenCircleColor;
+ private ImageView mCircle;
+ private float mScale;
+ private TextView mName;
+
+ public WearableListItemLayout(Context context) {
+ this(context, null);
+ }
+
+ public WearableListItemLayout(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public WearableListItemLayout(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ mFadedTextAlpha = getResources().getInteger(R.integer.action_text_faded_alpha) / 100f;
+ mFadedCircleColor = getResources().getColor(R.color.wl_gray);
+ mChosenCircleColor = getResources().getColor(R.color.wl_blue);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mCircle = (ImageView) findViewById(R.id.circle);
+ mName = (TextView) findViewById(R.id.name);
+ }
+
+ @Override
+ public float getProximityMinValue() {
+ return 1f;
+ }
+
+ @Override
+ public float getProximityMaxValue() {
+ return 1.6f;
+ }
+
+ @Override
+ public float getCurrentProximityValue() {
+ return mScale;
+ }
+
+ @Override
+ public void setScalingAnimatorValue(float scale) {
+ mScale = scale;
+ mCircle.setScaleX(scale);
+ mCircle.setScaleY(scale);
+ }
+
+ @Override
+ public void onScaleUpStart() {
+ mName.setAlpha(1f);
+ ((GradientDrawable) mCircle.getDrawable()).setColor(mChosenCircleColor);
+ }
+
+ @Override
+ public void onScaleDownStart() {
+ ((GradientDrawable) mCircle.getDrawable()).setColor(mFadedCircleColor);
+ mName.setAlpha(mFadedTextAlpha);
+ }
+}
diff --git a/wearable/wear/Notifications/Wearable/src/main/res/drawable-nodpi/content_icon_large.png b/wearable/wear/Notifications/Wearable/src/main/res/drawable-nodpi/content_icon_large.png
new file mode 100644
index 0000000..0eab3b1
--- /dev/null
+++ b/wearable/wear/Notifications/Wearable/src/main/res/drawable-nodpi/content_icon_large.png
Binary files differ
diff --git a/wearable/wear/Notifications/Wearable/src/main/res/drawable-nodpi/content_icon_small.png b/wearable/wear/Notifications/Wearable/src/main/res/drawable-nodpi/content_icon_small.png
new file mode 100644
index 0000000..9a9f4b4
--- /dev/null
+++ b/wearable/wear/Notifications/Wearable/src/main/res/drawable-nodpi/content_icon_small.png
Binary files differ
diff --git a/wearable/wear/Notifications/Wearable/src/main/res/drawable-nodpi/example_big_picture.jpg b/wearable/wear/Notifications/Wearable/src/main/res/drawable-nodpi/example_big_picture.jpg
new file mode 100644
index 0000000..68473ba
--- /dev/null
+++ b/wearable/wear/Notifications/Wearable/src/main/res/drawable-nodpi/example_big_picture.jpg
Binary files differ
diff --git a/wearable/wear/Notifications/Wearable/src/main/res/drawable/wl_circle.xml b/wearable/wear/Notifications/Wearable/src/main/res/drawable/wl_circle.xml
new file mode 100644
index 0000000..7c9708e
--- /dev/null
+++ b/wearable/wear/Notifications/Wearable/src/main/res/drawable/wl_circle.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval">
+ <solid android:color="@color/wl_gray"/>
+</shape>
diff --git a/wearable/wear/Notifications/Wearable/src/main/res/layout/activity_animated_notification_display.xml b/wearable/wear/Notifications/Wearable/src/main/res/layout/activity_animated_notification_display.xml
new file mode 100644
index 0000000..be70b2b
--- /dev/null
+++ b/wearable/wear/Notifications/Wearable/src/main/res/layout/activity_animated_notification_display.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/container"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <TextView android:id="@+id/title"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:textSize="16sp"
+ android:padding="8dp"
+ android:gravity="center_vertical|center_horizontal"
+ android:textColor="#FF3333"
+ android:shadowColor="#992222"
+ android:shadowRadius="2"
+ android:shadowDx="1"
+ android:shadowDy="1" />
+
+</FrameLayout>
diff --git a/wearable/wear/Notifications/Wearable/src/main/res/layout/activity_main.xml b/wearable/wear/Notifications/Wearable/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..9ae6026
--- /dev/null
+++ b/wearable/wear/Notifications/Wearable/src/main/res/layout/activity_main.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<android.support.wearable.view.WearableListView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scrollbars="none"
+ android:dividerHeight="0dp"/>
diff --git a/wearable/wear/Notifications/Wearable/src/main/res/layout/activity_notification_display.xml b/wearable/wear/Notifications/Wearable/src/main/res/layout/activity_notification_display.xml
new file mode 100644
index 0000000..7a329d2
--- /dev/null
+++ b/wearable/wear/Notifications/Wearable/src/main/res/layout/activity_notification_display.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <TextView android:id="@+id/title"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:textSize="16sp"
+ android:padding="8dp"
+ android:gravity="center_vertical|center_horizontal"
+ android:textColor="#7777FF"
+ android:shadowColor="#222299"
+ android:shadowRadius="2"
+ android:shadowDx="1"
+ android:shadowDy="1"
+ />
+
+</LinearLayout>
diff --git a/wearable/wear/Notifications/Wearable/src/main/res/layout/notif_preset_list_item.xml b/wearable/wear/Notifications/Wearable/src/main/res/layout/notif_preset_list_item.xml
new file mode 100644
index 0000000..9e3cd45
--- /dev/null
+++ b/wearable/wear/Notifications/Wearable/src/main/res/layout/notif_preset_list_item.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<com.example.android.support.wearable.notifications.WearableListItemLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:gravity="center_vertical"
+ android:layout_width="match_parent"
+ android:layout_height="80dp">
+ <ImageView
+ android:id="@+id/circle"
+ android:layout_height="20dp"
+ android:layout_margin="16dp"
+ android:layout_width="20dp"
+ android:src="@drawable/wl_circle"/>
+ <TextView
+ android:id="@+id/name"
+ android:gravity="center_vertical|left"
+ android:layout_width="wrap_content"
+ android:layout_marginRight="16dp"
+ android:layout_height="match_parent"
+ android:fontFamily="sans-serif-condensed-light"
+ android:lineSpacingExtra="-4sp"
+ android:textColor="@color/text_color"
+ android:textSize="16sp"/>
+</com.example.android.support.wearable.notifications.WearableListItemLayout>
diff --git a/wearable/wear/Notifications/Wearable/src/main/res/mipmap-hdpi/ic_launcher.png b/wearable/wear/Notifications/Wearable/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..41479de
--- /dev/null
+++ b/wearable/wear/Notifications/Wearable/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Notifications/Wearable/src/main/res/mipmap-mdpi/ic_launcher.png b/wearable/wear/Notifications/Wearable/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..380b02f
--- /dev/null
+++ b/wearable/wear/Notifications/Wearable/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Notifications/Wearable/src/main/res/mipmap-xhdpi/ic_launcher.png b/wearable/wear/Notifications/Wearable/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..b3e251e
--- /dev/null
+++ b/wearable/wear/Notifications/Wearable/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Notifications/Wearable/src/main/res/mipmap-xxhdpi/ic_launcher.png b/wearable/wear/Notifications/Wearable/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..1962289
--- /dev/null
+++ b/wearable/wear/Notifications/Wearable/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Notifications/Wearable/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/wearable/wear/Notifications/Wearable/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..163f1f0
--- /dev/null
+++ b/wearable/wear/Notifications/Wearable/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Notifications/Wearable/src/main/res/values/colors.xml b/wearable/wear/Notifications/Wearable/src/main/res/values/colors.xml
new file mode 100644
index 0000000..10fad66
--- /dev/null
+++ b/wearable/wear/Notifications/Wearable/src/main/res/values/colors.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+ <color name="wl_blue">#2878ff</color>
+ <color name="wl_gray">#c1c1c1</color>
+ <color name="text_color">#434343</color>
+</resources>
diff --git a/wearable/wear/Notifications/Wearable/src/main/res/values/dimens.xml b/wearable/wear/Notifications/Wearable/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..50214e6
--- /dev/null
+++ b/wearable/wear/Notifications/Wearable/src/main/res/values/dimens.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+ <dimen name="animation_range">60dp</dimen>
+
+</resources>
diff --git a/wearable/wear/Notifications/Wearable/src/main/res/values/integers.xml b/wearable/wear/Notifications/Wearable/src/main/res/values/integers.xml
new file mode 100644
index 0000000..1dfb011
--- /dev/null
+++ b/wearable/wear/Notifications/Wearable/src/main/res/values/integers.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+ <integer name="action_text_faded_alpha">40</integer>
+</resources>
diff --git a/wearable/wear/Notifications/Wearable/src/main/res/values/strings.xml b/wearable/wear/Notifications/Wearable/src/main/res/values/strings.xml
new file mode 100644
index 0000000..ff7023b
--- /dev/null
+++ b/wearable/wear/Notifications/Wearable/src/main/res/values/strings.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+
+ <string name="app_name">Wearable Notifications</string>
+ <string name="basic_example">Basic example</string>
+ <string name="stylized_text_example">Stylized text example</string>
+ <string name="display_intent_example">Display intent example</string>
+ <string name="multisize_display_intent_example">Multiple-sized display intent example</string>
+ <string name="animated_display_intent_example">Animated display intent example</string>
+ <string name="content_icon_example">Content icon example</string>
+
+ <string name="example_content_title">Example content title</string>
+ <string name="example_content_text">Example content text</string>
+
+ <string name="xsmall_sized_display">X-Small sized display</string>
+ <string name="small_sized_display">Small sized display</string>
+ <string name="medium_sized_display">Medium sized display</string>
+ <string name="large_sized_display">Large sized display</string>
+ <string name="full_screen_display">Full-Screen display</string>
+ <string name="dp256_height_display">256dp height display</string>
+ <string name="dp512_height_display">512dp height display</string>
+
+ <string name="action_a">Action A</string>
+ <string name="action_b">Action B</string>
+ <string name="action_c">Action C</string>
+ <string name="action_d">Action D</string>
+ <string name="reply">Reply</string>
+ <string name="reply_was">Reply was: </string>
+ <string name="third_page">Third page</string>
+ <string name="choice_1">Choice #1</string>
+</resources>
diff --git a/wearable/wear/Notifications/build.gradle b/wearable/wear/Notifications/build.gradle
new file mode 100644
index 0000000..be1fa82
--- /dev/null
+++ b/wearable/wear/Notifications/build.gradle
@@ -0,0 +1,14 @@
+
+
+
+
+// BEGIN_EXCLUDE
+import com.example.android.samples.build.SampleGenPlugin
+apply plugin: SampleGenPlugin
+
+samplegen {
+ pathToBuild "../../../../../build"
+ pathToSamplesCommon "../../../common"
+}
+apply from: "../../../../../build/build.gradle"
+// END_EXCLUDE
diff --git a/wearable/wear/Notifications/buildSrc/build.gradle b/wearable/wear/Notifications/buildSrc/build.gradle
new file mode 100644
index 0000000..e344a8c
--- /dev/null
+++ b/wearable/wear/Notifications/buildSrc/build.gradle
@@ -0,0 +1,18 @@
+
+
+
+repositories {
+ mavenCentral()
+}
+dependencies {
+ compile 'org.freemarker:freemarker:2.3.20'
+}
+
+sourceSets {
+ main {
+ groovy {
+ srcDir new File(rootDir, "../../../../../../build/buildSrc/src/main/groovy")
+ }
+ }
+}
+
diff --git a/wearable/wear/Notifications/gradle/wrapper/gradle-wrapper.jar b/wearable/wear/Notifications/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8c0fb64
--- /dev/null
+++ b/wearable/wear/Notifications/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/wearable/wear/Notifications/gradle/wrapper/gradle-wrapper.properties b/wearable/wear/Notifications/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..d7f03cf
--- /dev/null
+++ b/wearable/wear/Notifications/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=http\://services.gradle.org/distributions/gradle-1.12-bin.zip
diff --git a/wearable/wear/Notifications/gradlew b/wearable/wear/Notifications/gradlew
new file mode 100755
index 0000000..91a7e26
--- /dev/null
+++ b/wearable/wear/Notifications/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/wearable/wear/Notifications/gradlew.bat b/wearable/wear/Notifications/gradlew.bat
new file mode 100644
index 0000000..8a0b282
--- /dev/null
+++ b/wearable/wear/Notifications/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/wearable/wear/Notifications/settings.gradle b/wearable/wear/Notifications/settings.gradle
new file mode 100644
index 0000000..8522c57
--- /dev/null
+++ b/wearable/wear/Notifications/settings.gradle
@@ -0,0 +1 @@
+include ':Application', ':Wearable', ':Shared'
diff --git a/wearable/wear/Notifications/template-params.xml b/wearable/wear/Notifications/template-params.xml
new file mode 100644
index 0000000..f715675
--- /dev/null
+++ b/wearable/wear/Notifications/template-params.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+
+
+<sample>
+ <name>Notifications</name>
+ <group>Connectivity</group>
+ <package>com.example.android.notifications</package>
+
+
+
+ <!-- change minSdk if needed-->
+ <minSdk>20</minSdk>
+
+
+ <strings>
+ <intro>
+ <![CDATA[
+This sample application provides a showcase of available notification styles and
+demonstrates various features of the Android Wear notifications API. Running the sample on your
+companion allows you to select between various notification styles and to see how these
+notifications are displayed, both in a phone\'s notification shade and on the wearable.
+ ]]>
+ </intro>
+ </strings>
+
+ <template src="base"/>
+ <template src="Wear"/>
+ <common src="logger"/>
+ <common src="activities"/>
+
+</sample>
diff --git a/wearable/wear/Quiz/Application/.gitignore b/wearable/wear/Quiz/Application/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/Quiz/Application/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/Quiz/Application/proguard-project.txt b/wearable/wear/Quiz/Application/proguard-project.txt
new file mode 100644
index 0000000..0d8f171
--- /dev/null
+++ b/wearable/wear/Quiz/Application/proguard-project.txt
@@ -0,0 +1,20 @@
+ To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# 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/wearable/wear/Quiz/Application/src/main/AndroidManifest.xml b/wearable/wear/Quiz/Application/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..40e3602
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/AndroidManifest.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.quiz" >
+
+ <uses-sdk android:minSdkVersion="19"
+ android:targetSdkVersion="19" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme">
+ <meta-data android:name="com.google.android.gms.version"
+ android:value="@integer/google_play_services_version" />
+
+ <activity
+ android:name="com.example.android.quiz.MainActivity"
+ android:label="@string/app_name"
+ android:windowSoftInputMode="stateHidden"
+ android:configChanges="keyboardHidden|orientation|screenSize" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ </application>
+
+</manifest>
diff --git a/wearable/wear/Quiz/Application/src/main/assets/Quiz.json b/wearable/wear/Quiz/Application/src/main/assets/Quiz.json
new file mode 100644
index 0000000..db2448d
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/assets/Quiz.json
@@ -0,0 +1,124 @@
+{
+"questions": [
+{
+"question": "What is the scientific name of a butterfly?",
+"answers": [
+"Apis",
+"Coleoptera",
+"Formicidae",
+"Rhopalocera"
+],
+"correctIndex": 3
+},
+{
+"question": "How hot is the surface of the sun?",
+"answers": [
+"1,233 K",
+"5,778 K",
+"12,130 K",
+"101,300 K"
+],
+"correctIndex": 1
+},
+{
+"question": "Who are the actors in The Internship?",
+"answers": [
+"Ben Stiller, Jonah Hill",
+"Courteney Cox, Matt LeBlanc",
+"Kaley Cuoco, Jim Parsons",
+"Vince Vaughn, Owen Wilson"
+],
+"correctIndex": 3
+},
+{
+"question": "What is the capital of Spain?",
+"answers": [
+"Berlin",
+"Buenos Aires",
+"Madrid",
+"San Juan"
+],
+"correctIndex": 2
+},
+{
+"question": "What are the school colors of the University of Texas at Austin?",
+"answers": [
+"Black, Red",
+"Blue, Orange",
+"White, Burnt Orange",
+"White, Old gold, Gold"
+],
+"correctIndex": 2
+},
+{
+"question": "What is 70 degrees Fahrenheit in Celsius?",
+"answers": [
+"18.8889",
+"20",
+"21.1111",
+"158"
+],
+"correctIndex": 2
+},
+{
+"question": "When was Mahatma Gandhi born?",
+"answers": [
+"October 2, 1869",
+"December 15, 1872",
+"July 18, 1918",
+"January 15, 1929"
+],
+"correctIndex": 0
+},
+{
+"question": "How far is the moon from Earth?",
+"answers": [
+"7,918 miles (12,742 km)",
+"86,881 miles (139,822 km)",
+"238,400 miles (384,400 km)",
+"35,980,000 miles (57,910,000 km)"
+],
+"correctIndex": 2
+},
+{
+"question": "What is 65 times 52?",
+"answers": [
+"117",
+"3120",
+"3380",
+"3520"
+],
+"correctIndex": 2
+},
+{
+"question": "How tall is Mount Everest?",
+"answers": [
+"6,683 ft (2,037 m)",
+"7,918 ft (2,413 m)",
+"19,341 ft (5,895 m)",
+"29,029 ft (8,847 m)"
+],
+"correctIndex": 3
+},
+{
+"question": "When did The Avengers come out?",
+"answers": [
+"May 2, 2008",
+"May 4, 2012",
+"May 3, 2013",
+"April 4, 2014"
+],
+"correctIndex": 1
+},
+{
+"question": "What is 48,879 in hexidecimal?",
+"answers": [
+"0x18C1",
+"0xBEEF",
+"0xDEAD",
+"0x12D591"
+],
+"correctIndex": 1
+}
+]
+}
\ No newline at end of file
diff --git a/wearable/wear/Quiz/Application/src/main/java/com/example/android/quiz/Constants.java b/wearable/wear/Quiz/Application/src/main/java/com/example/android/quiz/Constants.java
new file mode 100644
index 0000000..ea5c56b
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/java/com/example/android/quiz/Constants.java
@@ -0,0 +1,39 @@
+/*
+ * 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.android.quiz;
+
+/** Constants used in the companion app. */
+public final class Constants {
+ private Constants() {
+ }
+
+ public static final String ANSWERS = "answers";
+ public static final String CHOSEN_ANSWER_CORRECT = "chosen_answer_correct";
+ public static final String CORRECT_ANSWER_INDEX = "correct_answer_index";
+ public static final String QUESTION = "question";
+ public static final String QUESTION_INDEX = "question_index";
+ public static final String QUESTION_WAS_ANSWERED = "question_was_answered";
+ public static final String QUESTION_WAS_DELETED = "question_was_deleted";
+
+ public static final String NUM_CORRECT = "num_correct";
+ public static final String NUM_INCORRECT = "num_incorrect";
+ public static final String NUM_SKIPPED = "num_skipped";
+
+ public static final String QUIZ_ENDED_PATH = "/quiz_ended";
+ public static final String QUIZ_EXITED_PATH = "/quiz_exited";
+ public static final String RESET_QUIZ_PATH = "/reset_quiz";
+}
diff --git a/wearable/wear/Quiz/Application/src/main/java/com/example/android/quiz/JsonUtils.java b/wearable/wear/Quiz/Application/src/main/java/com/example/android/quiz/JsonUtils.java
new file mode 100644
index 0000000..a0f98c1
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/java/com/example/android/quiz/JsonUtils.java
@@ -0,0 +1,47 @@
+/*
+ * 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.android.quiz;
+
+import android.content.Context;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+final class JsonUtils {
+ public static final String JSON_FIELD_QUESTIONS = "questions";
+ public static final String JSON_FIELD_QUESTION = "question";
+ public static final String JSON_FIELD_ANSWERS = "answers";
+ public static final String JSON_FIELD_CORRECT_INDEX = "correctIndex";
+ public static final int NUM_ANSWER_CHOICES = 4;
+
+ private JsonUtils() {
+ }
+
+ public static JSONObject loadJsonFile(Context context, String fileName) throws IOException,
+ JSONException {
+ InputStream is = context.getAssets().open(fileName);
+ int size = is.available();
+ byte[] buffer = new byte[size];
+ is.read(buffer);
+ is.close();
+ String jsonString = new String(buffer);
+ return new JSONObject(jsonString);
+ }
+}
diff --git a/wearable/wear/Quiz/Application/src/main/java/com/example/android/quiz/MainActivity.java b/wearable/wear/Quiz/Application/src/main/java/com/example/android/quiz/MainActivity.java
new file mode 100644
index 0000000..ab8e3b4
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/java/com/example/android/quiz/MainActivity.java
@@ -0,0 +1,585 @@
+/*
+ * 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.android.quiz;
+
+import static com.example.android.quiz.Constants.ANSWERS;
+import static com.example.android.quiz.Constants.CHOSEN_ANSWER_CORRECT;
+import static com.example.android.quiz.Constants.CORRECT_ANSWER_INDEX;
+import static com.example.android.quiz.Constants.NUM_CORRECT;
+import static com.example.android.quiz.Constants.NUM_INCORRECT;
+import static com.example.android.quiz.Constants.NUM_SKIPPED;
+import static com.example.android.quiz.Constants.QUESTION;
+import static com.example.android.quiz.Constants.QUESTION_INDEX;
+import static com.example.android.quiz.Constants.QUESTION_WAS_ANSWERED;
+import static com.example.android.quiz.Constants.QUESTION_WAS_DELETED;
+import static com.example.android.quiz.Constants.QUIZ_ENDED_PATH;
+import static com.example.android.quiz.Constants.QUIZ_EXITED_PATH;
+import static com.example.android.quiz.Constants.RESET_QUIZ_PATH;
+
+import android.app.Activity;
+import android.graphics.Color;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.RadioGroup;
+import android.widget.TextView;
+
+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.ResultCallback;
+import com.google.android.gms.common.data.FreezableUtils;
+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.DataItem;
+import com.google.android.gms.wearable.DataItemBuffer;
+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.MessageEvent;
+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 org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.PriorityQueue;
+
+/**
+ * Allows the user to create questions, which will be put as notifications on the watch's stream.
+ * The status of questions will be updated on the phone when the user answers them.
+ */
+public class MainActivity extends Activity implements DataApi.DataListener,
+ MessageApi.MessageListener, ConnectionCallbacks,
+ GoogleApiClient.OnConnectionFailedListener {
+
+ private static final String TAG = "ExampleQuizApp";
+ private static final String QUIZ_JSON_FILE = "Quiz.json";
+
+ // Various UI components.
+ private EditText questionEditText;
+ private EditText choiceAEditText;
+ private EditText choiceBEditText;
+ private EditText choiceCEditText;
+ private EditText choiceDEditText;
+ private RadioGroup choicesRadioGroup;
+ private TextView quizStatus;
+ private LinearLayout quizButtons;
+ private LinearLayout questionsContainer;
+ private Button readQuizFromFileButton;
+ private Button resetQuizButton;
+
+ private GoogleApiClient mGoogleApiClient;
+ private PriorityQueue<Question> mFutureQuestions;
+ private int mQuestionIndex = 0;
+ private boolean mHasQuestionBeenAsked = false;
+
+ // Data to display in end report.
+ private int mNumCorrect = 0;
+ private int mNumIncorrect = 0;
+ private int mNumSkipped = 0;
+
+ private static final Map<Integer, Integer> radioIdToIndex;
+
+ static {
+ Map<Integer, Integer> temp = new HashMap<Integer, Integer>(4);
+ temp.put(R.id.choice_a_radio, 0);
+ temp.put(R.id.choice_b_radio, 1);
+ temp.put(R.id.choice_c_radio, 2);
+ temp.put(R.id.choice_d_radio, 3);
+ radioIdToIndex = Collections.unmodifiableMap(temp);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+
+ mGoogleApiClient = new GoogleApiClient.Builder(this)
+ .addApi(Wearable.API)
+ .addConnectionCallbacks(this)
+ .addOnConnectionFailedListener(this)
+ .build();
+ mFutureQuestions = new PriorityQueue<Question>(10);
+
+ // Find UI components to be used later.
+ questionEditText = (EditText) findViewById(R.id.question_text);
+ choiceAEditText = (EditText) findViewById(R.id.choice_a_text);
+ choiceBEditText = (EditText) findViewById(R.id.choice_b_text);
+ choiceCEditText = (EditText) findViewById(R.id.choice_c_text);
+ choiceDEditText = (EditText) findViewById(R.id.choice_d_text);
+ choicesRadioGroup = (RadioGroup) findViewById(R.id.choices_radio_group);
+ quizStatus = (TextView) findViewById(R.id.quiz_status);
+ quizButtons = (LinearLayout) findViewById(R.id.quiz_buttons);
+ questionsContainer = (LinearLayout) findViewById(R.id.questions_container);
+ readQuizFromFileButton = (Button) findViewById(R.id.read_quiz_from_file_button);
+ resetQuizButton = (Button) findViewById(R.id.reset_quiz_button);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ if (!mGoogleApiClient.isConnected()) {
+ mGoogleApiClient.connect();
+ }
+ }
+
+ @Override
+ protected void onStop() {
+ Wearable.DataApi.removeListener(mGoogleApiClient, this);
+ Wearable.MessageApi.removeListener(mGoogleApiClient, this);
+
+ // Tell the wearable to end the quiz (counting unanswered questions as skipped), and then
+ // disconnect mGoogleApiClient.
+ DataMap dataMap = new DataMap();
+ dataMap.putInt(NUM_CORRECT, mNumCorrect);
+ dataMap.putInt(NUM_INCORRECT, mNumIncorrect);
+ if (mHasQuestionBeenAsked) {
+ mNumSkipped += 1;
+ }
+ mNumSkipped += mFutureQuestions.size();
+ dataMap.putInt(NUM_SKIPPED, mNumSkipped);
+ if (mNumCorrect + mNumIncorrect + mNumSkipped > 0) {
+ sendMessageToWearable(QUIZ_EXITED_PATH, dataMap.toByteArray());
+ }
+
+ clearQuizStatus();
+ super.onStop();
+ }
+
+ @Override
+ public void onConnected(Bundle connectionHint) {
+ Wearable.DataApi.addListener(mGoogleApiClient, this);
+ Wearable.MessageApi.addListener(mGoogleApiClient, this);
+ }
+
+ @Override
+ public void onConnectionSuspended(int cause) {
+ // Ignore
+ }
+
+ @Override
+ public void onConnectionFailed(ConnectionResult result) {
+ Log.e(TAG, "Failed to connect to Google Play Services");
+ }
+
+ @Override
+ public void onMessageReceived(MessageEvent messageEvent) {
+ if (messageEvent.getPath().equals(RESET_QUIZ_PATH)) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ resetQuiz(null);
+ }
+ });
+ }
+ }
+
+ /**
+ * Used to ensure questions with smaller indexes come before questions with larger
+ * indexes. For example, question0 should come before question1.
+ */
+ private static class Question implements Comparable<Question> {
+ private String question;
+ private int questionIndex;
+ private String[] answers;
+ private int correctAnswerIndex;
+
+ public Question(String question, int questionIndex, String[] answers,
+ int correctAnswerIndex) {
+ this.question = question;
+ this.questionIndex = questionIndex;
+ this.answers = answers;
+ this.correctAnswerIndex = correctAnswerIndex;
+ }
+
+ public static Question fromJson(JSONObject questionObject, int questionIndex)
+ throws JSONException {
+ String question = questionObject.getString(JsonUtils.JSON_FIELD_QUESTION);
+ JSONArray answersJsonArray = questionObject.getJSONArray(JsonUtils.JSON_FIELD_ANSWERS);
+ String[] answers = new String[JsonUtils.NUM_ANSWER_CHOICES];
+ for (int j = 0; j < answersJsonArray.length(); j++) {
+ answers[j] = answersJsonArray.getString(j);
+ }
+ int correctIndex = questionObject.getInt(JsonUtils.JSON_FIELD_CORRECT_INDEX);
+ return new Question(question, questionIndex, answers, correctIndex);
+ }
+
+ @Override
+ public int compareTo(Question that) {
+ return this.questionIndex - that.questionIndex;
+ }
+
+ public PutDataRequest toPutDataRequest() {
+ PutDataMapRequest request = PutDataMapRequest.create("/question/" + questionIndex);
+ DataMap dataMap = request.getDataMap();
+ dataMap.putString(QUESTION, question);
+ dataMap.putInt(QUESTION_INDEX, questionIndex);
+ dataMap.putStringArray(ANSWERS, answers);
+ dataMap.putInt(CORRECT_ANSWER_INDEX, correctAnswerIndex);
+ return request.asPutDataRequest();
+ }
+ }
+
+ /**
+ * Create a quiz, as defined in Quiz.json, when the user clicks on "Read quiz from file."
+ * @throws IOException
+ */
+ public void readQuizFromFile(View view) throws IOException, JSONException {
+ clearQuizStatus();
+ JSONObject jsonObject = JsonUtils.loadJsonFile(this, QUIZ_JSON_FILE);
+ JSONArray jsonArray = jsonObject.getJSONArray(JsonUtils.JSON_FIELD_QUESTIONS);
+ for (int i = 0; i < jsonArray.length(); i++) {
+ JSONObject questionObject = jsonArray.getJSONObject(i);
+ Question question = Question.fromJson(questionObject, mQuestionIndex++);
+ addQuestionDataItem(question);
+ setNewQuestionStatus(question.question);
+ }
+ }
+
+ /**
+ * Adds a question (with answer choices) when user clicks on "Add Question."
+ */
+ public void addQuestion(View view) {
+ // Retrieve the question and answers supplied by the user.
+ String question = questionEditText.getText().toString();
+ String[] answers = new String[4];
+ answers[0] = choiceAEditText.getText().toString();
+ answers[1] = choiceBEditText.getText().toString();
+ answers[2] = choiceCEditText.getText().toString();
+ answers[3] = choiceDEditText.getText().toString();
+ int correctAnswerIndex = radioIdToIndex.get(choicesRadioGroup.getCheckedRadioButtonId());
+
+ addQuestionDataItem(new Question(question, mQuestionIndex++, answers, correctAnswerIndex));
+ setNewQuestionStatus(question);
+
+ // Clear the edit boxes to let the user input a new question.
+ questionEditText.setText("");
+ choiceAEditText.setText("");
+ choiceBEditText.setText("");
+ choiceCEditText.setText("");
+ choiceDEditText.setText("");
+ }
+
+ /**
+ * Adds the questions (and answers) to the wearable's stream by creating a Data Item
+ * that will be received on the wearable, which will create corresponding notifications.
+ */
+ private void addQuestionDataItem(Question question) {
+ if (!mHasQuestionBeenAsked) {
+ // Ask the question now.
+ Wearable.DataApi.putDataItem(mGoogleApiClient, question.toPutDataRequest());
+ setHasQuestionBeenAsked(true);
+ } else {
+ // Enqueue the question to be asked in the future.
+ mFutureQuestions.add(question);
+ }
+ }
+
+ /**
+ * Sets the question's status to be the default "unanswered." This will be updated when the
+ * user chooses an answer for the question on the wearable.
+ */
+ private void setNewQuestionStatus(String question) {
+ quizStatus.setVisibility(View.VISIBLE);
+ quizButtons.setVisibility(View.VISIBLE);
+ LayoutInflater inflater = LayoutInflater.from(this);
+ View questionStatusElem = inflater.inflate(R.layout.question_status_element, null, false);
+ ((TextView) questionStatusElem.findViewById(R.id.question)).setText(question);
+ ((TextView) questionStatusElem.findViewById(R.id.status))
+ .setText(R.string.question_unanswered);
+ questionsContainer.addView(questionStatusElem);
+ }
+
+ @Override
+ public void onDataChanged(DataEventBuffer dataEvents) {
+ final List<DataEvent> events = FreezableUtils.freezeIterable(dataEvents);
+ dataEvents.close();
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ for (DataEvent event : events) {
+ if (event.getType() == DataEvent.TYPE_CHANGED) {
+ DataMap dataMap = DataMapItem.fromDataItem(event.getDataItem())
+ .getDataMap();
+ boolean questionWasAnswered = dataMap.getBoolean(QUESTION_WAS_ANSWERED);
+ boolean questionWasDeleted = dataMap.getBoolean(QUESTION_WAS_DELETED);
+ if (questionWasAnswered) {
+ // Update the answered question's status.
+ int questionIndex = dataMap.getInt(QUESTION_INDEX);
+ boolean questionCorrect = dataMap.getBoolean(CHOSEN_ANSWER_CORRECT);
+ updateQuestionStatus(questionIndex, questionCorrect);
+ askNextQuestionIfExists();
+ } else if (questionWasDeleted) {
+ // Update the deleted question's status by marking it as left blank.
+ int questionIndex = dataMap.getInt(QUESTION_INDEX);
+ markQuestionLeftBlank(questionIndex);
+ askNextQuestionIfExists();
+ }
+ }
+ }
+ }
+ });
+ }
+
+ /**
+ * Updates the given question based on whether it was answered correctly or not.
+ * This involves changing the question's text color and changing the status text for it.
+ */
+ public void updateQuestionStatus(int questionIndex, boolean questionCorrect) {
+ LinearLayout questionStatusElement = (LinearLayout)
+ questionsContainer.getChildAt(questionIndex);
+ TextView questionText = (TextView) questionStatusElement.findViewById(R.id.question);
+ TextView questionStatus = (TextView) questionStatusElement.findViewById(R.id.status);
+ if (questionCorrect) {
+ questionText.setTextColor(Color.GREEN);
+ questionStatus.setText(R.string.question_correct);
+ mNumCorrect++;
+ } else {
+ questionText.setTextColor(Color.RED);
+ questionStatus.setText(R.string.question_incorrect);
+ mNumIncorrect++;
+ }
+ }
+
+ /**
+ * Marks a question as "left blank" when its corresponding question notification is deleted.
+ */
+ private void markQuestionLeftBlank(int index) {
+ LinearLayout questionStatusElement = (LinearLayout) questionsContainer.getChildAt(index);
+ if (questionStatusElement != null) {
+ TextView questionText = (TextView) questionStatusElement.findViewById(R.id.question);
+ TextView questionStatus = (TextView) questionStatusElement.findViewById(R.id.status);
+ if (questionStatus.getText().equals(getString(R.string.question_unanswered))) {
+ questionText.setTextColor(Color.YELLOW);
+ questionStatus.setText(R.string.question_left_blank);
+ mNumSkipped++;
+ }
+ }
+ }
+
+ /**
+ * Asks the next enqueued question if it exists, otherwise ends the quiz.
+ */
+ private void askNextQuestionIfExists() {
+ if (mFutureQuestions.isEmpty()) {
+ // Quiz has been completed - send message to wearable to display end report.
+ DataMap dataMap = new DataMap();
+ dataMap.putInt(NUM_CORRECT, mNumCorrect);
+ dataMap.putInt(NUM_INCORRECT, mNumIncorrect);
+ dataMap.putInt(NUM_SKIPPED, mNumSkipped);
+ sendMessageToWearable(QUIZ_ENDED_PATH, dataMap.toByteArray());
+ setHasQuestionBeenAsked(false);
+ } else {
+ // Ask next question by putting a DataItem that will be received on the wearable.
+ Wearable.DataApi.putDataItem(mGoogleApiClient,
+ mFutureQuestions.remove().toPutDataRequest());
+ setHasQuestionBeenAsked(true);
+ }
+ }
+
+ private void sendMessageToWearable(final String path, final byte[] data) {
+ Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).setResultCallback(
+ new ResultCallback<NodeApi.GetConnectedNodesResult>() {
+ @Override
+ public void onResult(NodeApi.GetConnectedNodesResult nodes) {
+ for (Node node : nodes.getNodes()) {
+ Wearable.MessageApi.sendMessage(mGoogleApiClient, node.getId(), path, data);
+ }
+
+ if (path.equals(QUIZ_EXITED_PATH) && mGoogleApiClient.isConnected()) {
+ mGoogleApiClient.disconnect();
+ }
+ }
+ });
+ }
+
+ /**
+ * Resets the current quiz when Reset Quiz is pressed.
+ */
+ public void resetQuiz(View view) {
+ // Reset quiz status in phone layout.
+ for(int i = 0; i < questionsContainer.getChildCount(); i++) {
+ LinearLayout questionStatusElement = (LinearLayout) questionsContainer.getChildAt(i);
+ TextView questionText = (TextView) questionStatusElement.findViewById(R.id.question);
+ TextView questionStatus = (TextView) questionStatusElement.findViewById(R.id.status);
+ questionText.setTextColor(Color.WHITE);
+ questionStatus.setText(R.string.question_unanswered);
+ }
+ // Reset data items and notifications on wearable.
+ if (mGoogleApiClient.isConnected()) {
+ Wearable.DataApi.getDataItems(mGoogleApiClient)
+ .setResultCallback(new ResultCallback<DataItemBuffer>() {
+ @Override
+ public void onResult(DataItemBuffer result) {
+ if (result.getStatus().isSuccess()) {
+ List<DataItem> dataItemList = FreezableUtils.freezeIterable(result);
+ result.close();
+ resetDataItems(dataItemList);
+ } else {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Reset quiz: failed to get Data Items to reset");
+ }
+ }
+ result.close();
+ }
+ });
+ } else {
+ Log.e(TAG, "Failed to reset data items because client is disconnected from "
+ + "Google Play Services");
+ }
+ setHasQuestionBeenAsked(false);
+ mNumCorrect = 0;
+ mNumIncorrect = 0;
+ mNumSkipped = 0;
+ }
+
+ private void resetDataItems(List<DataItem> dataItemList) {
+ if (mGoogleApiClient.isConnected()) {
+ for (final DataItem dataItem : dataItemList) {
+ final Uri dataItemUri = dataItem.getUri();
+ Wearable.DataApi.getDataItem(mGoogleApiClient, dataItemUri)
+ .setResultCallback(new ResetDataItemCallback());
+ }
+ } else {
+ Log.e(TAG, "Failed to reset data items because client is disconnected from "
+ + "Google Play Services");
+ }
+ }
+
+ /**
+ * Callback that marks a DataItem, which represents a question, as unanswered and not deleted.
+ */
+ private class ResetDataItemCallback implements ResultCallback<DataApi.DataItemResult> {
+ @Override
+ public void onResult(DataApi.DataItemResult dataItemResult) {
+ if (dataItemResult.getStatus().isSuccess()) {
+ PutDataMapRequest request = PutDataMapRequest.createFromDataMapItem(
+ DataMapItem.fromDataItem(dataItemResult.getDataItem()));
+ DataMap dataMap = request.getDataMap();
+ dataMap.putBoolean(QUESTION_WAS_ANSWERED, false);
+ dataMap.putBoolean(QUESTION_WAS_DELETED, false);
+ if (!mHasQuestionBeenAsked && dataMap.getInt(QUESTION_INDEX) == 0) {
+ // Ask the first question now.
+ Wearable.DataApi.putDataItem(mGoogleApiClient, request.asPutDataRequest());
+ setHasQuestionBeenAsked(true);
+ } else {
+ // Enqueue future questions.
+ mFutureQuestions.add(new Question(dataMap.getString(QUESTION),
+ dataMap.getInt(QUESTION_INDEX), dataMap.getStringArray(ANSWERS),
+ dataMap.getInt(CORRECT_ANSWER_INDEX)));
+ }
+ } else {
+ Log.e(TAG, "Failed to reset data item " + dataItemResult.getDataItem().getUri());
+ }
+ }
+ }
+
+ /**
+ * Clears the current quiz when user clicks on "New Quiz."
+ * On this end, this involves clearing the quiz status layout and deleting all DataItems. The
+ * wearable will then remove any outstanding question notifications upon receiving this change.
+ */
+ public void newQuiz(View view) {
+ clearQuizStatus();
+ if (mGoogleApiClient.isConnected()) {
+ Wearable.DataApi.getDataItems(mGoogleApiClient)
+ .setResultCallback(new ResultCallback<DataItemBuffer>() {
+ @Override
+ public void onResult(DataItemBuffer result) {
+ if (result.getStatus().isSuccess()) {
+ List<Uri> dataItemUriList = new ArrayList<Uri>();
+ for (final DataItem dataItem : result) {
+ dataItemUriList.add(dataItem.getUri());
+ }
+ result.close();
+ deleteDataItems(dataItemUriList);
+ } else {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Clear quiz: failed to get Data Items for deletion");
+ }
+ }
+ result.close();
+ }
+ });
+ } else {
+ Log.e(TAG, "Failed to delete data items because client is disconnected from "
+ + "Google Play Services");
+ }
+ }
+
+ /**
+ * Removes quiz status views (i.e. the views describing the status of each question).
+ */
+ private void clearQuizStatus() {
+ questionsContainer.removeAllViews();
+ quizStatus.setVisibility(View.INVISIBLE);
+ quizButtons.setVisibility(View.INVISIBLE);
+ setHasQuestionBeenAsked(false);
+ mFutureQuestions.clear();
+ mQuestionIndex = 0;
+ mNumCorrect = 0;
+ mNumIncorrect = 0;
+ mNumSkipped = 0;
+ }
+
+ private void deleteDataItems(List<Uri> dataItemUriList) {
+ if (mGoogleApiClient.isConnected()) {
+ for (final Uri dataItemUri : dataItemUriList) {
+ Wearable.DataApi.deleteDataItems(mGoogleApiClient, dataItemUri)
+ .setResultCallback(new ResultCallback<DataApi.DeleteDataItemsResult>() {
+ @Override
+ public void onResult(DataApi.DeleteDataItemsResult deleteResult) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ if (deleteResult.getStatus().isSuccess()) {
+ Log.d(TAG, "Successfully deleted data item " + dataItemUri);
+ } else {
+ Log.d(TAG, "Failed to delete data item " + dataItemUri);
+ }
+ }
+ }
+ });
+ }
+ } else {
+ Log.e(TAG, "Failed to delete data items because client is disconnected from "
+ + "Google Play Services");
+ }
+ }
+
+ private void setHasQuestionBeenAsked(boolean b) {
+ mHasQuestionBeenAsked = b;
+ // Only let user click on Reset or Read from file if they have answered all the questions.
+ readQuizFromFileButton.setEnabled(!mHasQuestionBeenAsked);
+ resetQuizButton.setEnabled(!mHasQuestionBeenAsked);
+ }
+}
diff --git a/wearable/wear/Quiz/Application/src/main/res/drawable-hdpi/ic_choice_a.png b/wearable/wear/Quiz/Application/src/main/res/drawable-hdpi/ic_choice_a.png
new file mode 100644
index 0000000..de18ce1
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/res/drawable-hdpi/ic_choice_a.png
Binary files differ
diff --git a/wearable/wear/Quiz/Application/src/main/res/drawable-hdpi/ic_choice_b.png b/wearable/wear/Quiz/Application/src/main/res/drawable-hdpi/ic_choice_b.png
new file mode 100644
index 0000000..3cdfe97
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/res/drawable-hdpi/ic_choice_b.png
Binary files differ
diff --git a/wearable/wear/Quiz/Application/src/main/res/drawable-hdpi/ic_choice_c.png b/wearable/wear/Quiz/Application/src/main/res/drawable-hdpi/ic_choice_c.png
new file mode 100644
index 0000000..f0ed2ef
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/res/drawable-hdpi/ic_choice_c.png
Binary files differ
diff --git a/wearable/wear/Quiz/Application/src/main/res/drawable-hdpi/ic_choice_d.png b/wearable/wear/Quiz/Application/src/main/res/drawable-hdpi/ic_choice_d.png
new file mode 100644
index 0000000..c158d29
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/res/drawable-hdpi/ic_choice_d.png
Binary files differ
diff --git a/wearable/wear/Quiz/Application/src/main/res/drawable-hdpi/ic_launcher.png b/wearable/wear/Quiz/Application/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100755
index 0000000..91a8cff
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Quiz/Application/src/main/res/drawable-hdpi/ic_unknown_choice.png b/wearable/wear/Quiz/Application/src/main/res/drawable-hdpi/ic_unknown_choice.png
new file mode 100644
index 0000000..9aed517
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/res/drawable-hdpi/ic_unknown_choice.png
Binary files differ
diff --git a/wearable/wear/Quiz/Application/src/main/res/drawable-mdpi/ic_choice_a.png b/wearable/wear/Quiz/Application/src/main/res/drawable-mdpi/ic_choice_a.png
new file mode 100644
index 0000000..5745936
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/res/drawable-mdpi/ic_choice_a.png
Binary files differ
diff --git a/wearable/wear/Quiz/Application/src/main/res/drawable-mdpi/ic_choice_b.png b/wearable/wear/Quiz/Application/src/main/res/drawable-mdpi/ic_choice_b.png
new file mode 100644
index 0000000..958b92e
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/res/drawable-mdpi/ic_choice_b.png
Binary files differ
diff --git a/wearable/wear/Quiz/Application/src/main/res/drawable-mdpi/ic_choice_c.png b/wearable/wear/Quiz/Application/src/main/res/drawable-mdpi/ic_choice_c.png
new file mode 100644
index 0000000..9fcfab7
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/res/drawable-mdpi/ic_choice_c.png
Binary files differ
diff --git a/wearable/wear/Quiz/Application/src/main/res/drawable-mdpi/ic_choice_d.png b/wearable/wear/Quiz/Application/src/main/res/drawable-mdpi/ic_choice_d.png
new file mode 100644
index 0000000..821cadb
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/res/drawable-mdpi/ic_choice_d.png
Binary files differ
diff --git a/wearable/wear/Quiz/Application/src/main/res/drawable-mdpi/ic_launcher.png b/wearable/wear/Quiz/Application/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100755
index 0000000..728ee6d
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Quiz/Application/src/main/res/drawable-mdpi/ic_unknown_choice.png b/wearable/wear/Quiz/Application/src/main/res/drawable-mdpi/ic_unknown_choice.png
new file mode 100644
index 0000000..b8030ef
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/res/drawable-mdpi/ic_unknown_choice.png
Binary files differ
diff --git a/wearable/wear/Quiz/Application/src/main/res/drawable-xhdpi/ic_choice_a.png b/wearable/wear/Quiz/Application/src/main/res/drawable-xhdpi/ic_choice_a.png
new file mode 100644
index 0000000..3dba96f
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/res/drawable-xhdpi/ic_choice_a.png
Binary files differ
diff --git a/wearable/wear/Quiz/Application/src/main/res/drawable-xhdpi/ic_choice_b.png b/wearable/wear/Quiz/Application/src/main/res/drawable-xhdpi/ic_choice_b.png
new file mode 100644
index 0000000..9ca3c85
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/res/drawable-xhdpi/ic_choice_b.png
Binary files differ
diff --git a/wearable/wear/Quiz/Application/src/main/res/drawable-xhdpi/ic_choice_c.png b/wearable/wear/Quiz/Application/src/main/res/drawable-xhdpi/ic_choice_c.png
new file mode 100644
index 0000000..b84b3b7
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/res/drawable-xhdpi/ic_choice_c.png
Binary files differ
diff --git a/wearable/wear/Quiz/Application/src/main/res/drawable-xhdpi/ic_choice_d.png b/wearable/wear/Quiz/Application/src/main/res/drawable-xhdpi/ic_choice_d.png
new file mode 100644
index 0000000..185e91e
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/res/drawable-xhdpi/ic_choice_d.png
Binary files differ
diff --git a/wearable/wear/Quiz/Application/src/main/res/drawable-xhdpi/ic_launcher.png b/wearable/wear/Quiz/Application/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100755
index 0000000..64a5854
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Quiz/Application/src/main/res/drawable-xxhdpi/ic_launcher.png b/wearable/wear/Quiz/Application/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100755
index 0000000..86a395b
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Quiz/Application/src/main/res/drawable/selected_background.xml b/wearable/wear/Quiz/Application/src/main/res/drawable/selected_background.xml
new file mode 100644
index 0000000..5852dd8
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/res/drawable/selected_background.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <padding
+ android:top="4dp"
+ android:bottom="4dp"
+ android:left="4dp"
+ android:right="4dp"/>
+ <stroke
+ android:width="4dp"
+ android:color="@android:color/holo_blue_bright" />
+</shape>
diff --git a/wearable/wear/Quiz/Application/src/main/res/drawable/unselected_background.xml b/wearable/wear/Quiz/Application/src/main/res/drawable/unselected_background.xml
new file mode 100644
index 0000000..1613167
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/res/drawable/unselected_background.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <padding
+ android:top="4dp"
+ android:bottom="4dp"
+ android:left="4dp"
+ android:right="4dp"/>
+ <stroke
+ android:width="4dp"
+ android:color="#ff000000" />
+</shape>
diff --git a/wearable/wear/Quiz/Application/src/main/res/layout/main.xml b/wearable/wear/Quiz/Application/src/main/res/layout/main.xml
new file mode 100644
index 0000000..3eb19f9
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/res/layout/main.xml
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ tools:context="com.example.android.support.wearable.quiz.MainActivity"
+ tools:ignore="MergeRootFrame">
+
+ <LinearLayout android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/read_quiz_from_file_button"
+ android:text="@string/read_from_file_button"
+ android:onClick="readQuizFromFile"
+ android:layout_gravity="center"/>
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:text="@string/edit_question"
+ android:id="@+id/textView2" />
+
+ <EditText
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/question_text" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <RadioGroup
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:id="@+id/choices_radio_group">
+ <RadioButton
+ android:layout_width="wrap_content"
+ android:layout_height="50dp"
+ android:text="@string/edit_choice_a"
+ android:id="@+id/choice_a_radio"
+ android:checked="true" />
+ <RadioButton
+ android:layout_width="wrap_content"
+ android:layout_height="50dp"
+ android:text="@string/edit_choice_b"
+ android:id="@+id/choice_b_radio"
+ android:checked="false" />
+ <RadioButton
+ android:layout_width="wrap_content"
+ android:layout_height="50dp"
+ android:text="@string/edit_choice_c"
+ android:id="@+id/choice_c_radio" />
+ <RadioButton
+ android:layout_width="wrap_content"
+ android:layout_height="50dp"
+ android:text="@string/edit_choice_d"
+ android:id="@+id/choice_d_radio" />
+ </RadioGroup>
+
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <EditText
+ android:layout_width="match_parent"
+ android:layout_height="50dp"
+ android:id="@+id/choice_a_text" />
+ <EditText
+ android:layout_width="match_parent"
+ android:layout_height="50dp"
+ android:id="@+id/choice_b_text" />
+ <EditText
+ android:layout_width="match_parent"
+ android:layout_height="50dp"
+ android:id="@+id/choice_c_text" />
+ <EditText
+ android:layout_width="match_parent"
+ android:layout_height="50dp"
+ android:id="@+id/choice_d_text" />
+ </LinearLayout>
+
+
+ </LinearLayout>
+
+ <Button android:id="@+id/add_question"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/add_question"
+ android:onClick="addQuestion"
+ android:layout_gravity="center">
+ </Button>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:text="@string/quiz_status"
+ android:id="@+id/quiz_status"
+ android:paddingTop="30dp"
+ android:paddingBottom="10dp"
+ android:visibility="invisible"/>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/questions_container"
+ android:orientation="vertical"
+ android:paddingBottom="10dp">
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/quiz_buttons"
+ android:layout_gravity="center"
+ android:visibility="invisible">
+ <Button android:id="@+id/reset_quiz_button"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/reset_quiz"
+ android:onClick="resetQuiz">
+ </Button>
+ <Button android:id="@+id/new_quiz_button"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/new_quiz"
+ android:onClick="newQuiz">
+ </Button>
+ </LinearLayout>
+
+
+ </LinearLayout>
+
+</ScrollView>
diff --git a/wearable/wear/Quiz/Application/src/main/res/layout/question_status_element.xml b/wearable/wear/Quiz/Application/src/main/res/layout/question_status_element.xml
new file mode 100644
index 0000000..280f44a
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/res/layout/question_status_element.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical" android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="@string/question_placeholder"
+ android:id="@+id/question" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:text="@string/question_unanswered"
+ android:id="@+id/status" />
+</LinearLayout>
diff --git a/wearable/wear/Quiz/Application/src/main/res/values/dimens.xml b/wearable/wear/Quiz/Application/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..fd97910
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/res/values/dimens.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+
+ <dimen name="editor_text_size">12dp</dimen>
+ <dimen name="editor_item_padding_top">8dp</dimen>
+ <dimen name="editor_item_padding_bottom">8dp</dimen>
+ <dimen name="editor_spinner_caption_min_width">50dp</dimen>
+
+ <dimen name="image_picker_item_side">48dp</dimen>
+
+</resources>
diff --git a/wearable/wear/Quiz/Application/src/main/res/values/strings.xml b/wearable/wear/Quiz/Application/src/main/res/values/strings.xml
new file mode 100644
index 0000000..e2fa3b1
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/res/values/strings.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+
+ <string name="read_from_file_button">Read quiz from file</string>
+
+ <string name="edit_question">Question</string>
+ <string name="edit_choice_a">Choice A</string>
+ <string name="edit_choice_b">Choice B</string>
+ <string name="edit_choice_c">Choice C</string>
+ <string name="edit_choice_d">Choice D</string>
+ <string name="add_question">Add Question</string>
+
+ <string name="quiz_status">Quiz Status</string>
+ <string name="question_placeholder">Question</string>
+ <string name="question_unanswered">This question has not yet been answered.</string>
+ <string name="question_incorrect">This question has been answered incorrectly.</string>
+ <string name="question_correct">This question has been answered correctly!</string>
+ <string name="question_left_blank">This question was left blank.</string>
+
+ <string name="reset_quiz">Reset Quiz</string>
+ <string name="new_quiz">New Quiz</string>
+
+</resources>
diff --git a/wearable/wear/Quiz/Application/src/main/res/values/styles.xml b/wearable/wear/Quiz/Application/src/main/res/values/styles.xml
new file mode 100644
index 0000000..69f8dfa
--- /dev/null
+++ b/wearable/wear/Quiz/Application/src/main/res/values/styles.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+
+ <style name="bg_picker">
+ <item name="android:layout_marginLeft">16dp</item>
+ <item name="android:background">@drawable/unselected_background</item>
+ </style>
+
+</resources>
diff --git a/wearable/wear/Quiz/CONTRIB.md b/wearable/wear/Quiz/CONTRIB.md
new file mode 100644
index 0000000..14a4fcf
--- /dev/null
+++ b/wearable/wear/Quiz/CONTRIB.md
@@ -0,0 +1,35 @@
+# How to become a contributor and submit your own code
+
+## Contributor License Agreements
+
+We'd love to accept your sample apps and patches! Before we can take them, we
+have to jump a couple of legal hurdles.
+
+Please fill out either the individual or corporate Contributor License Agreement (CLA).
+
+ * If you are an individual writing original source code and you're sure you
+ own the intellectual property, then you'll need to sign an [individual CLA]
+ (https://developers.google.com/open-source/cla/individual).
+ * If you work for a company that wants to allow you to contribute your work,
+ then you'll need to sign a [corporate CLA]
+ (https://developers.google.com/open-source/cla/corporate).
+
+Follow either of the two links above to access the appropriate CLA and
+instructions for how to sign and return it. Once we receive it, we'll be able to
+accept your pull requests.
+
+## Contributing A Patch
+
+1. Submit an issue describing your proposed change to the repo in question.
+1. The repo owner will respond to your issue promptly.
+1. If your proposed change is accepted, and you haven't already done so, sign a
+ Contributor License Agreement (see details above).
+1. Fork the desired repo, develop and test your code changes.
+1. Ensure that your code adheres to the existing style in the sample to which
+ you are contributing. Refer to the
+ [Android Code Style Guide]
+ (https://source.android.com/source/code-style.html) for the
+ recommended coding standards for this organization.
+1. Ensure that your code has an appropriate set of unit tests which all pass.
+1. Submit a pull request.
+
diff --git a/wearable/wear/Quiz/LICENSE b/wearable/wear/Quiz/LICENSE
new file mode 100644
index 0000000..1af981f
--- /dev/null
+++ b/wearable/wear/Quiz/LICENSE
@@ -0,0 +1,201 @@
+ 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 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/wearable/wear/Quiz/README-wear.txt b/wearable/wear/Quiz/README-wear.txt
new file mode 100644
index 0000000..17523d7
--- /dev/null
+++ b/wearable/wear/Quiz/README-wear.txt
@@ -0,0 +1,30 @@
+<#--
+ Copyright 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.
+-->
+
+Steps to use Wear template on top of an existing sample:
+- In template-params.xml.ftl:
+ - Add the following template:
+ <template src="Wear"/>
+
+- Refresh your project (./gradlew refresh)
+- Add Wearable-specific code to Wearable directory
+- Add code to be shared among the main application and the wearable to Shared
+ directory
+
+Note that you still need the main application sample code. This is usually
+achieved by adding another template, like "base" for example.
+
+
diff --git a/wearable/wear/Quiz/Shared/.gitignore b/wearable/wear/Quiz/Shared/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/Quiz/Shared/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/Quiz/Shared/src/main/AndroidManifest.xml b/wearable/wear/Quiz/Shared/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..0d7b8a6
--- /dev/null
+++ b/wearable/wear/Quiz/Shared/src/main/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.quiz.common">
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name">
+ </application>
+
+</manifest>
diff --git a/wearable/wear/Quiz/Shared/src/main/res/values/strings.xml b/wearable/wear/Quiz/Shared/src/main/res/values/strings.xml
new file mode 100644
index 0000000..0f2bb90
--- /dev/null
+++ b/wearable/wear/Quiz/Shared/src/main/res/values/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+ <string name="app_name">Shared</string>
+</resources>
diff --git a/wearable/wear/Quiz/Wearable/.gitignore b/wearable/wear/Quiz/Wearable/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/Quiz/Wearable/src/main/AndroidManifest.xml b/wearable/wear/Quiz/Wearable/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..7954e32
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/AndroidManifest.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.quiz" >
+
+
+ <uses-sdk android:minSdkVersion="20"
+ android:targetSdkVersion="20" />
+
+ <uses-feature android:name="android.hardware.type.watch" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@android:style/Theme.DeviceDefault" >
+ <meta-data
+ android:name="com.google.android.gms.version"
+ android:value="@integer/google_play_services_version" />
+
+ <service android:name=".QuizListenerService" >
+ <intent-filter>
+ <action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
+ </intent-filter>
+ </service>
+ <service android:name=".UpdateQuestionService" />
+ <service android:name=".DeleteQuestionService" />
+ <service android:name=".QuizReportActionService" />
+
+ </application>
+
+</manifest>
diff --git a/wearable/wear/Quiz/Wearable/src/main/java/com/example/android/quiz/Constants.java b/wearable/wear/Quiz/Wearable/src/main/java/com/example/android/quiz/Constants.java
new file mode 100644
index 0000000..8218ad9
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/java/com/example/android/quiz/Constants.java
@@ -0,0 +1,41 @@
+/*
+ * 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.android.quiz;
+
+/** Constants used in the wearable app. */
+public final class Constants {
+ private Constants() {
+ }
+
+ public static final String ANSWERS = "answers";
+ public static final String CHOSEN_ANSWER_CORRECT = "chosen_answer_correct";
+ public static final String CORRECT_ANSWER_INDEX = "correct_answer_index";
+ public static final String QUESTION = "question";
+ public static final String QUESTION_INDEX = "question_index";
+ public static final String QUESTION_WAS_ANSWERED = "question_was_answered";
+ public static final String QUESTION_WAS_DELETED = "question_was_deleted";
+
+ public static final String NUM_CORRECT = "num_correct";
+ public static final String NUM_INCORRECT = "num_incorrect";
+ public static final String NUM_SKIPPED = "num_skipped";
+
+ public static final String QUIZ_ENDED_PATH = "/quiz_ended";
+ public static final String QUIZ_EXITED_PATH = "/quiz_exited";
+ public static final String RESET_QUIZ_PATH = "/reset_quiz";
+
+ public static final int CONNECT_TIMEOUT_MS = 100;
+}
diff --git a/wearable/wear/Quiz/Wearable/src/main/java/com/example/android/quiz/DeleteQuestionService.java b/wearable/wear/Quiz/Wearable/src/main/java/com/example/android/quiz/DeleteQuestionService.java
new file mode 100644
index 0000000..38b5e4a
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/java/com/example/android/quiz/DeleteQuestionService.java
@@ -0,0 +1,94 @@
+/*
+ * 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.android.quiz;
+
+import android.app.IntentService;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+
+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.DataMap;
+import com.google.android.gms.wearable.DataMapItem;
+import com.google.android.gms.wearable.PutDataMapRequest;
+import com.google.android.gms.wearable.PutDataRequest;
+import com.google.android.gms.wearable.Wearable;
+
+import java.util.concurrent.TimeUnit;
+
+import static com.example.android.quiz.Constants.CONNECT_TIMEOUT_MS;
+import static com.example.android.quiz.Constants.QUESTION_WAS_DELETED;
+
+/**
+ * Used to update quiz status on the phone when user dismisses a question on the watch.
+ */
+public class DeleteQuestionService extends IntentService
+ implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
+
+ private static final String TAG = "DeleteQuestionReceiver";
+
+ private GoogleApiClient mGoogleApiClient;
+
+ public DeleteQuestionService() {
+ super(DeleteQuestionService.class.getSimpleName());
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mGoogleApiClient = new GoogleApiClient.Builder(this)
+ .addApi(Wearable.API)
+ .addConnectionCallbacks(this)
+ .addOnConnectionFailedListener(this)
+ .build();
+ }
+
+ @Override
+ public void onHandleIntent(Intent intent) {
+ mGoogleApiClient.blockingConnect(CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ Uri dataItemUri = intent.getData();
+ if (!mGoogleApiClient.isConnected()) {
+ Log.e(TAG, "Failed to update data item " + dataItemUri
+ + " because client is disconnected from Google Play Services");
+ return;
+ }
+ DataApi.DataItemResult dataItemResult = Wearable.DataApi.getDataItem(
+ mGoogleApiClient, dataItemUri).await();
+ PutDataMapRequest putDataMapRequest = PutDataMapRequest
+ .createFromDataMapItem(DataMapItem.fromDataItem(dataItemResult.getDataItem()));
+ DataMap dataMap = putDataMapRequest.getDataMap();
+ dataMap.putBoolean(QUESTION_WAS_DELETED, true);
+ PutDataRequest request = putDataMapRequest.asPutDataRequest();
+ Wearable.DataApi.putDataItem(mGoogleApiClient, request).await();
+ mGoogleApiClient.disconnect();
+ }
+
+ @Override
+ public void onConnected(Bundle bundle) {
+ }
+
+ @Override
+ public void onConnectionSuspended(int i) {
+ }
+
+ @Override
+ public void onConnectionFailed(ConnectionResult connectionResult) {
+ }
+}
diff --git a/wearable/wear/Quiz/Wearable/src/main/java/com/example/android/quiz/QuizListenerService.java b/wearable/wear/Quiz/Wearable/src/main/java/com/example/android/quiz/QuizListenerService.java
new file mode 100644
index 0000000..3226f9b
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/java/com/example/android/quiz/QuizListenerService.java
@@ -0,0 +1,219 @@
+/*
+ * 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.android.quiz;
+
+import static com.example.android.quiz.Constants.ANSWERS;
+import static com.example.android.quiz.Constants.CONNECT_TIMEOUT_MS;
+import static com.example.android.quiz.Constants.CORRECT_ANSWER_INDEX;
+import static com.example.android.quiz.Constants.NUM_CORRECT;
+import static com.example.android.quiz.Constants.NUM_INCORRECT;
+import static com.example.android.quiz.Constants.NUM_SKIPPED;
+import static com.example.android.quiz.Constants.QUESTION;
+import static com.example.android.quiz.Constants.QUESTION_INDEX;
+import static com.example.android.quiz.Constants.QUESTION_WAS_ANSWERED;
+import static com.example.android.quiz.Constants.QUESTION_WAS_DELETED;
+import static com.example.android.quiz.Constants.QUIZ_ENDED_PATH;
+import static com.example.android.quiz.Constants.QUIZ_EXITED_PATH;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.net.Uri;
+import android.text.SpannableStringBuilder;
+import android.text.style.ForegroundColorSpan;
+import android.util.Log;
+
+import com.google.android.gms.common.ConnectionResult;
+import com.google.android.gms.common.api.GoogleApiClient;
+import com.google.android.gms.common.data.FreezableUtils;
+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.Wearable;
+import com.google.android.gms.wearable.WearableListenerService;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Listens to changes in DataItems, which represent quiz questions.
+ * If a new question is created, this builds a new notification for it.
+ * Otherwise, if a question is deleted, this cancels the corresponding notification.
+ *
+ * When the quiz ends, this listener receives a message telling it to create an end-of-quiz report.
+ */
+public class QuizListenerService extends WearableListenerService {
+ private static final String TAG = "QuizSample";
+ private static final int QUIZ_REPORT_NOTIF_ID = -1; // Never used by question notifications.
+ private static final Map<Integer, Integer> questionNumToDrawableId;
+
+ static {
+ Map<Integer, Integer> temp = new HashMap<Integer, Integer>(4);
+ temp.put(0, R.drawable.ic_choice_a);
+ temp.put(1, R.drawable.ic_choice_b);
+ temp.put(2, R.drawable.ic_choice_c);
+ temp.put(3, R.drawable.ic_choice_d);
+ questionNumToDrawableId = Collections.unmodifiableMap(temp);
+ }
+
+ @Override
+ public void onDataChanged(DataEventBuffer dataEvents) {
+ final List<DataEvent> events = FreezableUtils.freezeIterable(dataEvents);
+ dataEvents.close();
+
+ GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this)
+ .addApi(Wearable.API)
+ .build();
+
+ ConnectionResult connectionResult = googleApiClient.blockingConnect(CONNECT_TIMEOUT_MS,
+ TimeUnit.MILLISECONDS);
+ if (!connectionResult.isSuccess()) {
+ Log.e(TAG, "QuizListenerService failed to connect to GoogleApiClient.");
+ return;
+ }
+
+ for (DataEvent event : events) {
+ if (event.getType() == DataEvent.TYPE_CHANGED) {
+ DataItem dataItem = event.getDataItem();
+ DataMap dataMap = DataMapItem.fromDataItem(dataItem).getDataMap();
+ if (dataMap.getBoolean(QUESTION_WAS_ANSWERED)
+ || dataMap.getBoolean(QUESTION_WAS_DELETED)) {
+ // Ignore the change in data; it is used in MainActivity to update
+ // the question's status (i.e. was the answer right or wrong or left blank).
+ continue;
+ }
+ String question = dataMap.getString(QUESTION);
+ int questionIndex = dataMap.getInt(QUESTION_INDEX);
+ int questionNum = questionIndex + 1;
+ String[] answers = dataMap.getStringArray(ANSWERS);
+ int correctAnswerIndex = dataMap.getInt(CORRECT_ANSWER_INDEX);
+ Intent deleteOperation = new Intent(this, DeleteQuestionService.class);
+ deleteOperation.setData(dataItem.getUri());
+ PendingIntent deleteIntent = PendingIntent.getService(this, 0,
+ deleteOperation, PendingIntent.FLAG_UPDATE_CURRENT);
+ // First page of notification contains question as Big Text.
+ Notification.BigTextStyle bigTextStyle = new Notification.BigTextStyle()
+ .setBigContentTitle(getString(R.string.question, questionNum))
+ .bigText(question);
+ Notification.Builder builder = new Notification.Builder(this)
+ .setStyle(bigTextStyle)
+ .setSmallIcon(R.drawable.ic_launcher)
+ .setLocalOnly(true)
+ .setDeleteIntent(deleteIntent);
+
+ // Add answers as actions.
+ Notification.WearableExtender wearableOptions = new Notification.WearableExtender();
+ for (int i = 0; i < answers.length; i++) {
+ Notification answerPage = new Notification.Builder(this)
+ .setContentTitle(question)
+ .setContentText(answers[i])
+ .extend(new Notification.WearableExtender()
+ .setContentAction(i))
+ .build();
+
+ boolean correct = (i == correctAnswerIndex);
+ Intent updateOperation = new Intent(this, UpdateQuestionService.class);
+ // Give each intent a unique action.
+ updateOperation.setAction("question_" + questionIndex + "_answer_" + i);
+ updateOperation.setData(dataItem.getUri());
+ updateOperation.putExtra(UpdateQuestionService.EXTRA_QUESTION_INDEX,
+ questionIndex);
+ updateOperation.putExtra(UpdateQuestionService.EXTRA_QUESTION_CORRECT, correct);
+ PendingIntent updateIntent = PendingIntent.getService(this, 0, updateOperation,
+ PendingIntent.FLAG_UPDATE_CURRENT);
+ Notification.Action action = new Notification.Action.Builder(
+ questionNumToDrawableId.get(i), null, updateIntent)
+ .build();
+ wearableOptions.addAction(action).addPage(answerPage);
+ }
+ builder.extend(wearableOptions);
+ Notification notification = builder.build();
+ ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
+ .notify(questionIndex, notification);
+ } else if (event.getType() == DataEvent.TYPE_DELETED) {
+ Uri uri = event.getDataItem().getUri();
+ // URI's are of the form "/question/0", "/question/1" etc.
+ // We use the question index as the notification id.
+ int notificationId = Integer.parseInt(uri.getLastPathSegment());
+ ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
+ .cancel(notificationId);
+ }
+ // Delete the quiz report, if it exists.
+ ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
+ .cancel(QUIZ_REPORT_NOTIF_ID);
+ }
+ googleApiClient.disconnect();
+ }
+
+ @Override
+ public void onMessageReceived(MessageEvent messageEvent) {
+ String path = messageEvent.getPath();
+ if (path.equals(QUIZ_EXITED_PATH)) {
+ // Remove any lingering question notifications.
+ ((NotificationManager) getSystemService(NOTIFICATION_SERVICE)).cancelAll();
+ }
+ if (path.equals(QUIZ_ENDED_PATH) || path.equals(QUIZ_EXITED_PATH)) {
+ // Quiz ended - display overall results.
+ DataMap dataMap = DataMap.fromByteArray(messageEvent.getData());
+ int numCorrect = dataMap.getInt(NUM_CORRECT);
+ int numIncorrect = dataMap.getInt(NUM_INCORRECT);
+ int numSkipped = dataMap.getInt(NUM_SKIPPED);
+
+ Notification.Builder builder = new Notification.Builder(this)
+ .setContentTitle(getString(R.string.quiz_report))
+ .setSmallIcon(R.drawable.ic_launcher)
+ .setLocalOnly(true);
+ SpannableStringBuilder quizReportText = new SpannableStringBuilder();
+ appendColored(quizReportText, String.valueOf(numCorrect), R.color.dark_green);
+ quizReportText.append(" " + getString(R.string.correct) + "\n");
+ appendColored(quizReportText, String.valueOf(numIncorrect), R.color.dark_red);
+ quizReportText.append(" " + getString(R.string.incorrect) + "\n");
+ appendColored(quizReportText, String.valueOf(numSkipped), R.color.dark_yellow);
+ quizReportText.append(" " + getString(R.string.skipped) + "\n");
+
+ builder.setContentText(quizReportText);
+ if (!path.equals(QUIZ_EXITED_PATH)) {
+ // Don't add reset option if user exited quiz (there might not be a quiz to reset!).
+ builder.addAction(R.drawable.ic_launcher,
+ getString(R.string.reset_quiz), getResetQuizPendingIntent());
+ }
+ ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
+ .notify(QUIZ_REPORT_NOTIF_ID, builder.build());
+ }
+ }
+
+ private void appendColored(SpannableStringBuilder builder, String text, int colorResId) {
+ builder.append(text).setSpan(new ForegroundColorSpan(getResources().getColor(colorResId)),
+ builder.length() - text.length(), builder.length(), 0);
+ }
+
+ /**
+ * Returns a PendingIntent that will send a message to the phone to reset the quiz when fired.
+ */
+ private PendingIntent getResetQuizPendingIntent() {
+ Intent intent = new Intent(QuizReportActionService.ACTION_RESET_QUIZ)
+ .setClass(this, QuizReportActionService.class);
+ return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ }
+}
diff --git a/wearable/wear/Quiz/Wearable/src/main/java/com/example/android/quiz/QuizReportActionService.java b/wearable/wear/Quiz/Wearable/src/main/java/com/example/android/quiz/QuizReportActionService.java
new file mode 100644
index 0000000..4ca55be
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/java/com/example/android/quiz/QuizReportActionService.java
@@ -0,0 +1,67 @@
+/*
+ * 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.android.quiz;
+
+import android.app.IntentService;
+import android.content.Intent;
+import android.util.Log;
+
+import com.google.android.gms.common.ConnectionResult;
+import com.google.android.gms.common.api.GoogleApiClient;
+import com.google.android.gms.wearable.Node;
+import com.google.android.gms.wearable.NodeApi;
+import com.google.android.gms.wearable.Wearable;
+
+import java.util.concurrent.TimeUnit;
+
+import static com.example.android.quiz.Constants.CONNECT_TIMEOUT_MS;
+import static com.example.android.quiz.Constants.RESET_QUIZ_PATH;
+
+/**
+ * Service to reset the quiz (by sending a message to the phone) when the Reset Quiz
+ * action on the Quiz Report is selected.
+ */
+public class QuizReportActionService extends IntentService {
+ public static final String ACTION_RESET_QUIZ = "com.example.android.quiz.RESET_QUIZ";
+
+ private static final String TAG = "QuizReportActionReceiver";
+
+ public QuizReportActionService() {
+ super(QuizReportActionService.class.getSimpleName());
+ }
+
+ @Override
+ public void onHandleIntent(Intent intent) {
+ if (intent.getAction().equals(ACTION_RESET_QUIZ)) {
+ GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this)
+ .addApi(Wearable.API)
+ .build();
+ ConnectionResult result = googleApiClient.blockingConnect(CONNECT_TIMEOUT_MS,
+ TimeUnit.MILLISECONDS);
+ if (!result.isSuccess()) {
+ Log.e(TAG, "QuizListenerService failed to connect to GoogleApiClient.");
+ return;
+ }
+ NodeApi.GetConnectedNodesResult nodes =
+ Wearable.NodeApi.getConnectedNodes(googleApiClient).await();
+ for (Node node : nodes.getNodes()) {
+ Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), RESET_QUIZ_PATH,
+ new byte[0]);
+ }
+ }
+ }
+}
diff --git a/wearable/wear/Quiz/Wearable/src/main/java/com/example/android/quiz/UpdateQuestionService.java b/wearable/wear/Quiz/Wearable/src/main/java/com/example/android/quiz/UpdateQuestionService.java
new file mode 100644
index 0000000..671ecad
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/java/com/example/android/quiz/UpdateQuestionService.java
@@ -0,0 +1,108 @@
+/*
+ * 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.android.quiz;
+
+import android.app.IntentService;
+import android.app.NotificationManager;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+
+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.DataMap;
+import com.google.android.gms.wearable.DataMapItem;
+import com.google.android.gms.wearable.PutDataMapRequest;
+import com.google.android.gms.wearable.PutDataRequest;
+import com.google.android.gms.wearable.Wearable;
+
+import java.util.concurrent.TimeUnit;
+
+import static com.example.android.quiz.Constants.CHOSEN_ANSWER_CORRECT;
+import static com.example.android.quiz.Constants.QUESTION_INDEX;
+import static com.example.android.quiz.Constants.QUESTION_WAS_ANSWERED;
+
+/**
+ * Updates quiz status on the phone when user selects an answer to a question on the watch.
+ */
+public class UpdateQuestionService extends IntentService
+ implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
+ public static final String EXTRA_QUESTION_CORRECT = "extra_question_correct";
+ public static final String EXTRA_QUESTION_INDEX = "extra_question_index";
+
+ private static final long TIME_OUT_MS = 100;
+ private static final String TAG = "UpdateQuestionService";
+
+ private GoogleApiClient mGoogleApiClient;
+
+ public UpdateQuestionService() {
+ super(UpdateQuestionService.class.getSimpleName());
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mGoogleApiClient = new GoogleApiClient.Builder(this)
+ .addApi(Wearable.API)
+ .addConnectionCallbacks(this)
+ .addOnConnectionFailedListener(this)
+ .build();
+ }
+
+ @Override
+ protected void onHandleIntent(Intent intent) {
+ mGoogleApiClient.blockingConnect(TIME_OUT_MS, TimeUnit.MILLISECONDS);
+ Uri dataItemUri = intent.getData();
+ if (!mGoogleApiClient.isConnected()) {
+ Log.e(TAG, "Failed to update data item " + dataItemUri
+ + " because client is disconnected from Google Play Services");
+ return;
+ }
+ DataApi.DataItemResult dataItemResult = Wearable.DataApi.getDataItem(
+ mGoogleApiClient, dataItemUri).await();
+ PutDataMapRequest putDataMapRequest = PutDataMapRequest
+ .createFromDataMapItem(DataMapItem.fromDataItem(dataItemResult.getDataItem()));
+ DataMap dataMap = putDataMapRequest.getDataMap();
+
+ // Update quiz status variables, which will be reflected on the phone.
+ int questionIndex = intent.getIntExtra(EXTRA_QUESTION_INDEX, -1);
+ boolean chosenAnswerCorrect = intent.getBooleanExtra(EXTRA_QUESTION_CORRECT, false);
+ dataMap.putInt(QUESTION_INDEX, questionIndex);
+ dataMap.putBoolean(CHOSEN_ANSWER_CORRECT, chosenAnswerCorrect);
+ dataMap.putBoolean(QUESTION_WAS_ANSWERED, true);
+ PutDataRequest request = putDataMapRequest.asPutDataRequest();
+ Wearable.DataApi.putDataItem(mGoogleApiClient, request).await();
+
+ // Remove this question notification.
+ ((NotificationManager) getSystemService(NOTIFICATION_SERVICE)).cancel(questionIndex);
+ mGoogleApiClient.disconnect();
+ }
+
+ @Override
+ public void onConnected(Bundle connectionHint) {
+ }
+
+ @Override
+ public void onConnectionSuspended(int cause) {
+ }
+
+ @Override
+ public void onConnectionFailed(ConnectionResult result) {
+ }
+}
diff --git a/wearable/wear/Quiz/Wearable/src/main/res/drawable-hdpi/ic_choice_a.png b/wearable/wear/Quiz/Wearable/src/main/res/drawable-hdpi/ic_choice_a.png
new file mode 100644
index 0000000..de18ce1
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/res/drawable-hdpi/ic_choice_a.png
Binary files differ
diff --git a/wearable/wear/Quiz/Wearable/src/main/res/drawable-hdpi/ic_choice_b.png b/wearable/wear/Quiz/Wearable/src/main/res/drawable-hdpi/ic_choice_b.png
new file mode 100644
index 0000000..3cdfe97
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/res/drawable-hdpi/ic_choice_b.png
Binary files differ
diff --git a/wearable/wear/Quiz/Wearable/src/main/res/drawable-hdpi/ic_choice_c.png b/wearable/wear/Quiz/Wearable/src/main/res/drawable-hdpi/ic_choice_c.png
new file mode 100644
index 0000000..f0ed2ef
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/res/drawable-hdpi/ic_choice_c.png
Binary files differ
diff --git a/wearable/wear/Quiz/Wearable/src/main/res/drawable-hdpi/ic_choice_d.png b/wearable/wear/Quiz/Wearable/src/main/res/drawable-hdpi/ic_choice_d.png
new file mode 100644
index 0000000..c158d29
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/res/drawable-hdpi/ic_choice_d.png
Binary files differ
diff --git a/wearable/wear/Quiz/Wearable/src/main/res/drawable-hdpi/ic_launcher.png b/wearable/wear/Quiz/Wearable/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100755
index 0000000..91a8cff
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Quiz/Wearable/src/main/res/drawable-hdpi/ic_unknown_choice.png b/wearable/wear/Quiz/Wearable/src/main/res/drawable-hdpi/ic_unknown_choice.png
new file mode 100644
index 0000000..9aed517
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/res/drawable-hdpi/ic_unknown_choice.png
Binary files differ
diff --git a/wearable/wear/Quiz/Wearable/src/main/res/drawable-mdpi/ic_choice_a.png b/wearable/wear/Quiz/Wearable/src/main/res/drawable-mdpi/ic_choice_a.png
new file mode 100644
index 0000000..5745936
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/res/drawable-mdpi/ic_choice_a.png
Binary files differ
diff --git a/wearable/wear/Quiz/Wearable/src/main/res/drawable-mdpi/ic_choice_b.png b/wearable/wear/Quiz/Wearable/src/main/res/drawable-mdpi/ic_choice_b.png
new file mode 100644
index 0000000..958b92e
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/res/drawable-mdpi/ic_choice_b.png
Binary files differ
diff --git a/wearable/wear/Quiz/Wearable/src/main/res/drawable-mdpi/ic_choice_c.png b/wearable/wear/Quiz/Wearable/src/main/res/drawable-mdpi/ic_choice_c.png
new file mode 100644
index 0000000..9fcfab7
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/res/drawable-mdpi/ic_choice_c.png
Binary files differ
diff --git a/wearable/wear/Quiz/Wearable/src/main/res/drawable-mdpi/ic_choice_d.png b/wearable/wear/Quiz/Wearable/src/main/res/drawable-mdpi/ic_choice_d.png
new file mode 100644
index 0000000..821cadb
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/res/drawable-mdpi/ic_choice_d.png
Binary files differ
diff --git a/wearable/wear/Quiz/Wearable/src/main/res/drawable-mdpi/ic_launcher.png b/wearable/wear/Quiz/Wearable/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100755
index 0000000..728ee6d
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Quiz/Wearable/src/main/res/drawable-mdpi/ic_unknown_choice.png b/wearable/wear/Quiz/Wearable/src/main/res/drawable-mdpi/ic_unknown_choice.png
new file mode 100644
index 0000000..b8030ef
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/res/drawable-mdpi/ic_unknown_choice.png
Binary files differ
diff --git a/wearable/wear/Quiz/Wearable/src/main/res/drawable-xhdpi/ic_choice_a.png b/wearable/wear/Quiz/Wearable/src/main/res/drawable-xhdpi/ic_choice_a.png
new file mode 100644
index 0000000..3dba96f
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/res/drawable-xhdpi/ic_choice_a.png
Binary files differ
diff --git a/wearable/wear/Quiz/Wearable/src/main/res/drawable-xhdpi/ic_choice_b.png b/wearable/wear/Quiz/Wearable/src/main/res/drawable-xhdpi/ic_choice_b.png
new file mode 100644
index 0000000..9ca3c85
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/res/drawable-xhdpi/ic_choice_b.png
Binary files differ
diff --git a/wearable/wear/Quiz/Wearable/src/main/res/drawable-xhdpi/ic_choice_c.png b/wearable/wear/Quiz/Wearable/src/main/res/drawable-xhdpi/ic_choice_c.png
new file mode 100644
index 0000000..b84b3b7
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/res/drawable-xhdpi/ic_choice_c.png
Binary files differ
diff --git a/wearable/wear/Quiz/Wearable/src/main/res/drawable-xhdpi/ic_choice_d.png b/wearable/wear/Quiz/Wearable/src/main/res/drawable-xhdpi/ic_choice_d.png
new file mode 100644
index 0000000..185e91e
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/res/drawable-xhdpi/ic_choice_d.png
Binary files differ
diff --git a/wearable/wear/Quiz/Wearable/src/main/res/drawable-xhdpi/ic_launcher.png b/wearable/wear/Quiz/Wearable/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100755
index 0000000..64a5854
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Quiz/Wearable/src/main/res/drawable-xhdpi/ic_unknown_choice.png b/wearable/wear/Quiz/Wearable/src/main/res/drawable-xhdpi/ic_unknown_choice.png
new file mode 100644
index 0000000..57838d1
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/res/drawable-xhdpi/ic_unknown_choice.png
Binary files differ
diff --git a/wearable/wear/Quiz/Wearable/src/main/res/drawable-xxhdpi/ic_launcher.png b/wearable/wear/Quiz/Wearable/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100755
index 0000000..86a395b
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Quiz/Wearable/src/main/res/values/colors.xml b/wearable/wear/Quiz/Wearable/src/main/res/values/colors.xml
new file mode 100644
index 0000000..b10adaf
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/res/values/colors.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+ <color name="dark_green">#009900</color>
+ <color name="dark_red">#800000</color>
+ <color name="dark_yellow">#FF9900</color>
+</resources>
diff --git a/wearable/wear/Quiz/Wearable/src/main/res/values/strings.xml b/wearable/wear/Quiz/Wearable/src/main/res/values/strings.xml
new file mode 100644
index 0000000..313ee4c
--- /dev/null
+++ b/wearable/wear/Quiz/Wearable/src/main/res/values/strings.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <string name="app_name">Quiz Sample Wearable App</string>
+
+ <string name="question">Question %d</string>
+
+ <string name="quiz_report">Quiz Report</string>
+ <string name="correct">correct</string>
+ <string name="incorrect">incorrect</string>
+ <string name="skipped">skipped</string>
+ <string name="reset_quiz">Reset Quiz</string>
+
+</resources>
diff --git a/wearable/wear/Quiz/build.gradle b/wearable/wear/Quiz/build.gradle
new file mode 100644
index 0000000..be1fa82
--- /dev/null
+++ b/wearable/wear/Quiz/build.gradle
@@ -0,0 +1,14 @@
+
+
+
+
+// BEGIN_EXCLUDE
+import com.example.android.samples.build.SampleGenPlugin
+apply plugin: SampleGenPlugin
+
+samplegen {
+ pathToBuild "../../../../../build"
+ pathToSamplesCommon "../../../common"
+}
+apply from: "../../../../../build/build.gradle"
+// END_EXCLUDE
diff --git a/wearable/wear/Quiz/buildSrc/build.gradle b/wearable/wear/Quiz/buildSrc/build.gradle
new file mode 100644
index 0000000..e344a8c
--- /dev/null
+++ b/wearable/wear/Quiz/buildSrc/build.gradle
@@ -0,0 +1,18 @@
+
+
+
+repositories {
+ mavenCentral()
+}
+dependencies {
+ compile 'org.freemarker:freemarker:2.3.20'
+}
+
+sourceSets {
+ main {
+ groovy {
+ srcDir new File(rootDir, "../../../../../../build/buildSrc/src/main/groovy")
+ }
+ }
+}
+
diff --git a/wearable/wear/Quiz/gradle/wrapper/gradle-wrapper.jar b/wearable/wear/Quiz/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8c0fb64
--- /dev/null
+++ b/wearable/wear/Quiz/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/wearable/wear/Quiz/gradle/wrapper/gradle-wrapper.properties b/wearable/wear/Quiz/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..d7f03cf
--- /dev/null
+++ b/wearable/wear/Quiz/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=http\://services.gradle.org/distributions/gradle-1.12-bin.zip
diff --git a/wearable/wear/Quiz/gradlew b/wearable/wear/Quiz/gradlew
new file mode 100755
index 0000000..91a7e26
--- /dev/null
+++ b/wearable/wear/Quiz/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/wearable/wear/Quiz/gradlew.bat b/wearable/wear/Quiz/gradlew.bat
new file mode 100644
index 0000000..8a0b282
--- /dev/null
+++ b/wearable/wear/Quiz/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/wearable/wear/Quiz/settings.gradle b/wearable/wear/Quiz/settings.gradle
new file mode 100644
index 0000000..8522c57
--- /dev/null
+++ b/wearable/wear/Quiz/settings.gradle
@@ -0,0 +1 @@
+include ':Application', ':Wearable', ':Shared'
diff --git a/wearable/wear/Quiz/template-params.xml b/wearable/wear/Quiz/template-params.xml
new file mode 100644
index 0000000..ca48071
--- /dev/null
+++ b/wearable/wear/Quiz/template-params.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+
+
+<sample>
+ <name>Quiz</name>
+ <group>Connectivity</group>
+ <package>com.example.android.quiz</package>
+
+
+
+ <!-- change minSdk if needed-->
+ <minSdk>20</minSdk>
+
+
+ <strings>
+ <intro>
+ <![CDATA[
+ This sample uses Google Play Services Wearable Data APIs to communicate between
+ applications on a phone and a paired wearable device. Users can create quiz questions on the phone,
+ each of which has an associated DataItem. These DataItems are then received on the wearable, which
+ displays them as notifications. Each notification contains the question as the first page, followed
+ by answers as actions. When an answer is selected, the corresponding question\'s DataItem is updated,
+ which allows the phone application to update the status of the question (i.e. did the user answer it
+ correctly or not) and prompt the next question.
+ ]]>
+ </intro>
+ </strings>
+
+ <template src="base"/>
+ <template src="Wear"/>
+ <common src="logger"/>
+ <common src="activities"/>
+
+</sample>
diff --git a/wearable/wear/RecipeAssistant/Application/.gitignore b/wearable/wear/RecipeAssistant/Application/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/RecipeAssistant/Application/proguard-project.txt b/wearable/wear/RecipeAssistant/Application/proguard-project.txt
new file mode 100644
index 0000000..0d8f171
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/proguard-project.txt
@@ -0,0 +1,20 @@
+ To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# 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/wearable/wear/RecipeAssistant/Application/src/main/AndroidManifest.xml b/wearable/wear/RecipeAssistant/Application/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..db13ed9
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/AndroidManifest.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.recipeassistant" >
+
+ <uses-sdk android:minSdkVersion="19"
+ android:targetSdkVersion="19" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@mipmap/ic_app_recipe"
+ android:label="@string/app_name"
+ android:theme="@android:style/Theme.Holo.Light" >
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity
+ android:name=".RecipeActivity"
+ android:label="@string/app_name" >
+ </activity>
+ <service
+ android:name=".RecipeService" />
+ </application>
+
+</manifest>
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/assets/beef-brisket-chili.json b/wearable/wear/RecipeAssistant/Application/src/main/assets/beef-brisket-chili.json
new file mode 100644
index 0000000..19598f9
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/assets/beef-brisket-chili.json
@@ -0,0 +1,91 @@
+{
+name: "beef-brisket-chili.json",
+steps: [
+{
+text: "Place the cinnamon stick, cumin, paprika and oregano in a pestle and mortar. Bash and grind until the cinnamon is in very small flakes. ",
+img: "step-1-grind-spices.jpg"
+},
+{
+text: "Score the beef and rub the spice mix into the cuts. ",
+img: "step-2-score-beef.jpg"
+},
+{
+text: "Season the beef and drizzle with olive oil. Brown in a hot pan. ",
+img: "step-3-brown-beef.jpg"
+},
+{
+text: "Finely slice the onion and fry in a little olive oil together with the chillies, finely sliced. You can control the heat of your chili by deseeding some of the chillies. ",
+img: "step-4-fry-onion.jpg"
+},
+{
+text: "Add the browned brisket to the pan with the onions and chillies and fry on a low heat."
+},
+{
+text: "Place the bell peppers, roughly sliced, the bay leaves and chopped tomatoes in a large covered pot. Bring to the boil and then add the beef, onions and chillies. ",
+img: "step-6-combine.jpg"
+},
+{
+text: "Bring back to the boil, cover and allow to simmer on a low heat for 4 hours."
+},
+{
+text: "Remove the brisket from the pot, place on a large plate and use two forks to pull the beef apart into individual pieces. ",
+img: "step-8-pull.jpg"
+},
+{
+text: "Remove the bay leaves and add the pulled beef and coriander back to the pot, together with the kidney beans."
+},
+{
+text: "Bring back to the boil and simmer gently for a further 15 - 20 mins."
+}
+],
+summary: "",
+title: "Beef brisket chili",
+img: "chili.jpg",
+serving: [
+"Serve with rice, yoghurt and fresh guacamole. Garnish with the remaining coriander."
+],
+ingredients: [
+{
+text: "3 lbs beef brisket"
+},
+{
+text: "2 red onions"
+},
+{
+text: "4 jalapeno chillies"
+},
+{
+text: "1 large cinnamon stick"
+},
+{
+text: "1 tbsp ground cumin"
+},
+{
+text: "1 tbsp paprika"
+},
+{
+text: "1 heaped tbsp dried oregano"
+},
+{
+text: "2 fresh bay leaves"
+},
+{
+text: "2 red bell peppers"
+},
+{
+text: "2 green bell peppers"
+},
+{
+text: "800g tin chopped tomatoes"
+},
+{
+text: "400g tin kidney beans"
+},
+{
+text: "400ml beef stock"
+},
+{
+text: "1/2 bunch coriander"
+}
+]
+}
\ No newline at end of file
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/assets/chili.jpg b/wearable/wear/RecipeAssistant/Application/src/main/assets/chili.jpg
new file mode 100644
index 0000000..ca5f751
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/assets/chili.jpg
Binary files differ
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/assets/guacamole.jpg b/wearable/wear/RecipeAssistant/Application/src/main/assets/guacamole.jpg
new file mode 100644
index 0000000..77175eb
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/assets/guacamole.jpg
Binary files differ
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/assets/guacamole.json b/wearable/wear/RecipeAssistant/Application/src/main/assets/guacamole.json
new file mode 100644
index 0000000..5fae53f
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/assets/guacamole.json
@@ -0,0 +1,36 @@
+{
+name: "guacamole.json",
+steps: [
+{
+text: "Use a spoon to scoop the flesh of the avocados into a bowl."
+},
+{
+text: "Mash with a fork until fairly smooth and creamy. Preserve some small solid chunks to add texture."
+},
+{
+text: "Add the juice of the lime. ",
+img: "step-3-lime.jpg"
+},
+{
+text: "Add the cilantro."
+},
+{
+text: "Mix thoroughly."
+}
+],
+summary: "Some guacamole recipes call for many ingredients and can be a pain to prepare. This super simple guac can be thrown together in a couple of minutes and tastes great.",
+title: "Super simple guacamole",
+img: "guacamole.jpg",
+serving: "",
+ingredients: [
+{
+text: "2 ripe avocados"
+},
+{
+text: "1 lime"
+},
+{
+text: "2 tbsp cilantro"
+}
+]
+}
\ No newline at end of file
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/assets/irish-stew.jpg b/wearable/wear/RecipeAssistant/Application/src/main/assets/irish-stew.jpg
new file mode 100644
index 0000000..0c20766
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/assets/irish-stew.jpg
Binary files differ
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/assets/northern-irish-vegetable-soup.json b/wearable/wear/RecipeAssistant/Application/src/main/assets/northern-irish-vegetable-soup.json
new file mode 100644
index 0000000..55d2591
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/assets/northern-irish-vegetable-soup.json
@@ -0,0 +1,46 @@
+{
+name: "northern-irish-vegetable-soup.json",
+steps: [
+{
+text: "Place the beef in a large stock pot, cover with water and stew for 1 - 2 hours."
+},
+{
+text: "Allow the stock to cool, skim off any fat."
+},
+{
+text: "Add the soup mix to the stock, bring to the boil and simmer for 1 hour."
+},
+{
+text: "Roughly chop the leeks (green and white parts), onion, carrots, celery and parsley. Add to the soup. Season well and simmer until the vegetables are soft."
+}
+],
+summary: "This recipe is apparently unique to Northern Ireland and uses soup/herb celery which is hard to find outside the area, but regular table celery can be substituted (including the leaves).",
+title: "Northern irish vegetable soup",
+img: "irish-stew.jpg",
+serving: [
+"Whole boiled potatoes are traditionally placed in the soup at time of serving."
+],
+ingredients: [
+{
+text: "2 lbs beef shin or similar beef on bone"
+},
+{
+text: "60g soup mix (30g barley, 15g red lentils, 15g split peas)"
+},
+{
+text: "3 carrots"
+},
+{
+text: "1 white onion"
+},
+{
+text: "field celery or 1 stalk celery, plus any leaves on the bunch"
+},
+{
+text: "2 leeks"
+},
+{
+text: "1 bunch parsley"
+}
+]
+}
\ No newline at end of file
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/assets/recipelist.json b/wearable/wear/RecipeAssistant/Application/src/main/assets/recipelist.json
new file mode 100644
index 0000000..efd787d
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/assets/recipelist.json
@@ -0,0 +1,23 @@
+{
+recipe_list:
+[
+{
+name: "guacamole.json",
+summary: "Some guacamole recipes call for many ingredients and can be a pain to prepare. This super simple guac can be thrown together in a couple of minutes and tastes great.",
+title: "Super simple guacamole",
+img: "guacamole.jpg"
+},
+{
+name: "northern-irish-vegetable-soup.json",
+summary: "This recipe is apparently unique to Northern Ireland and uses soup/herb celery which is hard to find outside the area, but regular table celery can be substituted (including the leaves).",
+title: "Northern irish vegetable soup",
+img: "irish-stew.jpg"
+},
+{
+name: "beef-brisket-chili.json",
+summary: "",
+title: "Beef brisket chili",
+img: "chili.jpg"
+}
+]
+}
\ No newline at end of file
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/assets/step-1-grind-spices.jpg b/wearable/wear/RecipeAssistant/Application/src/main/assets/step-1-grind-spices.jpg
new file mode 100644
index 0000000..9b5f2b9
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/assets/step-1-grind-spices.jpg
Binary files differ
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/assets/step-2-score-beef.jpg b/wearable/wear/RecipeAssistant/Application/src/main/assets/step-2-score-beef.jpg
new file mode 100644
index 0000000..66c549d
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/assets/step-2-score-beef.jpg
Binary files differ
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/assets/step-3-brown-beef.jpg b/wearable/wear/RecipeAssistant/Application/src/main/assets/step-3-brown-beef.jpg
new file mode 100644
index 0000000..1bb801e
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/assets/step-3-brown-beef.jpg
Binary files differ
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/assets/step-3-lime.jpg b/wearable/wear/RecipeAssistant/Application/src/main/assets/step-3-lime.jpg
new file mode 100644
index 0000000..b615d55
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/assets/step-3-lime.jpg
Binary files differ
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/assets/step-4-fry-onion.jpg b/wearable/wear/RecipeAssistant/Application/src/main/assets/step-4-fry-onion.jpg
new file mode 100644
index 0000000..b5d2a18
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/assets/step-4-fry-onion.jpg
Binary files differ
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/assets/step-6-combine.jpg b/wearable/wear/RecipeAssistant/Application/src/main/assets/step-6-combine.jpg
new file mode 100644
index 0000000..fe29405
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/assets/step-6-combine.jpg
Binary files differ
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/assets/step-8-pull.jpg b/wearable/wear/RecipeAssistant/Application/src/main/assets/step-8-pull.jpg
new file mode 100644
index 0000000..f8288a8
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/assets/step-8-pull.jpg
Binary files differ
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/java/com/example/android/recipeassistant/AssetUtils.java b/wearable/wear/RecipeAssistant/Application/src/main/java/com/example/android/recipeassistant/AssetUtils.java
new file mode 100644
index 0000000..b9ad8d5
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/java/com/example/android/recipeassistant/AssetUtils.java
@@ -0,0 +1,79 @@
+/*
+ * 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.android.recipeassistant;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.util.Log;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+final class AssetUtils {
+ private static final String TAG = "RecipeAssistant";
+
+ public static byte[] loadAsset(Context context, String asset) {
+ byte[] buffer = null;
+ try {
+ InputStream is = context.getAssets().open(asset);
+ int size = is.available();
+ buffer = new byte[size];
+ is.read(buffer);
+ is.close();
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to load asset " + asset + ": " + e);
+ }
+ return buffer;
+ }
+
+ public static JSONObject loadJSONAsset(Context context, String asset) {
+ String jsonString = new String(loadAsset(context, asset));
+ JSONObject jsonObject = null;
+ try {
+ jsonObject = new JSONObject(jsonString);
+ } catch (JSONException e) {
+ Log.e(TAG, "Failed to parse JSON asset " + asset + ": " + e);
+ }
+ return jsonObject;
+ }
+
+ public static Bitmap loadBitmapAsset(Context context, String asset) {
+ InputStream is = null;
+ Bitmap bitmap = null;
+ try {
+ is = context.getAssets().open(asset);
+ if (is != null) {
+ bitmap = BitmapFactory.decodeStream(is);
+ }
+ } catch (IOException e) {
+ Log.e(TAG, e.toString());
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException e) {
+ Log.e(TAG, "Cannot close InputStream: ", e);
+ }
+ }
+ }
+ return bitmap;
+ }
+}
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/java/com/example/android/recipeassistant/Constants.java b/wearable/wear/RecipeAssistant/Application/src/main/java/com/example/android/recipeassistant/Constants.java
new file mode 100644
index 0000000..e6d367d
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/java/com/example/android/recipeassistant/Constants.java
@@ -0,0 +1,43 @@
+/*
+ * 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.android.recipeassistant;
+
+public final class Constants {
+ private Constants() {
+ }
+ public static final String RECIPE_LIST_FILE = "recipelist.json";
+ public static final String RECIPE_NAME_TO_LOAD = "recipe_name";
+
+ public static final String RECIPE_FIELD_LIST = "recipe_list";
+ public static final String RECIPE_FIELD_IMAGE = "img";
+ public static final String RECIPE_FIELD_INGREDIENTS = "ingredients";
+ public static final String RECIPE_FIELD_NAME = "name";
+ public static final String RECIPE_FIELD_SUMMARY = "summary";
+ public static final String RECIPE_FIELD_STEPS = "steps";
+ public static final String RECIPE_FIELD_TEXT = "text";
+ public static final String RECIPE_FIELD_TITLE = "title";
+ public static final String RECIPE_FIELD_STEP_TEXT = "step_text";
+ public static final String RECIPE_FIELD_STEP_IMAGE = "step_image";
+
+ static final String ACTION_START_COOKING =
+ "com.example.android.recipeassistant.START_COOKING";
+ public static final String EXTRA_RECIPE = "recipe";
+
+ public static final int NOTIFICATION_ID = 0;
+ public static final int NOTIFICATION_IMAGE_WIDTH = 280;
+ public static final int NOTIFICATION_IMAGE_HEIGHT = 280;
+}
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/java/com/example/android/recipeassistant/MainActivity.java b/wearable/wear/RecipeAssistant/Application/src/main/java/com/example/android/recipeassistant/MainActivity.java
new file mode 100644
index 0000000..5738e2a
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/java/com/example/android/recipeassistant/MainActivity.java
@@ -0,0 +1,50 @@
+/*
+ * 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.android.recipeassistant;
+
+import android.app.ListActivity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.ListView;
+
+public class MainActivity extends ListActivity {
+
+ private static final String TAG = "RecipeAssistant";
+ private RecipeListAdapter mAdapter;
+
+ @Override
+ protected void onListItemClick(ListView l, View v, int position, long id) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG , "onListItemClick " + position);
+ }
+ String itemName = mAdapter.getItemName(position);
+ Intent intent = new Intent(getApplicationContext(), RecipeActivity.class);
+ intent.putExtra(Constants.RECIPE_NAME_TO_LOAD, itemName);
+ startActivity(intent);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(android.R.layout.list_content);
+
+ mAdapter = new RecipeListAdapter(this);
+ setListAdapter(mAdapter);
+ }
+}
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/java/com/example/android/recipeassistant/Recipe.java b/wearable/wear/RecipeAssistant/Application/src/main/java/com/example/android/recipeassistant/Recipe.java
new file mode 100644
index 0000000..3551907
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/java/com/example/android/recipeassistant/Recipe.java
@@ -0,0 +1,126 @@
+/*
+ * 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.android.recipeassistant;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.util.Log;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+
+public class Recipe {
+ private static final String TAG = "RecipeAssistant";
+
+ public String titleText;
+ public String summaryText;
+ public String recipeImage;
+ public String ingredientsText;
+
+ public static class RecipeStep {
+ RecipeStep() { }
+ public String stepImage;
+ public String stepText;
+
+ public Bundle toBundle() {
+ Bundle bundle = new Bundle();
+ bundle.putString(Constants.RECIPE_FIELD_STEP_TEXT, stepText);
+ bundle.putString(Constants.RECIPE_FIELD_STEP_IMAGE, stepImage);
+ return bundle;
+ }
+
+ public static RecipeStep fromBundle(Bundle bundle) {
+ RecipeStep recipeStep = new RecipeStep();
+ recipeStep.stepText = bundle.getString(Constants.RECIPE_FIELD_STEP_TEXT);
+ recipeStep.stepImage = bundle.getString(Constants.RECIPE_FIELD_STEP_IMAGE);
+ return recipeStep;
+ }
+ }
+ ArrayList<RecipeStep> recipeSteps;
+
+ public Recipe() {
+ recipeSteps = new ArrayList<RecipeStep>();
+ }
+
+ public static Recipe fromJson(Context context, JSONObject json) {
+ Recipe recipe = new Recipe();
+ try {
+ recipe.titleText = json.getString(Constants.RECIPE_FIELD_TITLE);
+ recipe.summaryText = json.getString(Constants.RECIPE_FIELD_SUMMARY);
+ if (json.has(Constants.RECIPE_FIELD_IMAGE)) {
+ recipe.recipeImage = json.getString(Constants.RECIPE_FIELD_IMAGE);
+ }
+ JSONArray ingredients = json.getJSONArray(Constants.RECIPE_FIELD_INGREDIENTS);
+ recipe.ingredientsText = "";
+ for (int i = 0; i < ingredients.length(); i++) {
+ recipe.ingredientsText += " - "
+ + ingredients.getJSONObject(i).getString(Constants.RECIPE_FIELD_TEXT) + "\n";
+ }
+
+ JSONArray steps = json.getJSONArray(Constants.RECIPE_FIELD_STEPS);
+ for (int i = 0; i < steps.length(); i++) {
+ JSONObject step = steps.getJSONObject(i);
+ RecipeStep recipeStep = new RecipeStep();
+ recipeStep.stepText = step.getString(Constants.RECIPE_FIELD_TEXT);
+ if (step.has(Constants.RECIPE_FIELD_IMAGE)) {
+ recipeStep.stepImage = step.getString(Constants.RECIPE_FIELD_IMAGE);
+ }
+ recipe.recipeSteps.add(recipeStep);
+ }
+ } catch (JSONException e) {
+ Log.e(TAG, "Error loading recipe: " + e);
+ return null;
+ }
+ return recipe;
+ }
+
+ public Bundle toBundle() {
+ Bundle bundle = new Bundle();
+ bundle.putString(Constants.RECIPE_FIELD_TITLE, titleText);
+ bundle.putString(Constants.RECIPE_FIELD_SUMMARY, summaryText);
+ bundle.putString(Constants.RECIPE_FIELD_IMAGE, recipeImage);
+ bundle.putString(Constants.RECIPE_FIELD_INGREDIENTS, ingredientsText);
+ if (recipeSteps != null) {
+ ArrayList<Parcelable> stepBundles = new ArrayList<Parcelable>(recipeSteps.size());
+ for (RecipeStep recipeStep : recipeSteps) {
+ stepBundles.add(recipeStep.toBundle());
+ }
+ bundle.putParcelableArrayList(Constants.RECIPE_FIELD_STEPS, stepBundles);
+ }
+ return bundle;
+ }
+
+ public static Recipe fromBundle(Bundle bundle) {
+ Recipe recipe = new Recipe();
+ recipe.titleText = bundle.getString(Constants.RECIPE_FIELD_TITLE);
+ recipe.summaryText = bundle.getString(Constants.RECIPE_FIELD_SUMMARY);
+ recipe.recipeImage = bundle.getString(Constants.RECIPE_FIELD_IMAGE);
+ recipe.ingredientsText = bundle.getString(Constants.RECIPE_FIELD_INGREDIENTS);
+ ArrayList<Parcelable> stepBundles =
+ bundle.getParcelableArrayList(Constants.RECIPE_FIELD_STEPS);
+ if (stepBundles != null) {
+ for (Parcelable stepBundle : stepBundles) {
+ recipe.recipeSteps.add(RecipeStep.fromBundle((Bundle) stepBundle));
+ }
+ }
+ return recipe;
+ }
+}
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/java/com/example/android/recipeassistant/RecipeActivity.java b/wearable/wear/RecipeAssistant/Application/src/main/java/com/example/android/recipeassistant/RecipeActivity.java
new file mode 100644
index 0000000..4b9d72d
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/java/com/example/android/recipeassistant/RecipeActivity.java
@@ -0,0 +1,138 @@
+/*
+ * 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.android.recipeassistant;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import org.json.JSONObject;
+
+public class RecipeActivity extends Activity {
+ private static final String TAG = "RecipeAssistant";
+ private String mRecipeName;
+ private Recipe mRecipe;
+ private ImageView mImageView;
+ private TextView mTitleTextView;
+ private TextView mSummaryTextView;
+ private TextView mIngredientsTextView;
+ private LinearLayout mStepsLayout;
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ Intent intent = getIntent();
+ mRecipeName = intent.getStringExtra(Constants.RECIPE_NAME_TO_LOAD);
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Intent: " + intent.toString() + " " + mRecipeName);
+ }
+ loadRecipe();
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.recipe);
+ mTitleTextView = (TextView) findViewById(R.id.recipeTextTitle);
+ mSummaryTextView = (TextView) findViewById(R.id.recipeTextSummary);
+ mImageView = (ImageView) findViewById(R.id.recipeImageView);
+ mIngredientsTextView = (TextView) findViewById(R.id.textIngredients);
+ mStepsLayout = (LinearLayout) findViewById(R.id.layoutSteps);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.main, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch(item.getItemId()) {
+ case R.id.action_cook:
+ startCooking();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ private void loadRecipe() {
+ JSONObject jsonObject = AssetUtils.loadJSONAsset(this, mRecipeName);
+ if (jsonObject != null) {
+ mRecipe = Recipe.fromJson(this, jsonObject);
+ if (mRecipe != null) {
+ displayRecipe(mRecipe);
+ }
+ }
+ }
+
+ private void displayRecipe(Recipe recipe) {
+ Animation fadeIn = AnimationUtils.loadAnimation(this, android.R.anim.fade_in);
+ mTitleTextView.setAnimation(fadeIn);
+ mTitleTextView.setText(recipe.titleText);
+ mSummaryTextView.setText(recipe.summaryText);
+ if (recipe.recipeImage != null) {
+ mImageView.setAnimation(fadeIn);
+ Bitmap recipeImage = AssetUtils.loadBitmapAsset(this, recipe.recipeImage);
+ mImageView.setImageBitmap(recipeImage);
+ }
+ mIngredientsTextView.setText(recipe.ingredientsText);
+
+ findViewById(R.id.ingredientsHeader).setAnimation(fadeIn);
+ findViewById(R.id.ingredientsHeader).setVisibility(View.VISIBLE);
+ findViewById(R.id.stepsHeader).setAnimation(fadeIn);
+
+ findViewById(R.id.stepsHeader).setVisibility(View.VISIBLE);
+
+ LayoutInflater inf = LayoutInflater.from(this);
+ mStepsLayout.removeAllViews();
+ int stepNumber = 1;
+ for (Recipe.RecipeStep step : recipe.recipeSteps) {
+ View view = inf.inflate(R.layout.step_item, null);
+ ImageView iv = (ImageView) view.findViewById(R.id.stepImageView);
+ if (step.stepImage == null) {
+ iv.setVisibility(View.GONE);
+ } else {
+ Bitmap stepImage = AssetUtils.loadBitmapAsset(this, step.stepImage);
+ iv.setImageBitmap(stepImage);
+ }
+ ((TextView) view.findViewById(R.id.textStep)).setText(
+ (stepNumber++) + ". " + step.stepText);
+ mStepsLayout.addView(view);
+ }
+ }
+
+ private void startCooking() {
+ Intent intent = new Intent(this, RecipeService.class);
+ intent.setAction(Constants.ACTION_START_COOKING);
+ intent.putExtra(Constants.EXTRA_RECIPE, mRecipe.toBundle());
+ startService(intent);
+ }
+}
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/java/com/example/android/recipeassistant/RecipeListAdapter.java b/wearable/wear/RecipeAssistant/Application/src/main/java/com/example/android/recipeassistant/RecipeListAdapter.java
new file mode 100644
index 0000000..bc602a1
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/java/com/example/android/recipeassistant/RecipeListAdapter.java
@@ -0,0 +1,173 @@
+/*
+ * 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.android.recipeassistant;
+
+import android.content.Context;
+import android.database.DataSetObserver;
+import android.graphics.Bitmap;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.ListAdapter;
+import android.widget.TextView;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class RecipeListAdapter implements ListAdapter {
+ private String TAG = "RecipeListAdapter";
+
+ private class Item {
+ String title;
+ String name;
+ String summary;
+ Bitmap image;
+ }
+
+ private List<Item> mItems = new ArrayList<Item>();
+ private Context mContext;
+ private DataSetObserver mObserver;
+
+ public RecipeListAdapter(Context context) {
+ mContext = context;
+ loadRecipeList();
+ }
+
+ private void loadRecipeList() {
+ JSONObject jsonObject = AssetUtils.loadJSONAsset(mContext, Constants.RECIPE_LIST_FILE);
+ if (jsonObject != null) {
+ List<Item> items = parseJson(jsonObject);
+ appendItemsToList(items);
+ }
+ }
+
+ private List<Item> parseJson(JSONObject json) {
+ List<Item> result = new ArrayList<Item>();
+ try {
+ JSONArray items = json.getJSONArray(Constants.RECIPE_FIELD_LIST);
+ for (int i = 0; i < items.length(); i++) {
+ JSONObject item = items.getJSONObject(i);
+ Item parsed = new Item();
+ parsed.name = item.getString(Constants.RECIPE_FIELD_NAME);
+ parsed.title = item.getString(Constants.RECIPE_FIELD_TITLE);
+ if (item.has(Constants.RECIPE_FIELD_IMAGE)) {
+ String imageFile = item.getString(Constants.RECIPE_FIELD_IMAGE);
+ parsed.image = AssetUtils.loadBitmapAsset(mContext, imageFile);
+ }
+ parsed.summary = item.getString(Constants.RECIPE_FIELD_SUMMARY);
+ result.add(parsed);
+ }
+ } catch (JSONException e) {
+ Log.e(TAG, "Failed to parse recipe list: " + e);
+ }
+ return result;
+ }
+
+ private void appendItemsToList(List<Item> items) {
+ mItems.addAll(items);
+ if (mObserver != null) {
+ mObserver.onChanged();
+ }
+ }
+
+ @Override
+ public int getCount() {
+ return mItems.size();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return mItems.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return 0;
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ return 0;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ View view = convertView;
+ if (view == null) {
+ LayoutInflater inf = LayoutInflater.from(mContext);
+ view = inf.inflate(R.layout.list_item, null);
+ }
+ Item item = (Item) getItem(position);
+ TextView titleView = (TextView) view.findViewById(R.id.textTitle);
+ TextView summaryView = (TextView) view.findViewById(R.id.textSummary);
+ ImageView iv = (ImageView) view.findViewById(R.id.imageView);
+
+ titleView.setText(item.title);
+ summaryView.setText(item.summary);
+ if (item.image != null) {
+ iv.setImageBitmap(item.image);
+ } else {
+ iv.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_noimage));
+ }
+ return view;
+ }
+
+ @Override
+ public int getViewTypeCount() {
+ return 1;
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return false;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return mItems.isEmpty();
+ }
+
+ @Override
+ public void registerDataSetObserver(DataSetObserver observer) {
+ mObserver = observer;
+ }
+
+ @Override
+ public void unregisterDataSetObserver(DataSetObserver observer) {
+ mObserver = null;
+ }
+
+ @Override
+ public boolean areAllItemsEnabled() {
+ return true;
+ }
+
+ @Override
+ public boolean isEnabled(int position) {
+ return true;
+ }
+
+ public String getItemName(int position) {
+ return mItems.get(position).name;
+ }
+}
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/java/com/example/android/recipeassistant/RecipeService.java b/wearable/wear/RecipeAssistant/Application/src/main/java/com/example/android/recipeassistant/RecipeService.java
new file mode 100644
index 0000000..74bbfda
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/java/com/example/android/recipeassistant/RecipeService.java
@@ -0,0 +1,96 @@
+/*
+ * 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.android.recipeassistant;
+
+import android.app.Notification;
+import android.app.Service;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.os.Binder;
+import android.os.IBinder;
+import android.support.v4.app.NotificationManagerCompat;
+import android.support.v4.app.NotificationCompat;
+
+import java.util.ArrayList;
+
+public class RecipeService extends Service {
+ private NotificationManagerCompat mNotificationManager;
+ private Binder mBinder = new LocalBinder();
+ private Recipe mRecipe;
+
+ public class LocalBinder extends Binder {
+ RecipeService getService() {
+ return RecipeService.this;
+ }
+ }
+
+ @Override
+ public void onCreate() {
+ mNotificationManager = NotificationManagerCompat.from(this);
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ if (intent.getAction().equals(Constants.ACTION_START_COOKING)) {
+ createNotification(intent);
+ return START_STICKY;
+ }
+ return START_NOT_STICKY;
+ }
+
+ private void createNotification(Intent intent) {
+ mRecipe = Recipe.fromBundle(intent.getBundleExtra(Constants.EXTRA_RECIPE));
+ ArrayList<Notification> notificationPages = new ArrayList<Notification>();
+
+ int stepCount = mRecipe.recipeSteps.size();
+
+ for (int i = 0; i < stepCount; ++i) {
+ Recipe.RecipeStep recipeStep = mRecipe.recipeSteps.get(i);
+ NotificationCompat.BigTextStyle style = new NotificationCompat.BigTextStyle();
+ style.bigText(recipeStep.stepText);
+ style.setBigContentTitle(String.format(
+ getResources().getString(R.string.step_count), i + 1, stepCount));
+ style.setSummaryText("");
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
+ builder.setStyle(style);
+ notificationPages.add(builder.build());
+ }
+
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
+
+ if (mRecipe.recipeImage != null) {
+ Bitmap recipeImage = Bitmap.createScaledBitmap(
+ AssetUtils.loadBitmapAsset(this, mRecipe.recipeImage),
+ Constants.NOTIFICATION_IMAGE_WIDTH, Constants.NOTIFICATION_IMAGE_HEIGHT, false);
+ builder.setLargeIcon(recipeImage);
+ }
+ builder.setContentTitle(mRecipe.titleText);
+ builder.setContentText(mRecipe.summaryText);
+ builder.setSmallIcon(R.mipmap.ic_notification_recipe);
+
+ Notification notification = builder
+ .extend(new NotificationCompat.WearableExtender()
+ .addPages(notificationPages))
+ .build();
+ mNotificationManager.notify(Constants.NOTIFICATION_ID, notification);
+ }
+}
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/res/drawable-hdpi/ic_noimage.png b/wearable/wear/RecipeAssistant/Application/src/main/res/drawable-hdpi/ic_noimage.png
new file mode 100644
index 0000000..7bba7ab
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/res/drawable-hdpi/ic_noimage.png
Binary files differ
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/res/drawable-mdpi/ic_noimage.png b/wearable/wear/RecipeAssistant/Application/src/main/res/drawable-mdpi/ic_noimage.png
new file mode 100644
index 0000000..a5ad26f
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/res/drawable-mdpi/ic_noimage.png
Binary files differ
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/res/drawable-xhdpi/ic_noimage.png b/wearable/wear/RecipeAssistant/Application/src/main/res/drawable-xhdpi/ic_noimage.png
new file mode 100644
index 0000000..8b631d1
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/res/drawable-xhdpi/ic_noimage.png
Binary files differ
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/res/layout/list_item.xml b/wearable/wear/RecipeAssistant/Application/src/main/res/layout/list_item.xml
new file mode 100644
index 0000000..756880c
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/res/layout/list_item.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginBottom="16dp"
+ android:orientation="vertical" >
+
+ <ImageView
+ android:id="@+id/imageView"
+ android:layout_width="fill_parent"
+ android:layout_height="300dp"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:layout_marginBottom="16dp"
+ android:background="@color/list_image_bg_color"
+ android:src="@drawable/ic_noimage" />
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignBottom="@+id/imageView"
+ android:layout_alignParentLeft="true"
+ android:background="@color/list_text_bg_color"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/textTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="8dp"
+ android:layout_marginLeft="8dp"
+ android:textAppearance="@style/RecipeTitleFont" />
+
+ <TextView
+ android:id="@+id/textSummary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="16dp"
+ android:layout_marginLeft="16dp"
+ android:textAppearance="@style/RecipeSummaryFont" />
+ </LinearLayout>
+
+</RelativeLayout>
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/res/layout/recipe.xml b/wearable/wear/RecipeAssistant/Application/src/main/res/layout/recipe.xml
new file mode 100644
index 0000000..3bb20b8
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/res/layout/recipe.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+
+ <ImageView
+ android:id="@+id/recipeImageView"
+ android:layout_width="fill_parent"
+ android:layout_height="300dp"
+ android:layout_marginBottom="16dp"
+ android:background="@color/list_image_bg_color"
+ android:src="@drawable/ic_noimage" />
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:background="@color/list_text_bg_color"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/recipeTextTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="8dp"
+ android:layout_marginLeft="8dp"
+ android:textAppearance="@style/RecipeHugeFont" />
+
+ <TextView
+ android:id="@+id/recipeTextSummary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="16dp"
+ android:layout_marginLeft="16dp"
+ android:textAppearance="@style/RecipeSummaryFont" />
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/ingredientsHeader"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="8dp"
+ android:layout_marginLeft="8dp"
+ android:text="@string/ingredients"
+ android:textAppearance="@style/RecipeTitleFont"
+ android:visibility="gone" />
+
+ <TextView
+ android:id="@+id/textIngredients"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="8dp"
+ android:layout_marginLeft="8dp"
+ android:textAppearance="@style/RecipeSummaryFont" />
+
+ <TextView
+ android:id="@+id/stepsHeader"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="8dp"
+ android:layout_marginLeft="8dp"
+ android:text="@string/steps"
+ android:textAppearance="@style/RecipeTitleFont"
+ android:visibility="gone" />
+
+ <LinearLayout
+ android:id="@+id/layoutSteps"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_margin="8dp"
+ android:orientation="vertical"
+ android:textAppearance="@style/RecipeSummaryFont" >
+ </LinearLayout>
+ </LinearLayout>
+
+</ScrollView>
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/res/layout/step_item.xml b/wearable/wear/RecipeAssistant/Application/src/main/res/layout/step_item.xml
new file mode 100644
index 0000000..faa5ac5
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/res/layout/step_item.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginBottom="32dp"
+ android:orientation="vertical" >
+
+ <ImageView
+ android:id="@+id/stepImageView"
+ android:layout_width="fill_parent"
+ android:layout_height="300dp"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:layout_marginBottom="16dp"
+ android:background="@color/list_image_bg_color"
+ android:src="@drawable/ic_noimage" />
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignBottom="@+id/stepImageView"
+ android:layout_alignParentLeft="true"
+ android:background="@color/list_text_bg_color"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/textStep"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="8dp"
+ android:layout_marginLeft="8dp"
+ android:layout_marginRight="8dp"
+ android:textAppearance="@style/RecipeTitleFont" />
+ </LinearLayout>
+
+</RelativeLayout>
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/res/menu/main.xml b/wearable/wear/RecipeAssistant/Application/src/main/res/menu/main.xml
new file mode 100644
index 0000000..b392472
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/res/menu/main.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:id="@+id/action_cook"
+ android:orderInCategory="100"
+ android:showAsAction="always|withText"
+ android:title="@string/action_cook" />
+</menu>
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-hdpi/ic_app_recipe.png b/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-hdpi/ic_app_recipe.png
new file mode 100644
index 0000000..8ceb869
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-hdpi/ic_app_recipe.png
Binary files differ
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-hdpi/ic_notification_recipe.png b/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-hdpi/ic_notification_recipe.png
new file mode 100644
index 0000000..844d8ed
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-hdpi/ic_notification_recipe.png
Binary files differ
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-mdpi/ic_app_recipe.png b/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-mdpi/ic_app_recipe.png
new file mode 100644
index 0000000..b884789
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-mdpi/ic_app_recipe.png
Binary files differ
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-mdpi/ic_notification_recipe.png b/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-mdpi/ic_notification_recipe.png
new file mode 100644
index 0000000..3f3f58c
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-mdpi/ic_notification_recipe.png
Binary files differ
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-xhdpi/ic_app_recipe.png b/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-xhdpi/ic_app_recipe.png
new file mode 100644
index 0000000..2a27c32
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-xhdpi/ic_app_recipe.png
Binary files differ
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-xhdpi/ic_notification_recipe.png b/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-xhdpi/ic_notification_recipe.png
new file mode 100644
index 0000000..5a99b7c
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-xhdpi/ic_notification_recipe.png
Binary files differ
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-xxhdpi/ic_app_recipe.png b/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-xxhdpi/ic_app_recipe.png
new file mode 100644
index 0000000..b10c770
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-xxhdpi/ic_app_recipe.png
Binary files differ
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-xxhdpi/ic_notification_recipe.png b/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-xxhdpi/ic_notification_recipe.png
new file mode 100644
index 0000000..799726d
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-xxhdpi/ic_notification_recipe.png
Binary files differ
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-xxxhdpi/ic_app_recipe.png b/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-xxxhdpi/ic_app_recipe.png
new file mode 100644
index 0000000..606f07f
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-xxxhdpi/ic_app_recipe.png
Binary files differ
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-xxxhdpi/ic_notification_recipe.png b/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-xxxhdpi/ic_notification_recipe.png
new file mode 100644
index 0000000..30e28a8
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/res/mipmap-xxxhdpi/ic_notification_recipe.png
Binary files differ
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/res/values/colors.xml b/wearable/wear/RecipeAssistant/Application/src/main/res/values/colors.xml
new file mode 100644
index 0000000..0f1430c
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/res/values/colors.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+ <color name="list_text_bg_color">#dfff</color>
+ <color name="list_image_bg_color">#6aaa</color>
+</resources>
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/res/values/strings.xml b/wearable/wear/RecipeAssistant/Application/src/main/res/values/strings.xml
new file mode 100644
index 0000000..f8ae109
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/res/values/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+ <string name="action_settings">Settings</string>
+ <string name="action_cook">Start</string>
+ <string name="steps">Steps</string>
+ <string name="ingredients">Ingredients</string>
+ <string name="step_count">Step %1$d of %2$d</string>
+</resources>
diff --git a/wearable/wear/RecipeAssistant/Application/src/main/res/values/styles.xml b/wearable/wear/RecipeAssistant/Application/src/main/res/values/styles.xml
new file mode 100644
index 0000000..8876dd5
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Application/src/main/res/values/styles.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <style name="RecipeTitleFont" parent="@android:style/TextAppearance.Large">
+ <item name="android:layout_width">fill_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textColor">#333333</item>
+ <item name="android:fontFamily">sans-serif</item>
+ </style>
+
+ <style name="RecipeHugeFont" parent="@android:style/TextAppearance.Large">
+ <item name="android:layout_width">fill_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textColor">#333333</item>
+ <item name="android:fontFamily">sans-serif</item>
+ <item name="android:textSize">20pt</item>
+ </style>
+
+ <style name="RecipeSummaryFont" parent="@android:style/TextAppearance.Medium">
+ <item name="android:layout_width">fill_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textColor">#333333</item>
+ <item name="android:fontFamily">sans-serif</item>
+ </style>
+</resources>
diff --git a/wearable/wear/RecipeAssistant/CONTRIB.md b/wearable/wear/RecipeAssistant/CONTRIB.md
new file mode 100644
index 0000000..14a4fcf
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/CONTRIB.md
@@ -0,0 +1,35 @@
+# How to become a contributor and submit your own code
+
+## Contributor License Agreements
+
+We'd love to accept your sample apps and patches! Before we can take them, we
+have to jump a couple of legal hurdles.
+
+Please fill out either the individual or corporate Contributor License Agreement (CLA).
+
+ * If you are an individual writing original source code and you're sure you
+ own the intellectual property, then you'll need to sign an [individual CLA]
+ (https://developers.google.com/open-source/cla/individual).
+ * If you work for a company that wants to allow you to contribute your work,
+ then you'll need to sign a [corporate CLA]
+ (https://developers.google.com/open-source/cla/corporate).
+
+Follow either of the two links above to access the appropriate CLA and
+instructions for how to sign and return it. Once we receive it, we'll be able to
+accept your pull requests.
+
+## Contributing A Patch
+
+1. Submit an issue describing your proposed change to the repo in question.
+1. The repo owner will respond to your issue promptly.
+1. If your proposed change is accepted, and you haven't already done so, sign a
+ Contributor License Agreement (see details above).
+1. Fork the desired repo, develop and test your code changes.
+1. Ensure that your code adheres to the existing style in the sample to which
+ you are contributing. Refer to the
+ [Android Code Style Guide]
+ (https://source.android.com/source/code-style.html) for the
+ recommended coding standards for this organization.
+1. Ensure that your code has an appropriate set of unit tests which all pass.
+1. Submit a pull request.
+
diff --git a/wearable/wear/RecipeAssistant/LICENSE b/wearable/wear/RecipeAssistant/LICENSE
new file mode 100644
index 0000000..1af981f
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/LICENSE
@@ -0,0 +1,201 @@
+ 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 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/wearable/wear/RecipeAssistant/README-wear.txt b/wearable/wear/RecipeAssistant/README-wear.txt
new file mode 100644
index 0000000..17523d7
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/README-wear.txt
@@ -0,0 +1,30 @@
+<#--
+ Copyright 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.
+-->
+
+Steps to use Wear template on top of an existing sample:
+- In template-params.xml.ftl:
+ - Add the following template:
+ <template src="Wear"/>
+
+- Refresh your project (./gradlew refresh)
+- Add Wearable-specific code to Wearable directory
+- Add code to be shared among the main application and the wearable to Shared
+ directory
+
+Note that you still need the main application sample code. This is usually
+achieved by adding another template, like "base" for example.
+
+
diff --git a/wearable/wear/RecipeAssistant/Shared/.gitignore b/wearable/wear/RecipeAssistant/Shared/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Shared/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/RecipeAssistant/Shared/src/main/AndroidManifest.xml b/wearable/wear/RecipeAssistant/Shared/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..1951e26
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Shared/src/main/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.recipeassistant.common">
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name">
+ </application>
+
+</manifest>
diff --git a/wearable/wear/RecipeAssistant/Shared/src/main/res/values/strings.xml b/wearable/wear/RecipeAssistant/Shared/src/main/res/values/strings.xml
new file mode 100644
index 0000000..0f2bb90
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Shared/src/main/res/values/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+ <string name="app_name">Shared</string>
+</resources>
diff --git a/wearable/wear/RecipeAssistant/Wearable/.gitignore b/wearable/wear/RecipeAssistant/Wearable/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/Wearable/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/RecipeAssistant/build.gradle b/wearable/wear/RecipeAssistant/build.gradle
new file mode 100644
index 0000000..be1fa82
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/build.gradle
@@ -0,0 +1,14 @@
+
+
+
+
+// BEGIN_EXCLUDE
+import com.example.android.samples.build.SampleGenPlugin
+apply plugin: SampleGenPlugin
+
+samplegen {
+ pathToBuild "../../../../../build"
+ pathToSamplesCommon "../../../common"
+}
+apply from: "../../../../../build/build.gradle"
+// END_EXCLUDE
diff --git a/wearable/wear/RecipeAssistant/buildSrc/build.gradle b/wearable/wear/RecipeAssistant/buildSrc/build.gradle
new file mode 100644
index 0000000..e344a8c
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/buildSrc/build.gradle
@@ -0,0 +1,18 @@
+
+
+
+repositories {
+ mavenCentral()
+}
+dependencies {
+ compile 'org.freemarker:freemarker:2.3.20'
+}
+
+sourceSets {
+ main {
+ groovy {
+ srcDir new File(rootDir, "../../../../../../build/buildSrc/src/main/groovy")
+ }
+ }
+}
+
diff --git a/wearable/wear/RecipeAssistant/gradle/wrapper/gradle-wrapper.jar b/wearable/wear/RecipeAssistant/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8c0fb64
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/wearable/wear/RecipeAssistant/gradle/wrapper/gradle-wrapper.properties b/wearable/wear/RecipeAssistant/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..d7f03cf
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/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=http\://services.gradle.org/distributions/gradle-1.12-bin.zip
diff --git a/wearable/wear/RecipeAssistant/gradlew b/wearable/wear/RecipeAssistant/gradlew
new file mode 100755
index 0000000..91a7e26
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/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/wearable/wear/RecipeAssistant/gradlew.bat b/wearable/wear/RecipeAssistant/gradlew.bat
new file mode 100644
index 0000000..8a0b282
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/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/wearable/wear/RecipeAssistant/settings.gradle b/wearable/wear/RecipeAssistant/settings.gradle
new file mode 100644
index 0000000..360755c
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/settings.gradle
@@ -0,0 +1 @@
+include ':Application', ':Shared'
diff --git a/wearable/wear/RecipeAssistant/template-params.xml b/wearable/wear/RecipeAssistant/template-params.xml
new file mode 100644
index 0000000..955c92d
--- /dev/null
+++ b/wearable/wear/RecipeAssistant/template-params.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+
+
+<sample>
+ <name>RecipeAssistant</name>
+ <group>Connectivity</group>
+ <package>com.example.android.recipeassistant</package>
+
+
+
+ <!-- change minSdk if needed-->
+ <minSdk>20</minSdk>
+
+
+ <strings>
+ <intro>
+ <![CDATA[
+ This phone application uses the enhanced notifications API to display recipe
+ instructions using paged notifications. After starting the application on your phone, you can browse
+ from a short list of recipes and select one to view. Each recipe is broken down into a number of
+ steps; when ready, you can click on the START action in the action bar to send the steps to the
+ wearable. On the wearable device, the steps are displayed as a multi-page notification, with one
+ page for each step in the recipe.
+ ]]>
+ </intro>
+ </strings>
+
+ <template src="base"/>
+ <common src="logger"/>
+ <common src="activities"/>
+
+</sample>
diff --git a/wearable/wear/SkeletonWearableApp/Application/.gitignore b/wearable/wear/SkeletonWearableApp/Application/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/Application/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/SkeletonWearableApp/Application/proguard-project.txt b/wearable/wear/SkeletonWearableApp/Application/proguard-project.txt
new file mode 100644
index 0000000..0d8f171
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/Application/proguard-project.txt
@@ -0,0 +1,20 @@
+ To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# 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/wearable/wear/SkeletonWearableApp/Application/src/main/AndroidManifest.xml b/wearable/wear/SkeletonWearableApp/Application/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..7e19680
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/Application/src/main/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.skeletonwearableapp">
+
+ <uses-sdk android:minSdkVersion="19"
+ android:targetSdkVersion="19" />
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name">
+ </application>
+
+</manifest>
+
diff --git a/wearable/wear/SkeletonWearableApp/CONTRIB.md b/wearable/wear/SkeletonWearableApp/CONTRIB.md
new file mode 100644
index 0000000..14a4fcf
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/CONTRIB.md
@@ -0,0 +1,35 @@
+# How to become a contributor and submit your own code
+
+## Contributor License Agreements
+
+We'd love to accept your sample apps and patches! Before we can take them, we
+have to jump a couple of legal hurdles.
+
+Please fill out either the individual or corporate Contributor License Agreement (CLA).
+
+ * If you are an individual writing original source code and you're sure you
+ own the intellectual property, then you'll need to sign an [individual CLA]
+ (https://developers.google.com/open-source/cla/individual).
+ * If you work for a company that wants to allow you to contribute your work,
+ then you'll need to sign a [corporate CLA]
+ (https://developers.google.com/open-source/cla/corporate).
+
+Follow either of the two links above to access the appropriate CLA and
+instructions for how to sign and return it. Once we receive it, we'll be able to
+accept your pull requests.
+
+## Contributing A Patch
+
+1. Submit an issue describing your proposed change to the repo in question.
+1. The repo owner will respond to your issue promptly.
+1. If your proposed change is accepted, and you haven't already done so, sign a
+ Contributor License Agreement (see details above).
+1. Fork the desired repo, develop and test your code changes.
+1. Ensure that your code adheres to the existing style in the sample to which
+ you are contributing. Refer to the
+ [Android Code Style Guide]
+ (https://source.android.com/source/code-style.html) for the
+ recommended coding standards for this organization.
+1. Ensure that your code has an appropriate set of unit tests which all pass.
+1. Submit a pull request.
+
diff --git a/wearable/wear/SkeletonWearableApp/LICENSE b/wearable/wear/SkeletonWearableApp/LICENSE
new file mode 100644
index 0000000..1af981f
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/LICENSE
@@ -0,0 +1,201 @@
+ 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 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/wearable/wear/SkeletonWearableApp/README-wear.txt b/wearable/wear/SkeletonWearableApp/README-wear.txt
new file mode 100644
index 0000000..17523d7
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/README-wear.txt
@@ -0,0 +1,30 @@
+<#--
+ Copyright 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.
+-->
+
+Steps to use Wear template on top of an existing sample:
+- In template-params.xml.ftl:
+ - Add the following template:
+ <template src="Wear"/>
+
+- Refresh your project (./gradlew refresh)
+- Add Wearable-specific code to Wearable directory
+- Add code to be shared among the main application and the wearable to Shared
+ directory
+
+Note that you still need the main application sample code. This is usually
+achieved by adding another template, like "base" for example.
+
+
diff --git a/wearable/wear/SkeletonWearableApp/Shared/.gitignore b/wearable/wear/SkeletonWearableApp/Shared/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/Shared/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/SkeletonWearableApp/Shared/src/main/AndroidManifest.xml b/wearable/wear/SkeletonWearableApp/Shared/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..5e29d53
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/Shared/src/main/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.skeletonwearableapp.common">
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name">
+ </application>
+
+</manifest>
diff --git a/wearable/wear/SkeletonWearableApp/Shared/src/main/res/values/strings.xml b/wearable/wear/SkeletonWearableApp/Shared/src/main/res/values/strings.xml
new file mode 100644
index 0000000..0f2bb90
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/Shared/src/main/res/values/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+ <string name="app_name">Shared</string>
+</resources>
diff --git a/wearable/wear/SkeletonWearableApp/Wearable/.gitignore b/wearable/wear/SkeletonWearableApp/Wearable/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/Wearable/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/SkeletonWearableApp/Wearable/src/main/AndroidManifest.xml b/wearable/wear/SkeletonWearableApp/Wearable/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..3e9310e
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/Wearable/src/main/AndroidManifest.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.skeletonwearableapp" >
+
+ <uses-sdk android:minSdkVersion="20"
+ android:targetSdkVersion="20" />
+
+ <uses-feature android:name="android.hardware.type.watch" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@android:style/Theme.DeviceDefault">
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ <intent-filter>
+ <action android:name="com.google.android.clockwork.example.SKELETON"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
+ </activity>
+ <activity
+ android:name=".GridExampleActivity">
+ <intent-filter>
+ <action android:name="com.example.android.skeletonwearableapp.GRID_ACTIVITY"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/wearable/wear/SkeletonWearableApp/Wearable/src/main/java/com/example/android/skeletonwearableapp/GridExampleActivity.java b/wearable/wear/SkeletonWearableApp/Wearable/src/main/java/com/example/android/skeletonwearableapp/GridExampleActivity.java
new file mode 100644
index 0000000..c0d0b2b
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/Wearable/src/main/java/com/example/android/skeletonwearableapp/GridExampleActivity.java
@@ -0,0 +1,108 @@
+/*
+ * 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.android.skeletonwearableapp;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.Typeface;
+import android.os.Bundle;
+import android.support.wearable.view.CardFragment;
+import android.support.wearable.view.FragmentGridPagerAdapter;
+import android.support.wearable.view.GridViewPager;
+import android.support.wearable.view.ImageReference;
+import java.util.HashMap;
+import java.util.Map;
+
+public class GridExampleActivity extends Activity {
+ private static final int NUM_ROWS = 10;
+ private static final int NUM_COLS = 3;
+
+ MainAdapter mAdapter;
+ GridViewPager mPager;
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.grid_activity);
+ mPager = (GridViewPager) findViewById(R.id.fragment_container);
+ mAdapter = new MainAdapter(getFragmentManager());
+ mPager.setAdapter(mAdapter);
+
+ }
+
+ private static class MainAdapter extends FragmentGridPagerAdapter{
+ Map<Point, ImageReference> mBackgrounds = new HashMap<Point, ImageReference>();
+
+ public MainAdapter(FragmentManager fm) {
+ super(fm);
+ }
+
+ @Override
+ public int getRowCount() {
+ return NUM_ROWS;
+ }
+
+ @Override
+ public int getColumnCount(int rowNum) {
+ return NUM_COLS;
+ }
+
+ @Override
+ public Fragment getFragment(int rowNum, int colNum) {
+ return MainFragment.newInstance(rowNum, colNum);
+ }
+
+ @Override
+ public ImageReference getBackground(int row, int column) {
+ Point pt = new Point(column, row);
+ ImageReference ref = mBackgrounds.get(pt);
+ if (ref == null) {
+ Bitmap bm = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(bm);
+ Paint p = new Paint();
+ // Clear previous image.
+ c.drawRect(0, 0, 200, 200, p);
+ p.setAntiAlias(true);
+ p.setTypeface(Typeface.DEFAULT);
+ p.setTextSize(64);
+ p.setColor(Color.LTGRAY);
+ c.drawText(column+ "-" + row, 20, 100, p);
+ ref = ImageReference.forBitmap(bm);
+ mBackgrounds.put(pt, ref);
+ }
+ return ref;
+ }
+ }
+
+ public static class MainFragment extends CardFragment {
+ private static MainFragment newInstance(int rowNum, int colNum) {
+ Bundle args = new Bundle();
+ args.putString(CardFragment.KEY_TITLE, "Row:" + rowNum);
+ args.putString(CardFragment.KEY_TEXT, "Col:" + colNum);
+ MainFragment f = new MainFragment();
+ f.setArguments(args);
+ return f;
+ }
+ }
+}
diff --git a/wearable/wear/SkeletonWearableApp/Wearable/src/main/java/com/example/android/skeletonwearableapp/MainActivity.java b/wearable/wear/SkeletonWearableApp/Wearable/src/main/java/com/example/android/skeletonwearableapp/MainActivity.java
new file mode 100644
index 0000000..b7a91e6
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/Wearable/src/main/java/com/example/android/skeletonwearableapp/MainActivity.java
@@ -0,0 +1,129 @@
+/*
+ * 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.android.skeletonwearableapp;
+
+import android.app.Activity;
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v4.app.NotificationCompat;
+import android.support.v4.app.NotificationManagerCompat;
+import android.support.v4.view.GestureDetectorCompat;
+import android.support.wearable.view.DelayedConfirmationView;
+import android.support.wearable.view.DismissOverlayView;
+import android.util.Log;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.ScrollView;
+
+public class MainActivity extends Activity
+ implements DelayedConfirmationView.DelayedConfirmationListener {
+ private static final String TAG = "MainActivity";
+
+ private static final int NOTIFICATION_ID = 1;
+ private static final int NOTIFICATION_REQUEST_CODE = 1;
+ private static final int NUM_SECONDS = 5;
+
+ private GestureDetectorCompat mGestureDetector;
+ private DismissOverlayView mDismissOverlayView;
+
+ @Override
+ public void onCreate(Bundle b) {
+ super.onCreate(b);
+ setContentView(R.layout.main_activity);
+
+ mDismissOverlayView = (DismissOverlayView) findViewById(R.id.dismiss_overlay);
+ mDismissOverlayView.setIntroText(R.string.intro_text);
+ mDismissOverlayView.showIntroIfNecessary();
+ mGestureDetector = new GestureDetectorCompat(this, new LongPressListener());
+ }
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent event) {
+ return mGestureDetector.onTouchEvent(event) || super.dispatchTouchEvent(event);
+ }
+
+ private class LongPressListener extends GestureDetector.SimpleOnGestureListener {
+ @Override
+ public void onLongPress(MotionEvent event) {
+ mDismissOverlayView.show();
+ }
+ }
+
+ /**
+ * Handles the button to launch a notification.
+ */
+ public void showNotification(View view) {
+ Notification notification = new NotificationCompat.Builder(this)
+ .setContentTitle(getString(R.string.notification_title))
+ .setContentText(getString(R.string.notification_title))
+ .setSmallIcon(R.drawable.ic_launcher)
+ .addAction(R.drawable.ic_launcher,
+ getText(R.string.action_launch_activity),
+ PendingIntent.getActivity(this, NOTIFICATION_REQUEST_CODE,
+ new Intent(this, GridExampleActivity.class),
+ PendingIntent.FLAG_UPDATE_CURRENT))
+ .build();
+ NotificationManagerCompat.from(this).notify(NOTIFICATION_ID, notification);
+ finish();
+ }
+
+
+ /**
+ * Handles the button press to finish this activity and take the user back to the Home.
+ */
+ public void onFinishActivity(View view) {
+ setResult(RESULT_OK);
+ finish();
+ }
+
+ /**
+ * Handles the button to start a DelayedConfirmationView timer.
+ */
+ public void onStartTimer(View view) {
+ DelayedConfirmationView delayedConfirmationView = (DelayedConfirmationView)
+ findViewById(R.id.timer);
+ delayedConfirmationView.setTotalTimeMs(NUM_SECONDS * 1000);
+ delayedConfirmationView.setListener(this);
+ delayedConfirmationView.start();
+ scroll(View.FOCUS_DOWN);
+ }
+
+ @Override
+ public void onTimerFinished(View v) {
+ Log.d(TAG, "onTimerFinished is called.");
+ scroll(View.FOCUS_UP);
+ }
+
+ @Override
+ public void onTimerSelected(View v) {
+ Log.d(TAG, "onTimerSelected is called.");
+ scroll(View.FOCUS_UP);
+ }
+
+ private void scroll(final int scrollDirection) {
+ final ScrollView scrollView = (ScrollView) findViewById(R.id.scroll);
+ scrollView.post(new Runnable() {
+ @Override
+ public void run() {
+ scrollView.fullScroll(scrollDirection);
+ }
+ });
+ }
+}
diff --git a/wearable/wear/SkeletonWearableApp/Wearable/src/main/res/drawable-hdpi/ic_launcher.png b/wearable/wear/SkeletonWearableApp/Wearable/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100755
index 0000000..589f229
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/Wearable/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/SkeletonWearableApp/Wearable/src/main/res/drawable-mdpi/ic_launcher.png b/wearable/wear/SkeletonWearableApp/Wearable/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100755
index 0000000..77dd571
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/Wearable/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/SkeletonWearableApp/Wearable/src/main/res/drawable-xhdpi/ic_launcher.png b/wearable/wear/SkeletonWearableApp/Wearable/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100755
index 0000000..fe34ebe
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/Wearable/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/SkeletonWearableApp/Wearable/src/main/res/drawable-xxhdpi/ic_launcher.png b/wearable/wear/SkeletonWearableApp/Wearable/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100755
index 0000000..ab80bcd
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/Wearable/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/SkeletonWearableApp/Wearable/src/main/res/layout/grid_activity.xml b/wearable/wear/SkeletonWearableApp/Wearable/src/main/res/layout/grid_activity.xml
new file mode 100644
index 0000000..c867051
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/Wearable/src/main/res/layout/grid_activity.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<android.support.wearable.view.GridViewPager
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/fragment_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
diff --git a/wearable/wear/SkeletonWearableApp/Wearable/src/main/res/layout/main_activity.xml b/wearable/wear/SkeletonWearableApp/Wearable/src/main/res/layout/main_activity.xml
new file mode 100644
index 0000000..c949e5f
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/Wearable/src/main/res/layout/main_activity.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <ScrollView
+ android:id="@+id/scroll"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:background="#000000"
+ android:fillViewport="true">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="2dp"
+ android:text="@string/main_activity_title_text"
+ android:textSize="36sp"
+ android:textColor="#006600"/>
+
+ <Button
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:onClick="showNotification"
+ android:text="@string/show_notification" />
+
+ <Button
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:onClick="onFinishActivity"
+ android:text="@string/finish_activity" />
+
+ <Button
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/start_timer_button"
+ android:onClick="onStartTimer"
+ android:text="@string/start_timer" />
+
+ <android.support.wearable.view.DelayedConfirmationView
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/timer"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:src="@drawable/ic_launcher"
+ app:circle_color="@color/blue"
+ app:circle_padding="@dimen/circle_padding"
+ app:circle_border_width="@dimen/circle_border_normal_width"
+ app:circle_border_color="@color/white"
+ app:circle_radius="@dimen/circle_radius"/>
+
+ </LinearLayout>
+
+ </ScrollView>
+
+ <android.support.wearable.view.DismissOverlayView
+ android:id="@+id/dismiss_overlay"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+</FrameLayout>
diff --git a/wearable/wear/SkeletonWearableApp/Wearable/src/main/res/values/dimens.xml b/wearable/wear/SkeletonWearableApp/Wearable/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..67c9677
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/Wearable/src/main/res/values/dimens.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+ <dimen name="circle_border_normal_width">10dp</dimen>
+ <dimen name="circle_padding">5dp</dimen>
+ <dimen name="circle_radius">50dp</dimen>
+</resources>
diff --git a/wearable/wear/SkeletonWearableApp/Wearable/src/main/res/values/strings.xml b/wearable/wear/SkeletonWearableApp/Wearable/src/main/res/values/strings.xml
new file mode 100644
index 0000000..3917d07
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/Wearable/src/main/res/values/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+
+ <string name="app_name">Skeleton Wearable App</string>
+ <string name="intro_text">Long press to go back home.</string>
+ <string name="main_activity_title_text"> Main Activity </string>
+ <string name="grid_activity_title_text"> Grid Activity </string>
+ <string name="finish_activity"> Finish Activity </string>
+ <string name="start_timer"> Start Timer (5 sec) </string>
+ <string name="show_notification"> Show Notification </string>
+ <string name="notification_title"> Skeleton App Notification </string>
+ <string name="action_launch_activity">Launch Activity</string>
+</resources>
diff --git a/wearable/wear/SkeletonWearableApp/build.gradle b/wearable/wear/SkeletonWearableApp/build.gradle
new file mode 100644
index 0000000..be1fa82
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/build.gradle
@@ -0,0 +1,14 @@
+
+
+
+
+// BEGIN_EXCLUDE
+import com.example.android.samples.build.SampleGenPlugin
+apply plugin: SampleGenPlugin
+
+samplegen {
+ pathToBuild "../../../../../build"
+ pathToSamplesCommon "../../../common"
+}
+apply from: "../../../../../build/build.gradle"
+// END_EXCLUDE
diff --git a/wearable/wear/SkeletonWearableApp/buildSrc/build.gradle b/wearable/wear/SkeletonWearableApp/buildSrc/build.gradle
new file mode 100644
index 0000000..e344a8c
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/buildSrc/build.gradle
@@ -0,0 +1,18 @@
+
+
+
+repositories {
+ mavenCentral()
+}
+dependencies {
+ compile 'org.freemarker:freemarker:2.3.20'
+}
+
+sourceSets {
+ main {
+ groovy {
+ srcDir new File(rootDir, "../../../../../../build/buildSrc/src/main/groovy")
+ }
+ }
+}
+
diff --git a/wearable/wear/SkeletonWearableApp/gradle/wrapper/gradle-wrapper.jar b/wearable/wear/SkeletonWearableApp/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8c0fb64
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/wearable/wear/SkeletonWearableApp/gradle/wrapper/gradle-wrapper.properties b/wearable/wear/SkeletonWearableApp/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..d7f03cf
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/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=http\://services.gradle.org/distributions/gradle-1.12-bin.zip
diff --git a/wearable/wear/SkeletonWearableApp/gradlew b/wearable/wear/SkeletonWearableApp/gradlew
new file mode 100755
index 0000000..91a7e26
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/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/wearable/wear/SkeletonWearableApp/gradlew.bat b/wearable/wear/SkeletonWearableApp/gradlew.bat
new file mode 100644
index 0000000..8a0b282
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/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/wearable/wear/SkeletonWearableApp/settings.gradle b/wearable/wear/SkeletonWearableApp/settings.gradle
new file mode 100644
index 0000000..8522c57
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/settings.gradle
@@ -0,0 +1 @@
+include ':Application', ':Wearable', ':Shared'
diff --git a/wearable/wear/SkeletonWearableApp/template-params.xml b/wearable/wear/SkeletonWearableApp/template-params.xml
new file mode 100644
index 0000000..bf838f4
--- /dev/null
+++ b/wearable/wear/SkeletonWearableApp/template-params.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+
+
+<sample>
+ <name>SkeletonWearableApp</name>
+ <group>Connectivity</group>
+ <package>com.example.android.skeletonwearableapp</package>
+
+
+
+ <!-- change minSdk if needed-->
+ <minSdk>20</minSdk>
+
+
+ <strings>
+ <intro>
+ <![CDATA[
+ This sample is a mostly empty wearable app that implements a fullscreen activity
+ conforming to Android Wear best practices. Included in the sample are examples of GridViewPager,
+ DelayedConfirmationView, and DismissOverlayView. Developers who require a fullscreen activity for
+ their wearable app can use this sample as a starting point.
+ ]]>
+ </intro>
+ </strings>
+
+ <template src="base"/>
+ <template src="Wear"/>
+ <common src="logger"/>
+ <common src="activities"/>
+
+</sample>
diff --git a/wearable/wear/Timer/Application/.gitignore b/wearable/wear/Timer/Application/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/Timer/Application/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/Timer/Application/proguard-project.txt b/wearable/wear/Timer/Application/proguard-project.txt
new file mode 100644
index 0000000..0d8f171
--- /dev/null
+++ b/wearable/wear/Timer/Application/proguard-project.txt
@@ -0,0 +1,20 @@
+ To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# 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/wearable/wear/Timer/Application/src/main/AndroidManifest.xml b/wearable/wear/Timer/Application/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..b8ebd74
--- /dev/null
+++ b/wearable/wear/Timer/Application/src/main/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.timer">
+
+ <uses-sdk android:minSdkVersion="19"
+ android:targetSdkVersion="19" />
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name">
+ </application>
+
+</manifest>
+
diff --git a/wearable/wear/Timer/CONTRIB.md b/wearable/wear/Timer/CONTRIB.md
new file mode 100644
index 0000000..14a4fcf
--- /dev/null
+++ b/wearable/wear/Timer/CONTRIB.md
@@ -0,0 +1,35 @@
+# How to become a contributor and submit your own code
+
+## Contributor License Agreements
+
+We'd love to accept your sample apps and patches! Before we can take them, we
+have to jump a couple of legal hurdles.
+
+Please fill out either the individual or corporate Contributor License Agreement (CLA).
+
+ * If you are an individual writing original source code and you're sure you
+ own the intellectual property, then you'll need to sign an [individual CLA]
+ (https://developers.google.com/open-source/cla/individual).
+ * If you work for a company that wants to allow you to contribute your work,
+ then you'll need to sign a [corporate CLA]
+ (https://developers.google.com/open-source/cla/corporate).
+
+Follow either of the two links above to access the appropriate CLA and
+instructions for how to sign and return it. Once we receive it, we'll be able to
+accept your pull requests.
+
+## Contributing A Patch
+
+1. Submit an issue describing your proposed change to the repo in question.
+1. The repo owner will respond to your issue promptly.
+1. If your proposed change is accepted, and you haven't already done so, sign a
+ Contributor License Agreement (see details above).
+1. Fork the desired repo, develop and test your code changes.
+1. Ensure that your code adheres to the existing style in the sample to which
+ you are contributing. Refer to the
+ [Android Code Style Guide]
+ (https://source.android.com/source/code-style.html) for the
+ recommended coding standards for this organization.
+1. Ensure that your code has an appropriate set of unit tests which all pass.
+1. Submit a pull request.
+
diff --git a/wearable/wear/Timer/LICENSE b/wearable/wear/Timer/LICENSE
new file mode 100644
index 0000000..1af981f
--- /dev/null
+++ b/wearable/wear/Timer/LICENSE
@@ -0,0 +1,201 @@
+ 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 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/wearable/wear/Timer/README-wear.txt b/wearable/wear/Timer/README-wear.txt
new file mode 100644
index 0000000..17523d7
--- /dev/null
+++ b/wearable/wear/Timer/README-wear.txt
@@ -0,0 +1,30 @@
+<#--
+ Copyright 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.
+-->
+
+Steps to use Wear template on top of an existing sample:
+- In template-params.xml.ftl:
+ - Add the following template:
+ <template src="Wear"/>
+
+- Refresh your project (./gradlew refresh)
+- Add Wearable-specific code to Wearable directory
+- Add code to be shared among the main application and the wearable to Shared
+ directory
+
+Note that you still need the main application sample code. This is usually
+achieved by adding another template, like "base" for example.
+
+
diff --git a/wearable/wear/Timer/Shared/.gitignore b/wearable/wear/Timer/Shared/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/Timer/Shared/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/Timer/Shared/src/main/AndroidManifest.xml b/wearable/wear/Timer/Shared/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..c332a84
--- /dev/null
+++ b/wearable/wear/Timer/Shared/src/main/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.timer.common">
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name">
+ </application>
+
+</manifest>
diff --git a/wearable/wear/Timer/Shared/src/main/res/values/strings.xml b/wearable/wear/Timer/Shared/src/main/res/values/strings.xml
new file mode 100644
index 0000000..0f2bb90
--- /dev/null
+++ b/wearable/wear/Timer/Shared/src/main/res/values/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+ <string name="app_name">Shared</string>
+</resources>
diff --git a/wearable/wear/Timer/Wearable/.gitignore b/wearable/wear/Timer/Wearable/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/Timer/Wearable/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/Timer/Wearable/src/main/AndroidManifest.xml b/wearable/wear/Timer/Wearable/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..3dabadc
--- /dev/null
+++ b/wearable/wear/Timer/Wearable/src/main/AndroidManifest.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.timer" >
+
+ <uses-sdk android:minSdkVersion="20"
+ android:targetSdkVersion="20" />
+
+ <uses-feature android:name="android.hardware.type.watch" />
+
+ <application
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@android:style/Theme.DeviceDefault.Light"
+ android:allowBackup="true">
+
+ <!-- Timer components -->
+ <activity android:name=".SetTimerActivity">
+ <intent-filter>
+ <action android:name="com.android.example.clockwork.timer.TIMER"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
+ <!-- Set a timer voice command -->
+ <intent-filter>
+ <action android:name="android.intent.action.SET_TIMER"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
+ </activity>
+
+ <service android:name=".TimerNotificationService" />
+
+ </application>
+</manifest>
diff --git a/wearable/wear/Timer/Wearable/src/main/java/com/example/android/timer/SetTimerActivity.java b/wearable/wear/Timer/Wearable/src/main/java/com/example/android/timer/SetTimerActivity.java
new file mode 100644
index 0000000..5285589
--- /dev/null
+++ b/wearable/wear/Timer/Wearable/src/main/java/com/example/android/timer/SetTimerActivity.java
@@ -0,0 +1,217 @@
+/*
+ * 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.android.timer;
+
+import android.app.Activity;
+import android.app.AlarmManager;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.provider.AlarmClock;
+import android.support.wearable.view.WearableListView;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import com.example.android.timer.util.Constants;
+import com.example.android.timer.util.TimerFormat;
+
+/** This class sets a timer. */
+public class SetTimerActivity extends Activity implements WearableListView.ClickListener {
+
+ public static final int NUMBER_OF_TIMES = 10;
+ public static final String TAG = "SetTimerActivity";
+
+ private ListViewItem[] mTimeOptions = new ListViewItem[NUMBER_OF_TIMES];
+ private WearableListView mWearableListView;
+
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ int paramLength = getIntent().getIntExtra(AlarmClock.EXTRA_LENGTH, 0);
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "SetTimerActivity:onCreate=" + paramLength);
+ }
+ if (paramLength > 0 && paramLength <= 86400) {
+ long durationMillis = paramLength * 1000;
+ setupTimer(durationMillis);
+ finish();
+ return;
+ }
+
+ Resources res = getResources();
+ for (int i = 0; i < NUMBER_OF_TIMES; i++) {
+ mTimeOptions[i] = new ListViewItem(
+ res.getQuantityString(R.plurals.timer_minutes, i + 1, i + 1),
+ (i + 1) * 60 * 1000);
+ }
+
+ setContentView(R.layout.timer_set_timer);
+
+ // Initialize a simple list of countdown time options.
+ mWearableListView = (WearableListView) findViewById(R.id.times_list_view);
+ mWearableListView.setAdapter(new TimerWearableListViewAdapter(this));
+ mWearableListView.setClickListener(this);
+ }
+
+ /**
+ * Sets up an alarm (and an associated notification) to go off after <code>duration</code>
+ * milliseconds.
+ */
+ private void setupTimer(long duration) {
+ NotificationManager notifyMgr =
+ ((NotificationManager) getSystemService(NOTIFICATION_SERVICE));
+
+ // Delete dataItem and cancel a potential old countdown.
+ cancelCountdown(notifyMgr);
+
+ // Build notification and set it.
+ notifyMgr.notify(Constants.NOTIFICATION_TIMER_COUNTDOWN, buildNotification(duration));
+
+ // Register with the alarm manager to display a notification when the timer is done.
+ registerWithAlarmManager(duration);
+
+ finish();
+ }
+
+ @Override
+ public void onClick(WearableListView.ViewHolder holder) {
+ long duration = mTimeOptions[holder.getPosition()].duration;
+ setupTimer(duration);
+ }
+
+ @Override
+ public void onTopEmptyRegionClick() {
+ }
+
+ private void registerWithAlarmManager(long duration) {
+ // Get the alarm manager.
+ AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
+
+ // Create intent that gets fired when timer expires.
+ Intent intent = new Intent(Constants.ACTION_SHOW_ALARM, null, this,
+ TimerNotificationService.class);
+ PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent,
+ PendingIntent.FLAG_UPDATE_CURRENT);
+
+ // Calculate the time when it expires.
+ long wakeupTime = System.currentTimeMillis() + duration;
+
+ // Schedule an alarm.
+ alarm.setExact(AlarmManager.RTC_WAKEUP, wakeupTime, pendingIntent);
+ }
+
+ /**
+ * Build a notification including different actions and other various setup and return it.
+ *
+ * @param duration the duration of the timer.
+ * @return the notification to display.
+ */
+
+ private Notification buildNotification(long duration) {
+ // Intent to restart a timer.
+ Intent restartIntent = new Intent(Constants.ACTION_RESTART_ALARM, null, this,
+ TimerNotificationService.class);
+ PendingIntent pendingIntentRestart = PendingIntent
+ .getService(this, 0, restartIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+
+ // Intent to delete a timer.
+ Intent deleteIntent = new Intent(Constants.ACTION_DELETE_ALARM, null, this,
+ TimerNotificationService.class);
+ PendingIntent pendingIntentDelete = PendingIntent
+ .getService(this, 0, deleteIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+
+ // Create countdown notification using a chronometer style.
+ return new Notification.Builder(this)
+ .setSmallIcon(R.drawable.ic_cc_alarm)
+ .setContentTitle(getString(R.string.timer_time_left))
+ .setContentText(TimerFormat.getTimeString(duration))
+ .setUsesChronometer(true)
+ .setWhen(System.currentTimeMillis() + duration)
+ .addAction(R.drawable.ic_cc_alarm, getString(R.string.timer_restart),
+ pendingIntentRestart)
+ .addAction(R.drawable.ic_cc_alarm, getString(R.string.timer_delete),
+ pendingIntentDelete)
+ .setDeleteIntent(pendingIntentDelete)
+ .setLocalOnly(true)
+ .build();
+ }
+
+ /**
+ * Cancels an old countdown and deletes the dataItem.
+ *
+ * @param notifyMgr the notification manager.
+ */
+ private void cancelCountdown(NotificationManager notifyMgr) {
+ notifyMgr.cancel(Constants.NOTIFICATION_TIMER_EXPIRED);
+ }
+
+ /** Model class for the listview. */
+ private static class ListViewItem {
+
+ // Duration in milliseconds.
+ long duration;
+ // Label to display.
+ private String label;
+
+ public ListViewItem(String label, long duration) {
+ this.label = label;
+ this.duration = duration;
+ }
+
+ @Override
+ public String toString() {
+ return label;
+ }
+ }
+
+ private final class TimerWearableListViewAdapter extends WearableListView.Adapter {
+ private final Context mContext;
+ private final LayoutInflater mInflater;
+
+ private TimerWearableListViewAdapter(Context context) {
+ mContext = context;
+ mInflater = LayoutInflater.from(context);
+ }
+
+ @Override
+ public WearableListView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ return new WearableListView.ViewHolder(
+ mInflater.inflate(R.layout.timer_list_item, null));
+ }
+
+ @Override
+ public void onBindViewHolder(WearableListView.ViewHolder holder, int position) {
+ TextView view = (TextView) holder.itemView.findViewById(R.id.time_text);
+ view.setText(mTimeOptions[position].label);
+ holder.itemView.setTag(position);
+ }
+
+ @Override
+ public int getItemCount() {
+ return NUMBER_OF_TIMES;
+ }
+ }
+
+}
diff --git a/wearable/wear/Timer/Wearable/src/main/java/com/example/android/timer/TimerNotificationService.java b/wearable/wear/Timer/Wearable/src/main/java/com/example/android/timer/TimerNotificationService.java
new file mode 100644
index 0000000..709b949
--- /dev/null
+++ b/wearable/wear/Timer/Wearable/src/main/java/com/example/android/timer/TimerNotificationService.java
@@ -0,0 +1,119 @@
+/*
+ * 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.android.timer;
+
+import android.app.AlarmManager;
+import android.app.IntentService;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+import com.example.android.timer.util.Constants;
+
+/**
+ * Service class that manages notifications of the timer.
+ */
+public class TimerNotificationService extends IntentService {
+
+ public static final String TAG = "TimerNotificationSvc";
+
+ public TimerNotificationService() {
+ super(TAG);
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ }
+
+ @Override
+ protected void onHandleIntent(Intent intent) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "onHandleIntent called with intent: " + intent);
+ }
+ String action = intent.getAction();
+ if (Constants.ACTION_SHOW_ALARM.equals(action)) {
+ showTimerDoneNotification();
+ } else if (Constants.ACTION_DELETE_ALARM.equals(action)) {
+ deleteTimer();
+ } else if (Constants.ACTION_RESTART_ALARM.equals(action)) {
+ restartAlarm();
+ } else {
+ throw new IllegalStateException("Undefined constant used: " + action);
+ }
+ }
+
+ private void restartAlarm() {
+ Intent dialogIntent = new Intent(this, SetTimerActivity.class);
+ dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(dialogIntent);
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Timer restarted.");
+ }
+ }
+
+ private void deleteTimer() {
+ cancelCountdownNotification();
+
+ AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
+ Intent intent = new Intent(Constants.ACTION_SHOW_ALARM, null, this,
+ TimerNotificationService.class);
+ PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent,
+ PendingIntent.FLAG_UPDATE_CURRENT);
+ alarm.cancel(pendingIntent);
+
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Timer deleted.");
+ }
+ }
+
+ private void cancelCountdownNotification() {
+ NotificationManager notifyMgr =
+ ((NotificationManager) getSystemService(NOTIFICATION_SERVICE));
+ notifyMgr.cancel(Constants.NOTIFICATION_TIMER_COUNTDOWN);
+ }
+
+ private void showTimerDoneNotification() {
+ // Cancel the countdown notification to show the "timer done" notification.
+ cancelCountdownNotification();
+
+ // Create an intent to restart a timer.
+ Intent restartIntent = new Intent(Constants.ACTION_RESTART_ALARM, null, this,
+ TimerNotificationService.class);
+ PendingIntent pendingIntentRestart = PendingIntent
+ .getService(this, 0, restartIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+
+ // Create notification that timer has expired.
+ NotificationManager notifyMgr =
+ ((NotificationManager) getSystemService(NOTIFICATION_SERVICE));
+ Notification notif = new Notification.Builder(this)
+ .setSmallIcon(R.drawable.ic_cc_alarm)
+ .setContentTitle(getString(R.string.timer_done))
+ .setContentText(getString(R.string.timer_done))
+ .setUsesChronometer(true)
+ .setWhen(System.currentTimeMillis())
+ .addAction(R.drawable.ic_cc_alarm, getString(R.string.timer_restart),
+ pendingIntentRestart)
+ .setLocalOnly(true)
+ .build();
+ notifyMgr.notify(Constants.NOTIFICATION_TIMER_EXPIRED, notif);
+ }
+
+}
diff --git a/wearable/wear/Timer/Wearable/src/main/java/com/example/android/timer/WearableListItemLayout.java b/wearable/wear/Timer/Wearable/src/main/java/com/example/android/timer/WearableListItemLayout.java
new file mode 100644
index 0000000..739213d
--- /dev/null
+++ b/wearable/wear/Timer/Wearable/src/main/java/com/example/android/timer/WearableListItemLayout.java
@@ -0,0 +1,90 @@
+/*
+ * 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.android.timer;
+
+import android.content.Context;
+import android.graphics.drawable.GradientDrawable;
+import android.support.wearable.view.WearableListView;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+public class WearableListItemLayout extends LinearLayout implements WearableListView.Item {
+ private final float mFadedTextAlpha;
+ private final int mFadedCircleColor;
+ private final int mChosenCircleColor;
+ private ImageView mCircle;
+ private float mScale;
+ private TextView mName;
+
+ public WearableListItemLayout(Context context) {
+ this(context, null);
+ }
+
+ public WearableListItemLayout(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public WearableListItemLayout(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ mFadedTextAlpha = getResources().getInteger(R.integer.action_text_faded_alpha) / 100f;
+ mFadedCircleColor = getResources().getColor(R.color.wl_gray);
+ mChosenCircleColor = getResources().getColor(R.color.wl_blue);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mCircle = (ImageView) findViewById(R.id.circle);
+ mName = (TextView) findViewById(R.id.time_text);
+ }
+
+ @Override
+ public float getProximityMinValue() {
+ return 1f;
+ }
+
+ @Override
+ public float getProximityMaxValue() {
+ return 1.6f;
+ }
+
+ @Override
+ public float getCurrentProximityValue() {
+ return mScale;
+ }
+
+ @Override
+ public void setScalingAnimatorValue(float scale) {
+ mScale = scale;
+ mCircle.setScaleX(scale);
+ mCircle.setScaleY(scale);
+ }
+
+ @Override
+ public void onScaleUpStart() {
+ mName.setAlpha(1f);
+ ((GradientDrawable) mCircle.getDrawable()).setColor(mChosenCircleColor);
+ }
+
+ @Override
+ public void onScaleDownStart() {
+ ((GradientDrawable) mCircle.getDrawable()).setColor(mFadedCircleColor);
+ mName.setAlpha(mFadedTextAlpha);
+ }
+}
diff --git a/wearable/wear/Timer/Wearable/src/main/java/com/example/android/timer/util/Constants.java b/wearable/wear/Timer/Wearable/src/main/java/com/example/android/timer/util/Constants.java
new file mode 100644
index 0000000..18254f1
--- /dev/null
+++ b/wearable/wear/Timer/Wearable/src/main/java/com/example/android/timer/util/Constants.java
@@ -0,0 +1,43 @@
+/*
+ * 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.android.timer.util;
+
+import android.net.Uri;
+
+/** Used to hold constants. */
+public final class Constants {
+
+ public static final String START_TIME = "timer_start_time";
+ public static final String ORIGINAL_TIME = "timer_original_time";
+ public static final String DATA_ITEM_PATH = "/timer";
+ public static final Uri URI_PATTERN_DATA_ITEMS =
+ Uri.fromParts("wear", DATA_ITEM_PATH, null);
+
+ public static final int NOTIFICATION_TIMER_COUNTDOWN = 1;
+ public static final int NOTIFICATION_TIMER_EXPIRED = 2;
+
+ public static final String ACTION_SHOW_ALARM
+ = "com.android.example.clockwork.timer.ACTION_SHOW";
+ public static final String ACTION_DELETE_ALARM
+ = "com.android.example.clockwork.timer.ACTION_DELETE";
+ public static final String ACTION_RESTART_ALARM
+ = "com.android.example.clockwork.timer.ACTION_RESTART";
+
+ private Constants() {
+ }
+
+}
diff --git a/wearable/wear/Timer/Wearable/src/main/java/com/example/android/timer/util/TimerFormat.java b/wearable/wear/Timer/Wearable/src/main/java/com/example/android/timer/util/TimerFormat.java
new file mode 100644
index 0000000..b1c1dab
--- /dev/null
+++ b/wearable/wear/Timer/Wearable/src/main/java/com/example/android/timer/util/TimerFormat.java
@@ -0,0 +1,121 @@
+/*
+ * 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.android.timer.util;
+
+/** Helper class to format the timer. Based on com.android.deskclock.timer.CountingTimerView. */
+public final class TimerFormat {
+
+ private static final String TWO_DIGITS = "%02d";
+
+ private static final String ONE_DIGIT = "%01d";
+
+ private static final String NEG_TWO_DIGITS = "-%02d";
+
+ private static final String NEG_ONE_DIGIT = "-%01d";
+
+ private static String mHours;
+
+ private static String mMinutes;
+
+ private static String mSeconds;
+
+ private TimerFormat() {
+
+ }
+
+ /**
+ * Update the time to display. Separates that time into the hours, minutes, seconds.
+ * Copied and shortened from com.android.deskclock.timer.CountingTimerView.
+ *
+ * @param time new time to display - in milliseconds
+ */
+ private static void setTime(long time) {
+ boolean neg = false;
+ boolean showNeg = false;
+ String format;
+ if (time < 0) {
+ time = -time;
+ neg = showNeg = true;
+ }
+ long seconds = time / 1000;
+ long hundreds = (time - seconds * 1000) / 10;
+ long minutes = seconds / 60;
+ seconds = seconds - minutes * 60;
+ long hours = minutes / 60;
+ minutes = minutes - hours * 60;
+ if (hours > 999) {
+ hours = 0;
+ }
+ // The time can be between 0 and -1 seconds, but the "truncated" equivalent time of hours
+ // and minutes and seconds could be zero, so since we do not show fractions of seconds
+ // when counting down, do not show the minus sign.
+ if (hours == 0 && minutes == 0 && seconds == 0) {
+ showNeg = false;
+ }
+
+ // Normalize and check if it is 'time' to invalidate
+ if (!neg && hundreds != 0) {
+ seconds++;
+ if (seconds == 60) {
+ seconds = 0;
+ minutes++;
+ if (minutes == 60) {
+ minutes = 0;
+ hours++;
+ }
+ }
+ }
+
+ // Hours may be empty
+ if (hours >= 10) {
+ format = showNeg ? NEG_TWO_DIGITS : TWO_DIGITS;
+ mHours = String.format(format, hours);
+ } else if (hours > 0) {
+ format = showNeg ? NEG_ONE_DIGIT : ONE_DIGIT;
+ mHours = String.format(format, hours);
+ } else {
+ mHours = null;
+ }
+
+ // Minutes are never empty and when hours are non-empty, must be two digits
+ if (minutes >= 10 || hours > 0) {
+ format = (showNeg && hours == 0) ? NEG_TWO_DIGITS : TWO_DIGITS;
+ mMinutes = String.format(format, minutes);
+ } else {
+ format = (showNeg && hours == 0) ? NEG_ONE_DIGIT : ONE_DIGIT;
+ mMinutes = String.format(format, minutes);
+ }
+
+ // Seconds are always two digits
+ mSeconds = String.format(TWO_DIGITS, seconds);
+ }
+
+ /**
+ * Based on com.android.deskclock.timer.CountingTimerView.
+ *
+ * @param time the time to format.
+ * @return nicely formatted time.
+ */
+ public static String getTimeString(long time) {
+ setTime(time);
+ if (mHours == null) {
+ return String.format("%s:%s", mMinutes, mSeconds);
+ }
+ return String.format("%s:%s:%s", mHours, mMinutes, mSeconds);
+
+ }
+}
diff --git a/wearable/wear/Timer/Wearable/src/main/java/com/example/android/timer/util/TimerObj.java b/wearable/wear/Timer/Wearable/src/main/java/com/example/android/timer/util/TimerObj.java
new file mode 100644
index 0000000..47f019f
--- /dev/null
+++ b/wearable/wear/Timer/Wearable/src/main/java/com/example/android/timer/util/TimerObj.java
@@ -0,0 +1,49 @@
+/*
+ * 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.android.timer.util;
+
+import android.os.SystemClock;
+
+/** This class represents a timer. */
+public class TimerObj {
+
+ // Start time in milliseconds.
+ public long startTime;
+
+ // Length of the timer in milliseconds.
+ public long originalLength;
+
+ /**
+ * Construct a timer with a specific start time and length.
+ *
+ * @param startTime the start time of the timer.
+ * @param timerLength the length of the timer.
+ */
+ public TimerObj(long startTime, long timerLength) {
+ this.startTime = startTime;
+ this.originalLength = timerLength;
+ }
+
+ /**
+ * Calculate the time left of this timer.
+ * @return the time left for this timer.
+ */
+ public long timeLeft() {
+ long millis = SystemClock.elapsedRealtime();
+ return originalLength - (millis - startTime);
+ }
+}
diff --git a/wearable/wear/Timer/Wearable/src/main/res/drawable/ic_cc_alarm.png b/wearable/wear/Timer/Wearable/src/main/res/drawable/ic_cc_alarm.png
new file mode 100644
index 0000000..ad51ddf
--- /dev/null
+++ b/wearable/wear/Timer/Wearable/src/main/res/drawable/ic_cc_alarm.png
Binary files differ
diff --git a/wearable/wear/Timer/Wearable/src/main/res/drawable/wl_circle.xml b/wearable/wear/Timer/Wearable/src/main/res/drawable/wl_circle.xml
new file mode 100644
index 0000000..a06c53a
--- /dev/null
+++ b/wearable/wear/Timer/Wearable/src/main/res/drawable/wl_circle.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval">
+ <solid android:color="@color/wl_gray"/>
+</shape>
diff --git a/wearable/wear/Timer/Wearable/src/main/res/layout/timer_list_item.xml b/wearable/wear/Timer/Wearable/src/main/res/layout/timer_list_item.xml
new file mode 100644
index 0000000..6cef07a
--- /dev/null
+++ b/wearable/wear/Timer/Wearable/src/main/res/layout/timer_list_item.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<com.example.android.wearable.timer.WearableListItemLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:gravity="center_vertical"
+ android:layout_width="match_parent"
+ android:layout_height="80dp">
+ <ImageView
+ android:id="@+id/circle"
+ android:layout_height="20dp"
+ android:layout_margin="16dp"
+ android:layout_width="20dp"
+ android:src="@drawable/wl_circle"/>
+ <TextView
+ android:id="@+id/time_text"
+ android:gravity="center_vertical|left"
+ android:layout_width="wrap_content"
+ android:layout_marginRight="16dp"
+ android:layout_height="match_parent"
+ android:fontFamily="sans-serif-condensed-light"
+ android:lineSpacingExtra="-4sp"
+ android:textColor="@color/text_color"
+ android:textSize="16sp"/>
+</com.example.android.wearable.timer.WearableListItemLayout>
\ No newline at end of file
diff --git a/wearable/wear/Timer/Wearable/src/main/res/layout/timer_set_timer.xml b/wearable/wear/Timer/Wearable/src/main/res/layout/timer_set_timer.xml
new file mode 100644
index 0000000..cdf9e77
--- /dev/null
+++ b/wearable/wear/Timer/Wearable/src/main/res/layout/timer_set_timer.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<android.support.wearable.view.WearableListView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/times_list_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scrollbars="none"
+ android:dividerHeight="0dp" />
\ No newline at end of file
diff --git a/wearable/wear/Timer/Wearable/src/main/res/mipmap-hdpi/ic_launcher.png b/wearable/wear/Timer/Wearable/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..56f7fc1
--- /dev/null
+++ b/wearable/wear/Timer/Wearable/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Timer/Wearable/src/main/res/mipmap-mdpi/ic_launcher.png b/wearable/wear/Timer/Wearable/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..dec99cd
--- /dev/null
+++ b/wearable/wear/Timer/Wearable/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Timer/Wearable/src/main/res/mipmap-xhdpi/ic_launcher.png b/wearable/wear/Timer/Wearable/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..48fa0ab
--- /dev/null
+++ b/wearable/wear/Timer/Wearable/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Timer/Wearable/src/main/res/mipmap-xxhdpi/ic_launcher.png b/wearable/wear/Timer/Wearable/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..8173921
--- /dev/null
+++ b/wearable/wear/Timer/Wearable/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Timer/Wearable/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/wearable/wear/Timer/Wearable/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..0dce809
--- /dev/null
+++ b/wearable/wear/Timer/Wearable/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/Timer/Wearable/src/main/res/values/colors.xml b/wearable/wear/Timer/Wearable/src/main/res/values/colors.xml
new file mode 100644
index 0000000..a8bb87b
--- /dev/null
+++ b/wearable/wear/Timer/Wearable/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <color name="wl_blue">#2878ff</color>
+ <color name="wl_gray">#c1c1c1</color>
+ <color name="text_color">#434343</color>
+</resources>
diff --git a/wearable/wear/Timer/Wearable/src/main/res/values/integers.xml b/wearable/wear/Timer/Wearable/src/main/res/values/integers.xml
new file mode 100644
index 0000000..c3bc252
--- /dev/null
+++ b/wearable/wear/Timer/Wearable/src/main/res/values/integers.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <integer name="action_text_faded_alpha">40</integer>
+</resources>
diff --git a/wearable/wear/Timer/Wearable/src/main/res/values/strings.xml b/wearable/wear/Timer/Wearable/src/main/res/values/strings.xml
new file mode 100644
index 0000000..f7e05bb
--- /dev/null
+++ b/wearable/wear/Timer/Wearable/src/main/res/values/strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+ <string name="app_name">Timer Example Wearable App</string>
+ <string name="timer_done">Timer done</string>
+ <string name="timer_time_left">Time remaining</string>
+ <string name="timer_delete">Delete</string>
+ <string name="timer_restart">Restart</string>
+ <plurals name="timer_minutes">
+ <item quantity="one">1 minute</item>
+ <item quantity="other">%d minutes</item>
+ </plurals>
+</resources>
diff --git a/wearable/wear/Timer/build.gradle b/wearable/wear/Timer/build.gradle
new file mode 100644
index 0000000..be1fa82
--- /dev/null
+++ b/wearable/wear/Timer/build.gradle
@@ -0,0 +1,14 @@
+
+
+
+
+// BEGIN_EXCLUDE
+import com.example.android.samples.build.SampleGenPlugin
+apply plugin: SampleGenPlugin
+
+samplegen {
+ pathToBuild "../../../../../build"
+ pathToSamplesCommon "../../../common"
+}
+apply from: "../../../../../build/build.gradle"
+// END_EXCLUDE
diff --git a/wearable/wear/Timer/buildSrc/build.gradle b/wearable/wear/Timer/buildSrc/build.gradle
new file mode 100644
index 0000000..e344a8c
--- /dev/null
+++ b/wearable/wear/Timer/buildSrc/build.gradle
@@ -0,0 +1,18 @@
+
+
+
+repositories {
+ mavenCentral()
+}
+dependencies {
+ compile 'org.freemarker:freemarker:2.3.20'
+}
+
+sourceSets {
+ main {
+ groovy {
+ srcDir new File(rootDir, "../../../../../../build/buildSrc/src/main/groovy")
+ }
+ }
+}
+
diff --git a/wearable/wear/Timer/gradle/wrapper/gradle-wrapper.jar b/wearable/wear/Timer/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8c0fb64
--- /dev/null
+++ b/wearable/wear/Timer/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/wearable/wear/Timer/gradle/wrapper/gradle-wrapper.properties b/wearable/wear/Timer/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..d7f03cf
--- /dev/null
+++ b/wearable/wear/Timer/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=http\://services.gradle.org/distributions/gradle-1.12-bin.zip
diff --git a/wearable/wear/Timer/gradlew b/wearable/wear/Timer/gradlew
new file mode 100755
index 0000000..91a7e26
--- /dev/null
+++ b/wearable/wear/Timer/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/wearable/wear/Timer/gradlew.bat b/wearable/wear/Timer/gradlew.bat
new file mode 100644
index 0000000..8a0b282
--- /dev/null
+++ b/wearable/wear/Timer/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/wearable/wear/Timer/settings.gradle b/wearable/wear/Timer/settings.gradle
new file mode 100644
index 0000000..8522c57
--- /dev/null
+++ b/wearable/wear/Timer/settings.gradle
@@ -0,0 +1 @@
+include ':Application', ':Wearable', ':Shared'
diff --git a/wearable/wear/Timer/template-params.xml b/wearable/wear/Timer/template-params.xml
new file mode 100644
index 0000000..7904724
--- /dev/null
+++ b/wearable/wear/Timer/template-params.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+
+
+<sample>
+ <name>Timer</name>
+ <group>Connectivity</group>
+ <package>com.example.android.timer</package>
+
+
+
+ <!-- change minSdk if needed-->
+ <minSdk>20</minSdk>
+
+
+ <strings>
+ <intro>
+ <![CDATA[
+ This simple wearable app allows the user to set a countdown timer. It runs
+ independently on the wearable with no phone connection.
+ ]]>
+ </intro>
+ </strings>
+
+ <template src="base"/>
+ <template src="Wear"/>
+ <common src="logger"/>
+ <common src="activities"/>
+
+</sample>
diff --git a/wearable/wear/WatchViewStub/Application/.gitignore b/wearable/wear/WatchViewStub/Application/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/WatchViewStub/Application/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/WatchViewStub/Application/proguard-project.txt b/wearable/wear/WatchViewStub/Application/proguard-project.txt
new file mode 100644
index 0000000..0d8f171
--- /dev/null
+++ b/wearable/wear/WatchViewStub/Application/proguard-project.txt
@@ -0,0 +1,20 @@
+ To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# 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/wearable/wear/WatchViewStub/Application/src/main/AndroidManifest.xml b/wearable/wear/WatchViewStub/Application/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..aa0d790
--- /dev/null
+++ b/wearable/wear/WatchViewStub/Application/src/main/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.watchviewstub">
+
+ <uses-sdk android:minSdkVersion="19"
+ android:targetSdkVersion="19" />
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name">
+ </application>
+
+</manifest>
+
diff --git a/wearable/wear/WatchViewStub/CONTRIB.md b/wearable/wear/WatchViewStub/CONTRIB.md
new file mode 100644
index 0000000..14a4fcf
--- /dev/null
+++ b/wearable/wear/WatchViewStub/CONTRIB.md
@@ -0,0 +1,35 @@
+# How to become a contributor and submit your own code
+
+## Contributor License Agreements
+
+We'd love to accept your sample apps and patches! Before we can take them, we
+have to jump a couple of legal hurdles.
+
+Please fill out either the individual or corporate Contributor License Agreement (CLA).
+
+ * If you are an individual writing original source code and you're sure you
+ own the intellectual property, then you'll need to sign an [individual CLA]
+ (https://developers.google.com/open-source/cla/individual).
+ * If you work for a company that wants to allow you to contribute your work,
+ then you'll need to sign a [corporate CLA]
+ (https://developers.google.com/open-source/cla/corporate).
+
+Follow either of the two links above to access the appropriate CLA and
+instructions for how to sign and return it. Once we receive it, we'll be able to
+accept your pull requests.
+
+## Contributing A Patch
+
+1. Submit an issue describing your proposed change to the repo in question.
+1. The repo owner will respond to your issue promptly.
+1. If your proposed change is accepted, and you haven't already done so, sign a
+ Contributor License Agreement (see details above).
+1. Fork the desired repo, develop and test your code changes.
+1. Ensure that your code adheres to the existing style in the sample to which
+ you are contributing. Refer to the
+ [Android Code Style Guide]
+ (https://source.android.com/source/code-style.html) for the
+ recommended coding standards for this organization.
+1. Ensure that your code has an appropriate set of unit tests which all pass.
+1. Submit a pull request.
+
diff --git a/wearable/wear/WatchViewStub/LICENSE b/wearable/wear/WatchViewStub/LICENSE
new file mode 100644
index 0000000..1af981f
--- /dev/null
+++ b/wearable/wear/WatchViewStub/LICENSE
@@ -0,0 +1,201 @@
+ 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 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/wearable/wear/WatchViewStub/README-wear.txt b/wearable/wear/WatchViewStub/README-wear.txt
new file mode 100644
index 0000000..17523d7
--- /dev/null
+++ b/wearable/wear/WatchViewStub/README-wear.txt
@@ -0,0 +1,30 @@
+<#--
+ Copyright 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.
+-->
+
+Steps to use Wear template on top of an existing sample:
+- In template-params.xml.ftl:
+ - Add the following template:
+ <template src="Wear"/>
+
+- Refresh your project (./gradlew refresh)
+- Add Wearable-specific code to Wearable directory
+- Add code to be shared among the main application and the wearable to Shared
+ directory
+
+Note that you still need the main application sample code. This is usually
+achieved by adding another template, like "base" for example.
+
+
diff --git a/wearable/wear/WatchViewStub/Shared/.gitignore b/wearable/wear/WatchViewStub/Shared/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/WatchViewStub/Shared/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/WatchViewStub/Shared/src/main/AndroidManifest.xml b/wearable/wear/WatchViewStub/Shared/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..846fa9d
--- /dev/null
+++ b/wearable/wear/WatchViewStub/Shared/src/main/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.watchviewstub.common">
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name">
+ </application>
+
+</manifest>
diff --git a/wearable/wear/WatchViewStub/Shared/src/main/res/values/strings.xml b/wearable/wear/WatchViewStub/Shared/src/main/res/values/strings.xml
new file mode 100644
index 0000000..0f2bb90
--- /dev/null
+++ b/wearable/wear/WatchViewStub/Shared/src/main/res/values/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+ <string name="app_name">Shared</string>
+</resources>
diff --git a/wearable/wear/WatchViewStub/Wearable/.gitignore b/wearable/wear/WatchViewStub/Wearable/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/wearable/wear/WatchViewStub/Wearable/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+src/template/
+src/common/
+build.gradle
diff --git a/wearable/wear/WatchViewStub/Wearable/src/main/AndroidManifest.xml b/wearable/wear/WatchViewStub/Wearable/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..5b33044
--- /dev/null
+++ b/wearable/wear/WatchViewStub/Wearable/src/main/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.watchviewstub" >
+
+ <uses-sdk android:minSdkVersion="20"
+ android:targetSdkVersion="20" />
+
+ <uses-feature android:name="android.hardware.type.watch" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@android:style/Theme.DeviceDefault">
+ <activity
+ android:name="com.example.android.watchviewstub.MainActivity"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/wearable/wear/WatchViewStub/Wearable/src/main/java/com/example/android/watchviewstub/MainActivity.java b/wearable/wear/WatchViewStub/Wearable/src/main/java/com/example/android/watchviewstub/MainActivity.java
new file mode 100644
index 0000000..1e931dc
--- /dev/null
+++ b/wearable/wear/WatchViewStub/Wearable/src/main/java/com/example/android/watchviewstub/MainActivity.java
@@ -0,0 +1,85 @@
+/*
+ * 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.android.watchviewstub;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.support.v4.view.GestureDetectorCompat;
+import android.support.wearable.view.DismissOverlayView;
+import android.support.wearable.view.WatchViewStub;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.ScaleAnimation;
+import android.widget.RelativeLayout;
+
+public class MainActivity extends Activity {
+ private RelativeLayout mRectBackground;
+ private RelativeLayout mRoundBackground;
+
+ private GestureDetectorCompat mGestureDetector;
+ private DismissOverlayView mDismissOverlayView;
+
+ @Override
+ public void onCreate(Bundle b) {
+ super.onCreate(b);
+ setContentView(R.layout.main_activity);
+
+ WatchViewStub stub = (WatchViewStub) findViewById(R.id.stub);
+ stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
+ @Override
+ public void onLayoutInflated(WatchViewStub stub) {
+ mRectBackground = (RelativeLayout) findViewById(R.id.rect_layout);
+ mRoundBackground = (RelativeLayout) findViewById(R.id.round_layout);
+ }
+ });
+
+ mDismissOverlayView = (DismissOverlayView) findViewById(R.id.dismiss_overlay);
+ mGestureDetector = new GestureDetectorCompat(this, new LongPressListener());
+ }
+
+ /**
+ * Animates the layout when clicked. The animation used depends on whether the
+ * device is round or rectangular.
+ */
+ public void onLayoutClicked(View view) {
+ if (mRectBackground != null) {
+ ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 0.7f, 1.0f, 0.7f,
+ Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
+ scaleAnimation.setDuration(300);
+ scaleAnimation.setRepeatCount(1);
+ scaleAnimation.setRepeatMode(Animation.REVERSE);
+ mRectBackground.startAnimation(scaleAnimation);
+ }
+ if (mRoundBackground != null) {
+ mRoundBackground.animate().rotationBy(360).setDuration(300).start();
+ }
+ }
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent event) {
+ return mGestureDetector.onTouchEvent(event) || super.dispatchTouchEvent(event);
+ }
+
+ private class LongPressListener extends GestureDetector.SimpleOnGestureListener {
+ @Override
+ public void onLongPress(MotionEvent event) {
+ mDismissOverlayView.show();
+ }
+ }
+}
diff --git a/wearable/wear/WatchViewStub/Wearable/src/main/res/drawable-hdpi/ic_launcher.png b/wearable/wear/WatchViewStub/Wearable/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100755
index 0000000..589f229
--- /dev/null
+++ b/wearable/wear/WatchViewStub/Wearable/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/WatchViewStub/Wearable/src/main/res/drawable-mdpi/ic_launcher.png b/wearable/wear/WatchViewStub/Wearable/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100755
index 0000000..77dd571
--- /dev/null
+++ b/wearable/wear/WatchViewStub/Wearable/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/WatchViewStub/Wearable/src/main/res/drawable-xhdpi/ic_launcher.png b/wearable/wear/WatchViewStub/Wearable/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100755
index 0000000..fe34ebe
--- /dev/null
+++ b/wearable/wear/WatchViewStub/Wearable/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/WatchViewStub/Wearable/src/main/res/drawable-xxhdpi/ic_launcher.png b/wearable/wear/WatchViewStub/Wearable/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100755
index 0000000..ab80bcd
--- /dev/null
+++ b/wearable/wear/WatchViewStub/Wearable/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/wearable/wear/WatchViewStub/Wearable/src/main/res/drawable/rect_background.xml b/wearable/wear/WatchViewStub/Wearable/src/main/res/drawable/rect_background.xml
new file mode 100644
index 0000000..eeda78f
--- /dev/null
+++ b/wearable/wear/WatchViewStub/Wearable/src/main/res/drawable/rect_background.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <corners android:radius="@dimen/rect_corner_radius"/>
+ <gradient android:startColor="@color/green"
+ android:endColor="@color/blue"
+ android:angle="45"/>
+</shape>
diff --git a/wearable/wear/WatchViewStub/Wearable/src/main/res/drawable/round_background.xml b/wearable/wear/WatchViewStub/Wearable/src/main/res/drawable/round_background.xml
new file mode 100644
index 0000000..432b0d2
--- /dev/null
+++ b/wearable/wear/WatchViewStub/Wearable/src/main/res/drawable/round_background.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="ring"
+ android:useLevel="false" >
+ <gradient android:startColor="@color/green"
+ android:endColor="@color/blue"/>
+</shape>
diff --git a/wearable/wear/WatchViewStub/Wearable/src/main/res/layout/main_activity.xml b/wearable/wear/WatchViewStub/Wearable/src/main/res/layout/main_activity.xml
new file mode 100644
index 0000000..e9745bc
--- /dev/null
+++ b/wearable/wear/WatchViewStub/Wearable/src/main/res/layout/main_activity.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <android.support.wearable.view.WatchViewStub
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/stub"
+ app:rectLayout="@layout/rect_layout"
+ app:roundLayout="@layout/round_layout"/>
+
+ <android.support.wearable.view.DismissOverlayView
+ android:id="@+id/dismiss_overlay"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+</FrameLayout>
+
diff --git a/wearable/wear/WatchViewStub/Wearable/src/main/res/layout/rect_layout.xml b/wearable/wear/WatchViewStub/Wearable/src/main/res/layout/rect_layout.xml
new file mode 100644
index 0000000..7b0006c
--- /dev/null
+++ b/wearable/wear/WatchViewStub/Wearable/src/main/res/layout/rect_layout.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/rect_layout"
+ android:background="@drawable/rect_background"
+ android:onClick="onLayoutClicked">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/rect_string"
+ android:textColor="@color/red"
+ android:textSize="@dimen/text_size"
+ android:gravity="center"
+ android:layout_centerInParent="true"/>
+</RelativeLayout>
diff --git a/wearable/wear/WatchViewStub/Wearable/src/main/res/layout/round_layout.xml b/wearable/wear/WatchViewStub/Wearable/src/main/res/layout/round_layout.xml
new file mode 100644
index 0000000..d7a55f6
--- /dev/null
+++ b/wearable/wear/WatchViewStub/Wearable/src/main/res/layout/round_layout.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/round_layout"
+ android:background="@drawable/round_background"
+ android:onClick="onLayoutClicked">
+ <TextView
+ android:layout_width="@dimen/round_text_view_width"
+ android:layout_height="wrap_content"
+ android:text="@string/round_string"
+ android:textColor="@color/red"
+ android:textSize="@dimen/text_size"
+ android:gravity="center"
+ android:layout_centerInParent="true"/>
+</RelativeLayout>
diff --git a/wearable/wear/WatchViewStub/Wearable/src/main/res/values/dimens.xml b/wearable/wear/WatchViewStub/Wearable/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..37148a2
--- /dev/null
+++ b/wearable/wear/WatchViewStub/Wearable/src/main/res/values/dimens.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+ <dimen name="rect_corner_radius">20dp</dimen>
+ <dimen name="round_text_view_width">150dp</dimen>
+ <dimen name="text_size">24sp</dimen>
+</resources>
diff --git a/wearable/wear/WatchViewStub/Wearable/src/main/res/values/strings.xml b/wearable/wear/WatchViewStub/Wearable/src/main/res/values/strings.xml
new file mode 100644
index 0000000..00cc6c6
--- /dev/null
+++ b/wearable/wear/WatchViewStub/Wearable/src/main/res/values/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+
+ <string name="app_name">WatchViewStub Sample</string>
+ <string name="round_string">Your screen is round!</string>
+ <string name="rect_string">Your screen is rectangular!</string>
+
+</resources>
diff --git a/wearable/wear/WatchViewStub/build.gradle b/wearable/wear/WatchViewStub/build.gradle
new file mode 100644
index 0000000..be1fa82
--- /dev/null
+++ b/wearable/wear/WatchViewStub/build.gradle
@@ -0,0 +1,14 @@
+
+
+
+
+// BEGIN_EXCLUDE
+import com.example.android.samples.build.SampleGenPlugin
+apply plugin: SampleGenPlugin
+
+samplegen {
+ pathToBuild "../../../../../build"
+ pathToSamplesCommon "../../../common"
+}
+apply from: "../../../../../build/build.gradle"
+// END_EXCLUDE
diff --git a/wearable/wear/WatchViewStub/buildSrc/build.gradle b/wearable/wear/WatchViewStub/buildSrc/build.gradle
new file mode 100644
index 0000000..e344a8c
--- /dev/null
+++ b/wearable/wear/WatchViewStub/buildSrc/build.gradle
@@ -0,0 +1,18 @@
+
+
+
+repositories {
+ mavenCentral()
+}
+dependencies {
+ compile 'org.freemarker:freemarker:2.3.20'
+}
+
+sourceSets {
+ main {
+ groovy {
+ srcDir new File(rootDir, "../../../../../../build/buildSrc/src/main/groovy")
+ }
+ }
+}
+
diff --git a/wearable/wear/WatchViewStub/gradle/wrapper/gradle-wrapper.jar b/wearable/wear/WatchViewStub/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8c0fb64
--- /dev/null
+++ b/wearable/wear/WatchViewStub/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/wearable/wear/WatchViewStub/gradle/wrapper/gradle-wrapper.properties b/wearable/wear/WatchViewStub/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..d7f03cf
--- /dev/null
+++ b/wearable/wear/WatchViewStub/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=http\://services.gradle.org/distributions/gradle-1.12-bin.zip
diff --git a/wearable/wear/WatchViewStub/gradlew b/wearable/wear/WatchViewStub/gradlew
new file mode 100755
index 0000000..91a7e26
--- /dev/null
+++ b/wearable/wear/WatchViewStub/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/wearable/wear/WatchViewStub/gradlew.bat b/wearable/wear/WatchViewStub/gradlew.bat
new file mode 100644
index 0000000..8a0b282
--- /dev/null
+++ b/wearable/wear/WatchViewStub/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/wearable/wear/WatchViewStub/settings.gradle b/wearable/wear/WatchViewStub/settings.gradle
new file mode 100644
index 0000000..8522c57
--- /dev/null
+++ b/wearable/wear/WatchViewStub/settings.gradle
@@ -0,0 +1 @@
+include ':Application', ':Wearable', ':Shared'
diff --git a/wearable/wear/WatchViewStub/template-params.xml b/wearable/wear/WatchViewStub/template-params.xml
new file mode 100644
index 0000000..ad2d2f6
--- /dev/null
+++ b/wearable/wear/WatchViewStub/template-params.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+
+
+<sample>
+ <name>WatchViewStub</name>
+ <group>Connectivity</group>
+ <package>com.example.android.watchviewstub</package>
+
+
+
+ <!-- change minSdk if needed-->
+ <minSdk>20</minSdk>
+
+
+ <strings>
+ <intro>
+ <![CDATA[
+ This sample demonstrates how to specify different layouts for round and rectangular screens.
+ ]]>
+ </intro>
+ </strings>
+
+ <template src="base"/>
+ <template src="Wear"/>
+ <common src="logger"/>
+ <common src="activities"/>
+
+</sample>