Add browseable samples for Clockwork Beryl
Bug: 17473824
Change-Id: Id4c637733c491ac71bb6e269f55939c082fb0994
diff --git a/samples/browseable/ElizaChat/Application/AndroidManifest.xml b/samples/browseable/ElizaChat/Application/AndroidManifest.xml
new file mode 100644
index 0000000..e653fa9
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/AndroidManifest.xml
@@ -0,0 +1,45 @@
+<?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.elizachat" >
+
+ <uses-sdk android:minSdkVersion="19"
+ android:targetSdkVersion="19" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@mipmap/ic_app_eliza"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <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>
+ <service
+ android:name=".ResponderService">
+ <intent-filter>
+ <action android:name="com.example.android.elizachat.REPLY" />
+ <action android:name="com.example.android.elizachat.CONVERSATION" />
+ </intent-filter>
+ </service>
+ </application>
+
+</manifest>
diff --git a/samples/browseable/ElizaChat/Application/res/drawable-hdpi/ic_full_reply.png b/samples/browseable/ElizaChat/Application/res/drawable-hdpi/ic_full_reply.png
new file mode 100644
index 0000000..66388d5
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/res/drawable-hdpi/ic_full_reply.png
Binary files differ
diff --git a/samples/browseable/ElizaChat/Application/res/drawable-hdpi/tile.9.png b/samples/browseable/ElizaChat/Application/res/drawable-hdpi/tile.9.png
new file mode 100644
index 0000000..1358628
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/res/drawable-hdpi/tile.9.png
Binary files differ
diff --git a/samples/browseable/ElizaChat/Application/res/drawable-mdpi/ic_full_reply.png b/samples/browseable/ElizaChat/Application/res/drawable-mdpi/ic_full_reply.png
new file mode 100644
index 0000000..60ce9f9
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/res/drawable-mdpi/ic_full_reply.png
Binary files differ
diff --git a/samples/browseable/ElizaChat/Application/res/drawable-nodpi/bg_eliza.png b/samples/browseable/ElizaChat/Application/res/drawable-nodpi/bg_eliza.png
new file mode 100644
index 0000000..3bbdf48
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/res/drawable-nodpi/bg_eliza.png
Binary files differ
diff --git a/samples/browseable/ElizaChat/Application/res/drawable-xhdpi/ic_full_reply.png b/samples/browseable/ElizaChat/Application/res/drawable-xhdpi/ic_full_reply.png
new file mode 100644
index 0000000..dba6fa7
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/res/drawable-xhdpi/ic_full_reply.png
Binary files differ
diff --git a/samples/browseable/ElizaChat/Application/res/layout/activity_main.xml b/samples/browseable/ElizaChat/Application/res/layout/activity_main.xml
new file mode 100755
index 0000000..be1aa49
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/res/layout/activity_main.xml
@@ -0,0 +1,36 @@
+<!--
+ 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.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <LinearLayout style="@style/Widget.SampleMessageTile"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <TextView style="@style/Widget.SampleMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="@dimen/horizontal_page_margin"
+ android:layout_marginRight="@dimen/horizontal_page_margin"
+ android:layout_marginTop="@dimen/vertical_page_margin"
+ android:layout_marginBottom="@dimen/vertical_page_margin"
+ android:text="@string/intro_message" />
+ </LinearLayout>
+</LinearLayout>
diff --git a/samples/browseable/ElizaChat/Application/res/layout/main.xml b/samples/browseable/ElizaChat/Application/res/layout/main.xml
new file mode 100644
index 0000000..6ffed8e
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/res/layout/main.xml
@@ -0,0 +1,17 @@
+<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:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ tools:context="com.example.android.wearable.elizachat.MainActivity$PlaceholderFragment"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/history"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+
+</ScrollView>
diff --git a/samples/browseable/ElizaChat/Application/res/menu/main.xml b/samples/browseable/ElizaChat/Application/res/menu/main.xml
new file mode 100644
index 0000000..b8e1ef2
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/res/menu/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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:id="@+id/action_stop_service"
+ android:orderInCategory="100"
+ android:showAsAction="always|withText"
+ android:title="@string/stop_service" />
+
+</menu>
diff --git a/samples/browseable/ElizaChat/Application/res/mipmap-hdpi/ic_app_eliza.png b/samples/browseable/ElizaChat/Application/res/mipmap-hdpi/ic_app_eliza.png
new file mode 100644
index 0000000..1bdb147
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/res/mipmap-hdpi/ic_app_eliza.png
Binary files differ
diff --git a/samples/browseable/ElizaChat/Application/res/mipmap-mdpi/ic_app_eliza.png b/samples/browseable/ElizaChat/Application/res/mipmap-mdpi/ic_app_eliza.png
new file mode 100644
index 0000000..2e0e198
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/res/mipmap-mdpi/ic_app_eliza.png
Binary files differ
diff --git a/samples/browseable/ElizaChat/Application/res/mipmap-xhdpi/ic_app_eliza.png b/samples/browseable/ElizaChat/Application/res/mipmap-xhdpi/ic_app_eliza.png
new file mode 100644
index 0000000..8d0f436
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/res/mipmap-xhdpi/ic_app_eliza.png
Binary files differ
diff --git a/samples/browseable/ElizaChat/Application/res/mipmap-xxhdpi/ic_app_eliza.png b/samples/browseable/ElizaChat/Application/res/mipmap-xxhdpi/ic_app_eliza.png
new file mode 100644
index 0000000..e72b967
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/res/mipmap-xxhdpi/ic_app_eliza.png
Binary files differ
diff --git a/samples/browseable/ElizaChat/Application/res/mipmap-xxxhdpi/ic_app_eliza.png b/samples/browseable/ElizaChat/Application/res/mipmap-xxxhdpi/ic_app_eliza.png
new file mode 100644
index 0000000..06ea079
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/res/mipmap-xxxhdpi/ic_app_eliza.png
Binary files differ
diff --git a/samples/browseable/ElizaChat/Application/res/values-sw600dp/template-dimens.xml b/samples/browseable/ElizaChat/Application/res/values-sw600dp/template-dimens.xml
new file mode 100644
index 0000000..22074a2
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/res/values-sw600dp/template-dimens.xml
@@ -0,0 +1,24 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_huge</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/ElizaChat/Application/res/values-sw600dp/template-styles.xml b/samples/browseable/ElizaChat/Application/res/values-sw600dp/template-styles.xml
new file mode 100644
index 0000000..03d1974
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/res/values-sw600dp/template-styles.xml
@@ -0,0 +1,25 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <style name="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceLarge</item>
+ <item name="android:lineSpacingMultiplier">1.2</item>
+ <item name="android:shadowDy">-6.5</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/ElizaChat/Application/res/values-v11/template-styles.xml b/samples/browseable/ElizaChat/Application/res/values-v11/template-styles.xml
new file mode 100644
index 0000000..8c1ea66
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/res/values-v11/template-styles.xml
@@ -0,0 +1,22 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/samples/browseable/ElizaChat/Application/res/values/base-strings.xml b/samples/browseable/ElizaChat/Application/res/values/base-strings.xml
new file mode 100644
index 0000000..be29a5b
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/res/values/base-strings.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<resources>
+ <string name="app_name">ElizaChat</string>
+ <string name="intro_message">
+ <![CDATA[
+
+
+ This sample is a phone application that provides a chat experience in which users can respond to
+ messages with a quick voice response. New messages create a notification with a "Reply" action.
+ The notification is bridged from phone to wearable, and selecting the "Reply" action on the
+ wearable opens the voice transcription UI allowing the user to speak a response.
+
+
+ ]]>
+ </string>
+</resources>
diff --git a/samples/browseable/ElizaChat/Application/res/values/dimens.xml b/samples/browseable/ElizaChat/Application/res/values/dimens.xml
new file mode 100644
index 0000000..a1e9cfe
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/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/samples/browseable/ElizaChat/Application/res/values/strings.xml b/samples/browseable/ElizaChat/Application/res/values/strings.xml
new file mode 100644
index 0000000..9a5c9d7
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/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="send_notification">Send notification!</string>
+ <string name="eliza">Eliza</string>
+ <string name="answer_eliza">Answer Eliza</string>
+ <string name="reply">Reply</string>
+ <string name="stop_service">End Chat Session</string>
+
+</resources>
diff --git a/samples/browseable/ElizaChat/Application/res/values/template-dimens.xml b/samples/browseable/ElizaChat/Application/res/values/template-dimens.xml
new file mode 100644
index 0000000..39e710b
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/res/values/template-dimens.xml
@@ -0,0 +1,32 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Define standard dimensions to comply with Holo-style grids and rhythm. -->
+
+ <dimen name="margin_tiny">4dp</dimen>
+ <dimen name="margin_small">8dp</dimen>
+ <dimen name="margin_medium">16dp</dimen>
+ <dimen name="margin_large">32dp</dimen>
+ <dimen name="margin_huge">64dp</dimen>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_medium</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/samples/browseable/ElizaChat/Application/res/values/template-styles.xml b/samples/browseable/ElizaChat/Application/res/values/template-styles.xml
new file mode 100644
index 0000000..6e7d593
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/res/values/template-styles.xml
@@ -0,0 +1,42 @@
+<!--
+ 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+
+ <style name="Theme.Base" parent="android:Theme.Light" />
+
+ <style name="Theme.Sample" parent="Theme.Base" />
+
+ <style name="AppTheme" parent="Theme.Sample" />
+ <!-- Widget styling -->
+
+ <style name="Widget" />
+
+ <style name="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceMedium</item>
+ <item name="android:lineSpacingMultiplier">1.1</item>
+ </style>
+
+ <style name="Widget.SampleMessageTile">
+ <item name="android:background">@drawable/tile</item>
+ <item name="android:shadowColor">#7F000000</item>
+ <item name="android:shadowDy">-3.5</item>
+ <item name="android:shadowRadius">2</item>
+ </style>
+
+</resources>
diff --git a/samples/browseable/ElizaChat/Application/src/com.example.android.common/activities/SampleActivityBase.java b/samples/browseable/ElizaChat/Application/src/com.example.android.common/activities/SampleActivityBase.java
new file mode 100644
index 0000000..3228927
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/src/com.example.android.common/activities/SampleActivityBase.java
@@ -0,0 +1,52 @@
+/*
+* 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.
+*/
+
+package com.example.android.common.activities;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+
+import com.example.android.common.logger.Log;
+import com.example.android.common.logger.LogWrapper;
+
+/**
+ * Base launcher activity, to handle most of the common plumbing for samples.
+ */
+public class SampleActivityBase extends FragmentActivity {
+
+ public static final String TAG = "SampleActivityBase";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ initializeLogging();
+ }
+
+ /** Set up targets to receive log data */
+ public void initializeLogging() {
+ // Using Log, front-end to the logging chain, emulates android.util.log method signatures.
+ // Wraps Android's native log framework
+ LogWrapper logWrapper = new LogWrapper();
+ Log.setLogNode(logWrapper);
+
+ Log.i(TAG, "Ready");
+ }
+}
diff --git a/samples/browseable/ElizaChat/Application/src/com.example.android.common/logger/Log.java b/samples/browseable/ElizaChat/Application/src/com.example.android.common/logger/Log.java
new file mode 100644
index 0000000..17503c5
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/src/com.example.android.common/logger/Log.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.android.common.logger;
+
+/**
+ * Helper class for a list (or tree) of LoggerNodes.
+ *
+ * <p>When this is set as the head of the list,
+ * an instance of it can function as a drop-in replacement for {@link android.util.Log}.
+ * Most of the methods in this class server only to map a method call in Log to its equivalent
+ * in LogNode.</p>
+ */
+public class Log {
+ // Grabbing the native values from Android's native logging facilities,
+ // to make for easy migration and interop.
+ public static final int NONE = -1;
+ public static final int VERBOSE = android.util.Log.VERBOSE;
+ public static final int DEBUG = android.util.Log.DEBUG;
+ public static final int INFO = android.util.Log.INFO;
+ public static final int WARN = android.util.Log.WARN;
+ public static final int ERROR = android.util.Log.ERROR;
+ public static final int ASSERT = android.util.Log.ASSERT;
+
+ // Stores the beginning of the LogNode topology.
+ private static LogNode mLogNode;
+
+ /**
+ * Returns the next LogNode in the linked list.
+ */
+ public static LogNode getLogNode() {
+ return mLogNode;
+ }
+
+ /**
+ * Sets the LogNode data will be sent to.
+ */
+ public static void setLogNode(LogNode node) {
+ mLogNode = node;
+ }
+
+ /**
+ * Instructs the LogNode to print the log data provided. Other LogNodes can
+ * be chained to the end of the LogNode as desired.
+ *
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void println(int priority, String tag, String msg, Throwable tr) {
+ if (mLogNode != null) {
+ mLogNode.println(priority, tag, msg, tr);
+ }
+ }
+
+ /**
+ * Instructs the LogNode to print the log data provided. Other LogNodes can
+ * be chained to the end of the LogNode as desired.
+ *
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ */
+ public static void println(int priority, String tag, String msg) {
+ println(priority, tag, msg, null);
+ }
+
+ /**
+ * Prints a message at VERBOSE priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void v(String tag, String msg, Throwable tr) {
+ println(VERBOSE, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at VERBOSE priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void v(String tag, String msg) {
+ v(tag, msg, null);
+ }
+
+
+ /**
+ * Prints a message at DEBUG priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void d(String tag, String msg, Throwable tr) {
+ println(DEBUG, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at DEBUG priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void d(String tag, String msg) {
+ d(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at INFO priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void i(String tag, String msg, Throwable tr) {
+ println(INFO, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at INFO priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void i(String tag, String msg) {
+ i(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at WARN priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void w(String tag, String msg, Throwable tr) {
+ println(WARN, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at WARN priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void w(String tag, String msg) {
+ w(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at WARN priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void w(String tag, Throwable tr) {
+ w(tag, null, tr);
+ }
+
+ /**
+ * Prints a message at ERROR priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void e(String tag, String msg, Throwable tr) {
+ println(ERROR, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at ERROR priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void e(String tag, String msg) {
+ e(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at ASSERT priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void wtf(String tag, String msg, Throwable tr) {
+ println(ASSERT, tag, msg, tr);
+ }
+
+ /**
+ * Prints a message at ASSERT priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged.
+ */
+ public static void wtf(String tag, String msg) {
+ wtf(tag, msg, null);
+ }
+
+ /**
+ * Prints a message at ASSERT priority.
+ *
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public static void wtf(String tag, Throwable tr) {
+ wtf(tag, null, tr);
+ }
+}
diff --git a/samples/browseable/ElizaChat/Application/src/com.example.android.common/logger/LogFragment.java b/samples/browseable/ElizaChat/Application/src/com.example.android.common/logger/LogFragment.java
new file mode 100644
index 0000000..b302acd
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/src/com.example.android.common/logger/LogFragment.java
@@ -0,0 +1,109 @@
+/*
+* 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.
+*/
+/*
+ * 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.
+ */
+
+package com.example.android.common.logger;
+
+import android.graphics.Typeface;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ScrollView;
+
+/**
+ * Simple fraggment which contains a LogView and uses is to output log data it receives
+ * through the LogNode interface.
+ */
+public class LogFragment extends Fragment {
+
+ private LogView mLogView;
+ private ScrollView mScrollView;
+
+ public LogFragment() {}
+
+ public View inflateViews() {
+ mScrollView = new ScrollView(getActivity());
+ ViewGroup.LayoutParams scrollParams = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT);
+ mScrollView.setLayoutParams(scrollParams);
+
+ mLogView = new LogView(getActivity());
+ ViewGroup.LayoutParams logParams = new ViewGroup.LayoutParams(scrollParams);
+ logParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+ mLogView.setLayoutParams(logParams);
+ mLogView.setClickable(true);
+ mLogView.setFocusable(true);
+ mLogView.setTypeface(Typeface.MONOSPACE);
+
+ // Want to set padding as 16 dips, setPadding takes pixels. Hooray math!
+ int paddingDips = 16;
+ double scale = getResources().getDisplayMetrics().density;
+ int paddingPixels = (int) ((paddingDips * (scale)) + .5);
+ mLogView.setPadding(paddingPixels, paddingPixels, paddingPixels, paddingPixels);
+ mLogView.setCompoundDrawablePadding(paddingPixels);
+
+ mLogView.setGravity(Gravity.BOTTOM);
+ mLogView.setTextAppearance(getActivity(), android.R.style.TextAppearance_Holo_Medium);
+
+ mScrollView.addView(mLogView);
+ return mScrollView;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+
+ View result = inflateViews();
+
+ mLogView.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {}
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ mScrollView.fullScroll(ScrollView.FOCUS_DOWN);
+ }
+ });
+ return result;
+ }
+
+ public LogView getLogView() {
+ return mLogView;
+ }
+}
\ No newline at end of file
diff --git a/samples/browseable/ElizaChat/Application/src/com.example.android.common/logger/LogNode.java b/samples/browseable/ElizaChat/Application/src/com.example.android.common/logger/LogNode.java
new file mode 100644
index 0000000..bc37cab
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/src/com.example.android.common/logger/LogNode.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.android.common.logger;
+
+/**
+ * Basic interface for a logging system that can output to one or more targets.
+ * Note that in addition to classes that will output these logs in some format,
+ * one can also implement this interface over a filter and insert that in the chain,
+ * such that no targets further down see certain data, or see manipulated forms of the data.
+ * You could, for instance, write a "ToHtmlLoggerNode" that just converted all the log data
+ * it received to HTML and sent it along to the next node in the chain, without printing it
+ * anywhere.
+ */
+public interface LogNode {
+
+ /**
+ * Instructs first LogNode in the list to print the log data provided.
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ public void println(int priority, String tag, String msg, Throwable tr);
+
+}
diff --git a/samples/browseable/ElizaChat/Application/src/com.example.android.common/logger/LogView.java b/samples/browseable/ElizaChat/Application/src/com.example.android.common/logger/LogView.java
new file mode 100644
index 0000000..c01542b
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/src/com.example.android.common/logger/LogView.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.android.common.logger;
+
+import android.app.Activity;
+import android.content.Context;
+import android.util.*;
+import android.widget.TextView;
+
+/** Simple TextView which is used to output log data received through the LogNode interface.
+*/
+public class LogView extends TextView implements LogNode {
+
+ public LogView(Context context) {
+ super(context);
+ }
+
+ public LogView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public LogView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ /**
+ * Formats the log data and prints it out to the LogView.
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ @Override
+ public void println(int priority, String tag, String msg, Throwable tr) {
+
+
+ String priorityStr = null;
+
+ // For the purposes of this View, we want to print the priority as readable text.
+ switch(priority) {
+ case android.util.Log.VERBOSE:
+ priorityStr = "VERBOSE";
+ break;
+ case android.util.Log.DEBUG:
+ priorityStr = "DEBUG";
+ break;
+ case android.util.Log.INFO:
+ priorityStr = "INFO";
+ break;
+ case android.util.Log.WARN:
+ priorityStr = "WARN";
+ break;
+ case android.util.Log.ERROR:
+ priorityStr = "ERROR";
+ break;
+ case android.util.Log.ASSERT:
+ priorityStr = "ASSERT";
+ break;
+ default:
+ break;
+ }
+
+ // Handily, the Log class has a facility for converting a stack trace into a usable string.
+ String exceptionStr = null;
+ if (tr != null) {
+ exceptionStr = android.util.Log.getStackTraceString(tr);
+ }
+
+ // Take the priority, tag, message, and exception, and concatenate as necessary
+ // into one usable line of text.
+ final StringBuilder outputBuilder = new StringBuilder();
+
+ String delimiter = "\t";
+ appendIfNotNull(outputBuilder, priorityStr, delimiter);
+ appendIfNotNull(outputBuilder, tag, delimiter);
+ appendIfNotNull(outputBuilder, msg, delimiter);
+ appendIfNotNull(outputBuilder, exceptionStr, delimiter);
+
+ // In case this was originally called from an AsyncTask or some other off-UI thread,
+ // make sure the update occurs within the UI thread.
+ ((Activity) getContext()).runOnUiThread( (new Thread(new Runnable() {
+ @Override
+ public void run() {
+ // Display the text we just generated within the LogView.
+ appendToLog(outputBuilder.toString());
+ }
+ })));
+
+ if (mNext != null) {
+ mNext.println(priority, tag, msg, tr);
+ }
+ }
+
+ public LogNode getNext() {
+ return mNext;
+ }
+
+ public void setNext(LogNode node) {
+ mNext = node;
+ }
+
+ /** Takes a string and adds to it, with a separator, if the bit to be added isn't null. Since
+ * the logger takes so many arguments that might be null, this method helps cut out some of the
+ * agonizing tedium of writing the same 3 lines over and over.
+ * @param source StringBuilder containing the text to append to.
+ * @param addStr The String to append
+ * @param delimiter The String to separate the source and appended strings. A tab or comma,
+ * for instance.
+ * @return The fully concatenated String as a StringBuilder
+ */
+ private StringBuilder appendIfNotNull(StringBuilder source, String addStr, String delimiter) {
+ if (addStr != null) {
+ if (addStr.length() == 0) {
+ delimiter = "";
+ }
+
+ return source.append(addStr).append(delimiter);
+ }
+ return source;
+ }
+
+ // The next LogNode in the chain.
+ LogNode mNext;
+
+ /** Outputs the string as a new line of log data in the LogView. */
+ public void appendToLog(String s) {
+ append("\n" + s);
+ }
+
+
+}
diff --git a/samples/browseable/ElizaChat/Application/src/com.example.android.common/logger/LogWrapper.java b/samples/browseable/ElizaChat/Application/src/com.example.android.common/logger/LogWrapper.java
new file mode 100644
index 0000000..16a9e7b
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/src/com.example.android.common/logger/LogWrapper.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.android.common.logger;
+
+import android.util.Log;
+
+/**
+ * Helper class which wraps Android's native Log utility in the Logger interface. This way
+ * normal DDMS output can be one of the many targets receiving and outputting logs simultaneously.
+ */
+public class LogWrapper implements LogNode {
+
+ // For piping: The next node to receive Log data after this one has done its work.
+ private LogNode mNext;
+
+ /**
+ * Returns the next LogNode in the linked list.
+ */
+ public LogNode getNext() {
+ return mNext;
+ }
+
+ /**
+ * Sets the LogNode data will be sent to..
+ */
+ public void setNext(LogNode node) {
+ mNext = node;
+ }
+
+ /**
+ * Prints data out to the console using Android's native log mechanism.
+ * @param priority Log level of the data being logged. Verbose, Error, etc.
+ * @param tag Tag for for the log data. Can be used to organize log statements.
+ * @param msg The actual message to be logged. The actual message to be logged.
+ * @param tr If an exception was thrown, this can be sent along for the logging facilities
+ * to extract and print useful information.
+ */
+ @Override
+ public void println(int priority, String tag, String msg, Throwable tr) {
+ // There actually are log methods that don't take a msg parameter. For now,
+ // if that's the case, just convert null to the empty string and move on.
+ String useMsg = msg;
+ if (useMsg == null) {
+ useMsg = "";
+ }
+
+ // If an exeption was provided, convert that exception to a usable string and attach
+ // it to the end of the msg method.
+ if (tr != null) {
+ msg += "\n" + Log.getStackTraceString(tr);
+ }
+
+ // This is functionally identical to Log.x(tag, useMsg);
+ // For instance, if priority were Log.VERBOSE, this would be the same as Log.v(tag, useMsg)
+ Log.println(priority, tag, useMsg);
+
+ // If this isn't the last node in the chain, move things along.
+ if (mNext != null) {
+ mNext.println(priority, tag, msg, tr);
+ }
+ }
+}
diff --git a/samples/browseable/ElizaChat/Application/src/com.example.android.common/logger/MessageOnlyLogFilter.java b/samples/browseable/ElizaChat/Application/src/com.example.android.common/logger/MessageOnlyLogFilter.java
new file mode 100644
index 0000000..19967dc
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/src/com.example.android.common/logger/MessageOnlyLogFilter.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.android.common.logger;
+
+/**
+ * Simple {@link LogNode} filter, removes everything except the message.
+ * Useful for situations like on-screen log output where you don't want a lot of metadata displayed,
+ * just easy-to-read message updates as they're happening.
+ */
+public class MessageOnlyLogFilter implements LogNode {
+
+ LogNode mNext;
+
+ /**
+ * Takes the "next" LogNode as a parameter, to simplify chaining.
+ *
+ * @param next The next LogNode in the pipeline.
+ */
+ public MessageOnlyLogFilter(LogNode next) {
+ mNext = next;
+ }
+
+ public MessageOnlyLogFilter() {
+ }
+
+ @Override
+ public void println(int priority, String tag, String msg, Throwable tr) {
+ if (mNext != null) {
+ getNext().println(Log.NONE, null, msg, null);
+ }
+ }
+
+ /**
+ * Returns the next LogNode in the chain.
+ */
+ public LogNode getNext() {
+ return mNext;
+ }
+
+ /**
+ * Sets the LogNode data will be sent to..
+ */
+ public void setNext(LogNode node) {
+ mNext = node;
+ }
+
+}
diff --git a/samples/browseable/ElizaChat/Application/src/com.example.android.elizachat/ElizaResponder.java b/samples/browseable/ElizaChat/Application/src/com.example.android.elizachat/ElizaResponder.java
new file mode 100644
index 0000000..e87f6de
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/src/com.example.android.elizachat/ElizaResponder.java
@@ -0,0 +1,168 @@
+/*
+ * 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.elizachat;
+
+import android.text.TextUtils;
+
+/**
+ * A basic chat bot based on ELIZA, one of the earliest programs to employ primitive natural
+ * language processing. Like ELIZA, this bot can simulate a Rogerian psychotherapist using a
+ * collection of vague and generic responses.
+ */
+public class ElizaResponder {
+
+ private static final String[] CONVERSATION_KEYWORDS = {
+ "CAN YOU", "CAN I", "YOU ARE", "YOURE", "I DONT", "I FEEL", "WHY DONT YOU", "WHY CANT I",
+ "ARE YOU", "I CANT", "I AM", " IM ", "YOU", "I WANT", "WHAT", "HOW", "WHO", "WHERE",
+ "WHEN", "WHY", "NAME", "CAUSE", "SORRY", "DREAM", "HELLO", "HI", "MAYBE", "NO", "YOUR",
+ "ALWAYS", "THINK", "ALIKE", "YES", "FRIEND", "COMPUTER", "NOKEYFOUND" };
+
+ private static String[] WORDS_TO_REPLACE = {"ARE","AM","WERE","WAS","YOU","I","YOUR","MY",
+ "IVE","YOUVE","IM","YOURE", "YOU", "ME"};
+
+ private static String[] QUESTIONS = {
+ "DON'T YOU BELIEVE THAT I CAN.", "PERHAPS YOU WOULD LIKE TO BE ABLE TO.",
+ "YOU WANT ME TO BE ABLE TO*", "PERHAPS YOU DON'T WANT TO*",
+ "DO YOU WANT TO BE ABLE TO*", "WHAT MAKES YOU THINK I AM*",
+ "DOES IT PLEASE YOU TO BELIEVE I AM*", "PERHAPS YOU WOULD LIKE TO BE*",
+ "DO YOU SOMETIMES WISH YOU WERE*", "DON'T YOU REALLY*", "WHY DON'T YOU*",
+ "DO YOU WISH TO BE ABLE TO*", "DOES THAT TROUBLE YOU?",
+ "TELL ME MORE ABOUT SUCH FEELINGS*", "DO YOU OFTEN FEEL*",
+ "DO YOU ENJOY FEELING*", "DO YOU REALLY BELIEVE I DON'T*",
+ "PERHAPS IN TIME I WILL*", "DO YOU WANT ME TO*",
+ "DO YOU THINK YOU SHOULD BE ABLE TO*", "WHY CAN'T YOU*",
+ "WHAT MAKES YOU WONDER WHETHER OR NOT I AM*",
+ "WOULD YOU PREFER IF I WERE NOT*", "PERHAPS IN YOUR FANTASIES I AM*",
+ "HOW DO YOU KNOW YOU CAN'T*", "HAVE YOU TRIED?", "PERHAPS YOU CAN NOW*",
+ "DID YOU COME TO ME BECAUSE YOU ARE*", "HOW LONG HAVE YOU BEEN*",
+ "DO YOU BELIEVE IT IS NORMAL TO BE*", "DO YOU ENJOY BEING*",
+ "I AM MORE INTERESTED IN TALKING ABOUT YOU.", "OH, I*",
+ "ARE YOU REALLY SO INTERESTED IN SOMEONE LIKE ME?",
+ "WHAT WOULD IT MEAN TO YOU IF YOU GOT*", "WHY DO YOU WANT*",
+ "SUPPOSE YOU SOON GOT*", "WHAT IF YOU NEVER GOT*", "I SOMETIMES ALSO WANT*",
+ "WHY DO YOU ASK?", "DOES THAT QUESTION INTEREST YOU?",
+ "WHAT ANSWER WOULD PLEASE YOU THE MOST?", "WHAT DO YOU THINK?",
+ "ARE SUCH QUESTIONS ON YOUR MIND OFTEN?",
+ "WHAT IS IT THAT YOU REALLY WANT TO KNOW?", "HAVE YOU ASKED ANYONE ELSE?",
+ "HAVE YOU ASKED SUCH QUESTIONS BEFORE?",
+ "WHAT ELSE COMES TO MIND WHEN YOU ASK THAT?", "WE CAN KEEP THIS ANONYMOUS.",
+ "NO NEED TO SPECIFY ANY NAMES-- PLEASE GO ON.", "IS THAT THE REAL REASON?",
+ "DON'T ANY OTHER REASONS COME TO MIND?",
+ "DOES THAT REASON EXPLAIN ANYTHING ELSE?", "WHAT OTHER REASONS MIGHT THERE BE?",
+ "PLEASE DON'T APOLOGIZE.", "APOLOGIES ARE NOT NECESSARY.",
+ "WHAT FEELINGS DO YOU HAVE WHEN YOU APOLOGIZE?", "NO NEED TO BE DEFENSIVE!",
+ "WHAT DOES THAT DREAM SUGGEST TO YOU?", "DO YOU DREAM OFTEN?",
+ "WHAT PERSONS APPEAR IN YOUR DREAMS?", "DO YOU HAVE PLEASANT DREAMS?",
+ "HOW DO YOU DO ... PLEASE STATE YOUR PROBLEM.", "YOU DON'T SEEM QUITE CERTAIN.",
+ "WHY THE UNCERTAIN TONE?", "LET'S TRY TO KEEP THIS POSITIVE.", "YOU AREN'T SURE?",
+ "DON'T YOU KNOW?", "IS THAT A DEFINITE NO OR MIGHT YOU CHANGE YOUR MIND?",
+ "I AM SENSING SOME NEGATIVITY.", "WHY NOT?", "ARE YOU SURE?", "WHY NO?",
+ "WHY ARE YOU CONCERNED ABOUT MY*", "WHAT ABOUT YOUR OWN*",
+ "CAN'T YOU THINK OF A SPECIFIC EXAMPLE?", "WHEN?", "WHAT ARE YOU THINKING OF?",
+ "REALLY. ALWAYS?", "DO YOU REALLY THINK SO?", "BUT YOU ARE NOT SURE YOU.",
+ "BELIEVE IN YOURSELF.", "IN WHAT WAY?", "WHAT RESEMBLANCE DO YOU SEE?",
+ "WHAT DOES THE SIMILARITY SUGGEST TO YOU?",
+ "WHAT OTHER CONNECTIONS DO YOU SEE?", "COULD THERE REALLY BE SOME CONNECTION?",
+ "HOW?", "YOU SEEM QUITE POSITIVE.", "ARE YOU SURE?", "I SEE.", "I UNDERSTAND.",
+ "TELL ME ABOUT YOUR FRIENDS.", "ARE YOU WORRIED ABOUT YOUR FRIENDS?",
+ "DO YOUR FRIENDS EVER GIVE YOU A HARD TIME?", "WHAT DO YOU LIKE ABOUT YOUR FRIENDS?",
+ "DO YOU LOVE YOUR FRIENDS?", "PERHAPS YOUR LOVE FOR FRIENDS WORRIES YOU.",
+ "DO COMPUTERS EXCITE YOU?", "ARE YOU TALKING ABOUT ME IN PARTICULAR?",
+ "HOW DO YOU LIKE YOUR WATCH?", "WHY DO YOU MENTION COMPUTERS?",
+ "DO YOU FIND MACHINES AS FASCINATING AS I DO?",
+ "DON'T YOU THINK COMPUTERS CAN HELP PEOPLE?",
+ "WHAT ABOUT MACHINES EXCITES YOU THE MOST?",
+ "HEY THERE, HOW CAN I HELP YOU?",
+ "WHAT DOES THAT SUGGEST TO YOU?", "I SEE.",
+ "I'M NOT SURE I UNDERSTAND YOU FULLY.", "COME COME ELUCIDATE YOUR THOUGHTS.",
+ "CAN YOU ELABORATE ON THAT?", "THAT IS QUITE INTERESTING."};
+
+ private static char[] CONVERSATION_TO_RESPONSES_MAP = {
+ 1,3,4,2,6,4,6,4,10,4,14,3,17,3,20,2,22,3,25,3,
+ 28,4,28,4,32,3,35,5,40,9,40,9,40,9,40,9,40,9,40,9,
+ 49,2,51,4,55,4,59,4,63,1,63,1,64,5,69,5,74,2,76,4,
+ 80,3,83,7,90,3,93,6,99,7,106,6};
+
+ private int[] responseStarts = new int[36];
+ private int[] responseCurrentIndices = new int[36];
+ private int[] responseEnds = new int[36];
+ private String previousInput = null;
+
+ public ElizaResponder() {
+ for (int i = 0; i < CONVERSATION_TO_RESPONSES_MAP.length / 2; i++) {
+ responseStarts[i] = CONVERSATION_TO_RESPONSES_MAP[2 * i];
+ responseCurrentIndices[i] = CONVERSATION_TO_RESPONSES_MAP[2 * i];
+ responseEnds[i] = responseStarts[i] + CONVERSATION_TO_RESPONSES_MAP[2 * i + 1];
+ }
+ }
+
+ public String elzTalk(String input) {
+ if (null == input) {
+ input = "";
+ }
+ String result = "";
+
+ input = " " + input.toUpperCase().replace("\'", "") + " ";
+
+ if (previousInput != null && input.equals(previousInput)) {
+ return "DIDN'T YOU JUST SAY THAT?\n";
+ }
+ previousInput = input;
+
+ int keywordIndex = 0;
+ for (; keywordIndex < CONVERSATION_KEYWORDS.length; ++keywordIndex) {
+ int index = input.indexOf(CONVERSATION_KEYWORDS[keywordIndex]);
+ if (index != -1) {
+ break;
+ }
+ }
+
+ String afterKeyword = "";
+ if (keywordIndex == CONVERSATION_KEYWORDS.length) {
+ keywordIndex = 35;
+ } else {
+ int index = input.indexOf(CONVERSATION_KEYWORDS[keywordIndex]);
+ afterKeyword = input.substring(index + CONVERSATION_KEYWORDS[keywordIndex].length());
+ String[] parts = afterKeyword.split("\\s+");
+ for (int i = 0; i < WORDS_TO_REPLACE.length / 2; i++) {
+ String first = WORDS_TO_REPLACE[i * 2];
+ String second = WORDS_TO_REPLACE[i * 2 + 1];
+ for (int j = 0; j < parts.length; ++j) {
+ if (parts[j].equals(first)) {
+ parts[j] = second;
+ } else if (parts[j].equals(second)) {
+ parts[j] = first;
+ }
+ }
+ }
+ afterKeyword = TextUtils.join(" ", parts);
+ }
+
+ String question = QUESTIONS[responseCurrentIndices[keywordIndex] - 1];
+ responseCurrentIndices[keywordIndex] = responseCurrentIndices[keywordIndex] + 1;
+ if (responseCurrentIndices[keywordIndex] > responseEnds[keywordIndex]) {
+ responseCurrentIndices[keywordIndex] = responseStarts[keywordIndex];
+ }
+ result += question;
+ if (result.endsWith("*")) {
+ result = result.substring(0, result.length() - 1);
+ result += " " + afterKeyword;
+ }
+
+ return result;
+ }
+}
diff --git a/samples/browseable/ElizaChat/Application/src/com.example.android.elizachat/MainActivity.java b/samples/browseable/ElizaChat/Application/src/com.example.android.elizachat/MainActivity.java
new file mode 100644
index 0000000..421dcb8
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/src/com.example.android.elizachat/MainActivity.java
@@ -0,0 +1,107 @@
+/*
+ * 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.elizachat;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.support.v4.content.LocalBroadcastManager;
+import android.text.TextUtils;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.TextView;
+
+public class MainActivity extends Activity {
+
+ @SuppressWarnings("unused")
+ private static final String TAG = "MainActivity";
+
+ public static final String EXTRA_MESSAGE = "message";
+
+ public static final String ACTION_NOTIFY = "com.example.android.elizachat.NOTIFY";
+
+ public static final String ACTION_GET_CONVERSATION
+ = "com.example.android.elizachat.CONVERSATION";
+
+ private BroadcastReceiver mReceiver;
+
+ private TextView mHistoryView;
+
+ @Override
+ protected void onCreate(Bundle saved) {
+ super.onCreate(saved);
+ setContentView(R.layout.main);
+ mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ processMessage(intent);
+ }
+ };
+ mHistoryView = (TextView) findViewById(R.id.history);
+ startResponderService();
+ }
+
+ private void startResponderService() {
+ Intent serviceIntent = new Intent(ResponderService.ACTION_INCOMING);
+ startService(serviceIntent);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver,
+ new IntentFilter(ACTION_NOTIFY));
+ mHistoryView.setText("");
+ Intent serviceIntent = new Intent(ACTION_GET_CONVERSATION);
+ startService(serviceIntent);
+
+ }
+
+ @Override
+ protected void onPause() {
+ LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
+ super.onPause();
+ }
+
+ private void processMessage(Intent intent) {
+ String text = intent.getStringExtra(EXTRA_MESSAGE);
+ if (!TextUtils.isEmpty(text)) {
+ mHistoryView.append("\n" + text);
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ getMenuInflater().inflate(R.menu.main, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.action_stop_service:
+ stopService(new Intent(this, ResponderService.class));
+ finish();
+ break;
+ }
+ return true;
+ }
+}
diff --git a/samples/browseable/ElizaChat/Application/src/com.example.android.elizachat/ResponderService.java b/samples/browseable/ElizaChat/Application/src/com.example.android.elizachat/ResponderService.java
new file mode 100644
index 0000000..6d6cd9a
--- /dev/null
+++ b/samples/browseable/ElizaChat/Application/src/com.example.android.elizachat/ResponderService.java
@@ -0,0 +1,148 @@
+/*
+ * 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.elizachat;
+
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Intent;
+import android.graphics.BitmapFactory;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.support.v4.app.NotificationCompat;
+import android.support.v4.app.RemoteInput;
+import android.support.v4.content.LocalBroadcastManager;
+import android.support.v4.app.NotificationManagerCompat;
+import android.text.TextUtils;
+import android.util.Log;
+
+/**
+ * A service that runs in the background and provides responses to the incoming messages from the
+ * wearable. It also keeps a record of the chat session history, which it can provide upon request.
+ */
+public class ResponderService extends Service {
+
+ public static final String ACTION_INCOMING = "com.example.android.elizachat.INCOMING";
+
+ public static final String ACTION_RESPONSE = "com.example.android.elizachat.REPLY";
+
+ public static final String EXTRA_REPLY = "reply";
+
+ private static final String TAG = "ResponderService";
+
+ private ElizaResponder mResponder;
+
+ private String mLastResponse = null;
+
+ private StringBuffer mCompleteConversation = new StringBuffer();
+
+ private LocalBroadcastManager mBroadcastManager;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Chat Service started");
+ }
+ mResponder = new ElizaResponder();
+ mBroadcastManager = LocalBroadcastManager.getInstance(this);
+ processIncoming(null);
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ if (null == intent || null == intent.getAction()) {
+ return Service.START_STICKY;
+ }
+ String action = intent.getAction();
+ if (action.equals(ACTION_RESPONSE)) {
+ Bundle remoteInputResults = RemoteInput.getResultsFromIntent(intent);
+ CharSequence replyMessage = "";
+ if (remoteInputResults != null) {
+ replyMessage = remoteInputResults.getCharSequence(EXTRA_REPLY);
+ }
+ processIncoming(replyMessage.toString());
+ } else if (action.equals(MainActivity.ACTION_GET_CONVERSATION)) {
+ broadcastMessage(mCompleteConversation.toString());
+ }
+ return Service.START_STICKY;
+ }
+
+ private void showNotification() {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Sent: " + mLastResponse);
+ }
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
+ .setContentTitle(getString(R.string.eliza))
+ .setContentText(mLastResponse)
+ .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.bg_eliza))
+ .setSmallIcon(R.drawable.bg_eliza)
+ .setPriority(NotificationCompat.PRIORITY_MIN);
+
+ Intent intent = new Intent(ACTION_RESPONSE);
+ PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent,
+ PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_CANCEL_CURRENT);
+ Notification notification = builder
+ .extend(new NotificationCompat.WearableExtender()
+ .addAction(new NotificationCompat.Action.Builder(
+ R.drawable.ic_full_reply, getString(R.string.reply), pendingIntent)
+ .addRemoteInput(new RemoteInput.Builder(EXTRA_REPLY)
+ .setLabel(getString(R.string.reply))
+ .build())
+ .build()))
+ .build();
+ NotificationManagerCompat.from(this).notify(0, notification);
+ }
+
+ private void processIncoming(String text) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Received: " + text);
+ }
+ mLastResponse = mResponder.elzTalk(text);
+ String line = TextUtils.isEmpty(text) ? mLastResponse : text + "\n" + mLastResponse;
+
+ // Send a new line of conversation to update the Activity, unless the incoming text was
+ // empty.
+ if (!TextUtils.isEmpty(text)) {
+ broadcastMessage(line);
+ }
+ NotificationManagerCompat.from(this).cancelAll();
+ showNotification();
+ mCompleteConversation.append("\n" + line);
+ }
+
+ private void broadcastMessage(String message) {
+ Intent intent = new Intent(MainActivity.ACTION_NOTIFY);
+ intent.putExtra(MainActivity.EXTRA_MESSAGE, message);
+ mBroadcastManager.sendBroadcast(intent);
+ }
+
+ @Override
+ public void onDestroy() {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Chat Service stopped");
+ }
+ NotificationManagerCompat.from(this).cancel(0);
+ mBroadcastManager = null;
+ super.onDestroy();
+ }
+}
diff --git a/samples/browseable/ElizaChat/Shared/AndroidManifest.xml b/samples/browseable/ElizaChat/Shared/AndroidManifest.xml
new file mode 100644
index 0000000..9c02d59
--- /dev/null
+++ b/samples/browseable/ElizaChat/Shared/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.elizachat.common">
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name">
+ </application>
+
+</manifest>
diff --git a/samples/browseable/ElizaChat/Shared/res/values/strings.xml b/samples/browseable/ElizaChat/Shared/res/values/strings.xml
new file mode 100644
index 0000000..0f2bb90
--- /dev/null
+++ b/samples/browseable/ElizaChat/Shared/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/samples/browseable/ElizaChat/_index.jd b/samples/browseable/ElizaChat/_index.jd
new file mode 100644
index 0000000..a88371c
--- /dev/null
+++ b/samples/browseable/ElizaChat/_index.jd
@@ -0,0 +1,12 @@
+page.tags="ElizaChat"
+sample.group=Wearable
+@jd:body
+
+<p>
+
+ This sample is a phone application that provides a chat experience in which users can respond to
+ messages with a quick voice response. New messages create a notification with a "Reply" action.
+ The notification is bridged from phone to wearable, and selecting the "Reply" action on the
+ wearable opens the voice transcription UI allowing the user to speak a response.
+
+ </p>