diff options
Diffstat (limited to 'samples/browseable/WearNotifications/Application')
61 files changed, 2813 insertions, 0 deletions
diff --git a/samples/browseable/WearNotifications/Application/AndroidManifest.xml b/samples/browseable/WearNotifications/Application/AndroidManifest.xml new file mode 100644 index 000000000..20c44cc12 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/AndroidManifest.xml @@ -0,0 +1,83 @@ +<?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.wearable.wear.wearnotifications" + android:versionCode="1" + android:versionName="1.0"> + + <application + android:allowBackup="true" + android:icon="@drawable/ic_launcher" + android:label="@string/app_name" + android:supportsRtl="true" + android:theme="@style/AppThemeOverride"> + + <activity android:name=".MainActivity"> + <intent-filter> + <action android:name="android.intent.action.MAIN"/> + <category android:name="android.intent.category.LAUNCHER"/> + </intent-filter> + </activity> + + <activity + android:name=".handlers.BigTextMainActivity" + android:excludeFromRecents="true" + android:label="@string/title_activity_big_text_main" + android:taskAffinity=""> + </activity> + + <activity + android:name=".handlers.BigPictureSocialMainActivity" + android:label="@string/title_activity_big_picture_main"> + <meta-data + android:name="android.support.PARENT_ACTIVITY" + android:value=".MainActivity"/> + </activity> + + + <activity + android:name=".handlers.InboxMainActivity" + android:label="@string/title_activity_inbox_main"> + <meta-data + android:name="android.support.PARENT_ACTIVITY" + android:value=".MainActivity"/> + </activity> + + <activity + android:name=".handlers.MessagingMainActivity" + android:label="@string/title_activity_messaging_main"> + <meta-data + android:name="android.support.PARENT_ACTIVITY" + android:value=".MainActivity"/> + </activity> + + <service + android:name=".handlers.BigTextIntentService" + android:exported="false"> + </service> + + <service + android:name=".handlers.MessagingIntentService" + android:exported="false"> + </service> + + <service + android:name=".handlers.BigPictureSocialIntentService" + android:exported="false"> + </service> + </application> +</manifest>
\ No newline at end of file diff --git a/samples/browseable/WearNotifications/Application/res/drawable-hdpi/earth.png b/samples/browseable/WearNotifications/Application/res/drawable-hdpi/earth.png Binary files differnew file mode 100644 index 000000000..13abd77a5 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-hdpi/earth.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-hdpi/ic_alarm_white_48dp.png b/samples/browseable/WearNotifications/Application/res/drawable-hdpi/ic_alarm_white_48dp.png Binary files differnew file mode 100644 index 000000000..75e5a46ee --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-hdpi/ic_alarm_white_48dp.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-hdpi/ic_cancel_white_48dp.png b/samples/browseable/WearNotifications/Application/res/drawable-hdpi/ic_cancel_white_48dp.png Binary files differnew file mode 100644 index 000000000..dc32a14f9 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-hdpi/ic_cancel_white_48dp.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-hdpi/ic_launcher.png b/samples/browseable/WearNotifications/Application/res/drawable-hdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..0ed1b5fbf --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-hdpi/ic_launcher.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-hdpi/ic_message_black_18dp.png b/samples/browseable/WearNotifications/Application/res/drawable-hdpi/ic_message_black_18dp.png Binary files differnew file mode 100644 index 000000000..d921ba2da --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-hdpi/ic_message_black_18dp.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-hdpi/ic_person_black_48dp.png b/samples/browseable/WearNotifications/Application/res/drawable-hdpi/ic_person_black_48dp.png Binary files differnew file mode 100644 index 000000000..f1e148490 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-hdpi/ic_person_black_48dp.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-hdpi/ic_reply_white_18dp.png b/samples/browseable/WearNotifications/Application/res/drawable-hdpi/ic_reply_white_18dp.png Binary files differnew file mode 100644 index 000000000..cc732baab --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-hdpi/ic_reply_white_18dp.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-hdpi/tile.9.png b/samples/browseable/WearNotifications/Application/res/drawable-hdpi/tile.9.png Binary files differnew file mode 100644 index 000000000..135862883 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-hdpi/tile.9.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-mdpi/ic_alarm_white_48dp.png b/samples/browseable/WearNotifications/Application/res/drawable-mdpi/ic_alarm_white_48dp.png Binary files differnew file mode 100644 index 000000000..280e09df3 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-mdpi/ic_alarm_white_48dp.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-mdpi/ic_cancel_white_48dp.png b/samples/browseable/WearNotifications/Application/res/drawable-mdpi/ic_cancel_white_48dp.png Binary files differnew file mode 100644 index 000000000..6ebbc8316 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-mdpi/ic_cancel_white_48dp.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-mdpi/ic_launcher.png b/samples/browseable/WearNotifications/Application/res/drawable-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..2b6948acb --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-mdpi/ic_launcher.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-mdpi/ic_message_black_18dp.png b/samples/browseable/WearNotifications/Application/res/drawable-mdpi/ic_message_black_18dp.png Binary files differnew file mode 100644 index 000000000..2156f1673 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-mdpi/ic_message_black_18dp.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-mdpi/ic_person_black_48dp.png b/samples/browseable/WearNotifications/Application/res/drawable-mdpi/ic_person_black_48dp.png Binary files differnew file mode 100644 index 000000000..360a32f27 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-mdpi/ic_person_black_48dp.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-mdpi/ic_reply_white_18dp.png b/samples/browseable/WearNotifications/Application/res/drawable-mdpi/ic_reply_white_18dp.png Binary files differnew file mode 100644 index 000000000..b336e2f4d --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-mdpi/ic_reply_white_18dp.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-xhdpi/ic_alarm_white_48dp.png b/samples/browseable/WearNotifications/Application/res/drawable-xhdpi/ic_alarm_white_48dp.png Binary files differnew file mode 100644 index 000000000..aa8102fd2 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-xhdpi/ic_alarm_white_48dp.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-xhdpi/ic_cancel_white_48dp.png b/samples/browseable/WearNotifications/Application/res/drawable-xhdpi/ic_cancel_white_48dp.png Binary files differnew file mode 100644 index 000000000..dc775b243 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-xhdpi/ic_cancel_white_48dp.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-xhdpi/ic_launcher.png b/samples/browseable/WearNotifications/Application/res/drawable-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..d9b134890 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-xhdpi/ic_launcher.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-xhdpi/ic_message_black_18dp.png b/samples/browseable/WearNotifications/Application/res/drawable-xhdpi/ic_message_black_18dp.png Binary files differnew file mode 100644 index 000000000..185d6136e --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-xhdpi/ic_message_black_18dp.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-xhdpi/ic_person_black_48dp.png b/samples/browseable/WearNotifications/Application/res/drawable-xhdpi/ic_person_black_48dp.png Binary files differnew file mode 100644 index 000000000..1ebc37be1 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-xhdpi/ic_person_black_48dp.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-xhdpi/ic_reply_white_18dp.png b/samples/browseable/WearNotifications/Application/res/drawable-xhdpi/ic_reply_white_18dp.png Binary files differnew file mode 100644 index 000000000..0424c2bd6 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-xhdpi/ic_reply_white_18dp.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-xxhdpi/ic_alarm_white_48dp.png b/samples/browseable/WearNotifications/Application/res/drawable-xxhdpi/ic_alarm_white_48dp.png Binary files differnew file mode 100644 index 000000000..f665286f8 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-xxhdpi/ic_alarm_white_48dp.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-xxhdpi/ic_cancel_white_48dp.png b/samples/browseable/WearNotifications/Application/res/drawable-xxhdpi/ic_cancel_white_48dp.png Binary files differnew file mode 100644 index 000000000..cf2822a07 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-xxhdpi/ic_cancel_white_48dp.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-xxhdpi/ic_launcher.png b/samples/browseable/WearNotifications/Application/res/drawable-xxhdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..cb4f56f26 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-xxhdpi/ic_launcher.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-xxhdpi/ic_message_black_18dp.png b/samples/browseable/WearNotifications/Application/res/drawable-xxhdpi/ic_message_black_18dp.png Binary files differnew file mode 100644 index 000000000..e710deeb5 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-xxhdpi/ic_message_black_18dp.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-xxhdpi/ic_person_black_48dp.png b/samples/browseable/WearNotifications/Application/res/drawable-xxhdpi/ic_person_black_48dp.png Binary files differnew file mode 100644 index 000000000..77e3a1816 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-xxhdpi/ic_person_black_48dp.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-xxhdpi/ic_reply_white_18dp.png b/samples/browseable/WearNotifications/Application/res/drawable-xxhdpi/ic_reply_white_18dp.png Binary files differnew file mode 100644 index 000000000..eeb5d4977 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-xxhdpi/ic_reply_white_18dp.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-xxxhdpi/ic_alarm_white_48dp.png b/samples/browseable/WearNotifications/Application/res/drawable-xxxhdpi/ic_alarm_white_48dp.png Binary files differnew file mode 100644 index 000000000..419f4bb4f --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-xxxhdpi/ic_alarm_white_48dp.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-xxxhdpi/ic_cancel_white_48dp.png b/samples/browseable/WearNotifications/Application/res/drawable-xxxhdpi/ic_cancel_white_48dp.png Binary files differnew file mode 100644 index 000000000..8bea844cd --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-xxxhdpi/ic_cancel_white_48dp.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-xxxhdpi/ic_launcher.png b/samples/browseable/WearNotifications/Application/res/drawable-xxxhdpi/ic_launcher.png Binary files differnew file mode 100644 index 000000000..77c9929cb --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-xxxhdpi/ic_launcher.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-xxxhdpi/ic_message_black_18dp.png b/samples/browseable/WearNotifications/Application/res/drawable-xxxhdpi/ic_message_black_18dp.png Binary files differnew file mode 100644 index 000000000..5456c42f4 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-xxxhdpi/ic_message_black_18dp.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-xxxhdpi/ic_person_black_48dp.png b/samples/browseable/WearNotifications/Application/res/drawable-xxxhdpi/ic_person_black_48dp.png Binary files differnew file mode 100644 index 000000000..6be3e3063 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-xxxhdpi/ic_person_black_48dp.png diff --git a/samples/browseable/WearNotifications/Application/res/drawable-xxxhdpi/ic_reply_white_18dp.png b/samples/browseable/WearNotifications/Application/res/drawable-xxxhdpi/ic_reply_white_18dp.png Binary files differnew file mode 100644 index 000000000..de0dad204 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/drawable-xxxhdpi/ic_reply_white_18dp.png diff --git a/samples/browseable/WearNotifications/Application/res/layout/activity_big_picture_main.xml b/samples/browseable/WearNotifications/Application/res/layout/activity_big_picture_main.xml new file mode 100644 index 000000000..e86c462f5 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/layout/activity_big_picture_main.xml @@ -0,0 +1,37 @@ +<?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. +--> +<RelativeLayout + 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=".handlers.BigPictureSocialMainActivity"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/main_text_activity_big_picture_main" + android:id="@+id/mainTextView" + android:layout_alignParentTop="true" + android:layout_alignParentStart="true" + android:layout_alignParentEnd="true" + android:layout_alignParentBottom="true"/> +</RelativeLayout> diff --git a/samples/browseable/WearNotifications/Application/res/layout/activity_big_text_main.xml b/samples/browseable/WearNotifications/Application/res/layout/activity_big_text_main.xml new file mode 100644 index 000000000..5b37603bd --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/layout/activity_big_text_main.xml @@ -0,0 +1,38 @@ +<?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. +--> +<RelativeLayout + 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=".handlers.BigTextMainActivity"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/main_text_activity_big_text_main" + android:id="@+id/mainTextView" + android:layout_alignParentTop="true" + android:layout_alignParentStart="true" + android:layout_alignParentEnd="true" + android:layout_alignParentBottom="true"/> + +</RelativeLayout> diff --git a/samples/browseable/WearNotifications/Application/res/layout/activity_inbox_main.xml b/samples/browseable/WearNotifications/Application/res/layout/activity_inbox_main.xml new file mode 100644 index 000000000..0377b4ae8 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/layout/activity_inbox_main.xml @@ -0,0 +1,38 @@ +<?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. +--> +<RelativeLayout + 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=".handlers.InboxMainActivity"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/main_text_activity_inbox_main" + android:id="@+id/mainTextView" + android:layout_alignParentTop="true" + android:layout_alignParentStart="true" + android:layout_alignParentEnd="true" + android:layout_alignParentBottom="true"/> + +</RelativeLayout> diff --git a/samples/browseable/WearNotifications/Application/res/layout/activity_main.xml b/samples/browseable/WearNotifications/Application/res/layout/activity_main.xml new file mode 100644 index 000000000..c18e102b2 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/layout/activity_main.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2016 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/mainRelativeLayout" + 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.wearable.wear.wearnotifications.MainActivity"> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Pick your Notification Style:" + android:id="@+id/spinnerHeadertextView"/> + + <Spinner + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:id="@+id/spinner" + android:layout_below="@+id/spinnerHeadertextView" + android:paddingTop="@dimen/activity_vertical_margin" + android:layout_alignParentStart="true" + android:layout_alignParentEnd="true"/> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/notificationDetails" + android:layout_below="@+id/spinner" + android:layout_alignParentStart="true" + android:layout_above="@+id/submit" + android:layout_alignEnd="@+id/spinner" + android:paddingTop="@dimen/activity_vertical_margin"/> + + <Button + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Launch!" + android:onClick="onClick" + android:layout_alignParentBottom="true" + android:layout_alignParentStart="true" + android:id="@+id/submit"/> +</RelativeLayout> diff --git a/samples/browseable/WearNotifications/Application/res/layout/activity_messaging_main.xml b/samples/browseable/WearNotifications/Application/res/layout/activity_messaging_main.xml new file mode 100644 index 000000000..205b4285d --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/layout/activity_messaging_main.xml @@ -0,0 +1,38 @@ +<?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. +--> +<RelativeLayout + 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=".handlers.MessagingMainActivity"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/main_text_activity_messaging_main" + android:id="@+id/mainTextView" + android:layout_alignParentTop="true" + android:layout_alignParentStart="true" + android:layout_alignParentEnd="true" + android:layout_alignParentBottom="true"/> + +</RelativeLayout>
\ No newline at end of file diff --git a/samples/browseable/WearNotifications/Application/res/values-sw600dp/template-dimens.xml b/samples/browseable/WearNotifications/Application/res/values-sw600dp/template-dimens.xml new file mode 100644 index 000000000..22074a2bd --- /dev/null +++ b/samples/browseable/WearNotifications/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/WearNotifications/Application/res/values-sw600dp/template-styles.xml b/samples/browseable/WearNotifications/Application/res/values-sw600dp/template-styles.xml new file mode 100644 index 000000000..03d197418 --- /dev/null +++ b/samples/browseable/WearNotifications/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/WearNotifications/Application/res/values-v11/template-styles.xml b/samples/browseable/WearNotifications/Application/res/values-v11/template-styles.xml new file mode 100644 index 000000000..8c1ea66f2 --- /dev/null +++ b/samples/browseable/WearNotifications/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/WearNotifications/Application/res/values-v21/base-colors.xml b/samples/browseable/WearNotifications/Application/res/values-v21/base-colors.xml new file mode 100644 index 000000000..8b6ec3f85 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/values-v21/base-colors.xml @@ -0,0 +1,21 @@ +<?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> + + +</resources> diff --git a/samples/browseable/WearNotifications/Application/res/values-v21/base-template-styles.xml b/samples/browseable/WearNotifications/Application/res/values-v21/base-template-styles.xml new file mode 100644 index 000000000..c778e4f98 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/values-v21/base-template-styles.xml @@ -0,0 +1,24 @@ +<?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> + + <!-- Activity themes --> + <style name="Theme.Base" parent="android:Theme.Material.Light"> + </style> + +</resources> diff --git a/samples/browseable/WearNotifications/Application/res/values-w820dp/dimens.xml b/samples/browseable/WearNotifications/Application/res/values-w820dp/dimens.xml new file mode 100644 index 000000000..2a45ed87c --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/values-w820dp/dimens.xml @@ -0,0 +1,22 @@ +<?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> + <!-- Example customization of dimensions originally defined in res/values/dimens.xml + (such as screen margins) for screens with more than 820dp of available width. This + would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). --> + <dimen name="activity_horizontal_margin">64dp</dimen> +</resources> diff --git a/samples/browseable/WearNotifications/Application/res/values/base-strings.xml b/samples/browseable/WearNotifications/Application/res/values/base-strings.xml new file mode 100644 index 000000000..554428945 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/values/base-strings.xml @@ -0,0 +1,33 @@ +<?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">Wear Notifications</string> + <string name="intro_message"> + <![CDATA[ + + + Sample demonstrates best practices for Notification Styles that support Android + phone/tablets and Android Wear. The phone app demonstrates best practices if you do not + have a dedicated Android Wear app for Notifications. While the Android Wear app + demonstrates best practices for a standalone Wear Notification experience without + the Notifications showing on the phone/tablet. + + + ]]> + </string> +</resources> diff --git a/samples/browseable/WearNotifications/Application/res/values/colors.xml b/samples/browseable/WearNotifications/Application/res/values/colors.xml new file mode 100644 index 000000000..752b74fc3 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/values/colors.xml @@ -0,0 +1,21 @@ +<?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> + <color name="colorPrimary">#3F51B5</color> + <color name="colorPrimaryDark">#303F9F</color> + <color name="colorAccent">#FF4081</color> +</resources> diff --git a/samples/browseable/WearNotifications/Application/res/values/dimens.xml b/samples/browseable/WearNotifications/Application/res/values/dimens.xml new file mode 100644 index 000000000..fcb2a4296 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/values/dimens.xml @@ -0,0 +1,21 @@ +<?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> + <!-- 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/WearNotifications/Application/res/values/strings.xml b/samples/browseable/WearNotifications/Application/res/values/strings.xml new file mode 100644 index 000000000..ddd1641be --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/values/strings.xml @@ -0,0 +1,43 @@ +<?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="reply_label">Reply</string> + <string name="reply_name">Me</string> + + <string name="title_activity_big_text_main">BigTextStyle Main Activity</string> + <string name="title_activity_big_picture_main">BigPictureStyle Main Activity</string> + <string name="title_activity_inbox_main">InboxStyle Main Activity</string> + <string name="title_activity_messaging_main">MessagingStyle Main Activity</string> + + <string name="main_text_activity_big_text_main"> + This Activity would handle the reminder app\'s functionality. + \n\nThe notification type for this example was the Big Text Style! + </string> + <string name="main_text_activity_big_picture_main"> + This Activity would handle the social app\'s functionality for an individual post. + \n\nThe notification type for this example was the Big Picture Style! + </string> + <string name="main_text_activity_inbox_main"> + This Activity would handle the email app\'s functionality for an email(s). + \n\nThe notification type for this example was the Inbox Style! + </string> + <string name="main_text_activity_messaging_main"> + This Activity would handle the messaging app\'s functionality for a chat(s). + \n\nThe notification type for this example was the Messaging Style! + </string> +</resources>
\ No newline at end of file diff --git a/samples/browseable/WearNotifications/Application/res/values/styles.xml b/samples/browseable/WearNotifications/Application/res/values/styles.xml new file mode 100644 index 000000000..6ea59e045 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/res/values/styles.xml @@ -0,0 +1,21 @@ +<?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> + + <style name="AppThemeOverride" parent="Theme.AppCompat.Light" /> + +</resources>
\ No newline at end of file diff --git a/samples/browseable/WearNotifications/Application/res/values/template-dimens.xml b/samples/browseable/WearNotifications/Application/res/values/template-dimens.xml new file mode 100644 index 000000000..39e710b5c --- /dev/null +++ b/samples/browseable/WearNotifications/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/WearNotifications/Application/res/values/template-styles.xml b/samples/browseable/WearNotifications/Application/res/values/template-styles.xml new file mode 100644 index 000000000..6e7d593dd --- /dev/null +++ b/samples/browseable/WearNotifications/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/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/GlobalNotificationBuilder.java b/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/GlobalNotificationBuilder.java new file mode 100644 index 000000000..1b1743f6f --- /dev/null +++ b/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/GlobalNotificationBuilder.java @@ -0,0 +1,60 @@ +/* +Copyright 2016 The Android Open Source Project + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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.wearable.wear.wearnotifications; + +import android.support.v7.app.NotificationCompat; + +/** + * We use a Singleton for a global copy of the NotificationCompat.Builder to update active + * Notifications from other Services/Activities. + * + * You have two options for updating your notifications: + * + * 1. Use a new NotificationCompatBuilder to create the Notification. This approach requires you + * to get *ALL* the information and pass it to the builder. We get all the information from a Mock + * Database and this is the approach used in the MainActivity. + * + * 2. Use an existing NotificationCompatBuilder to create a Notification. This approach requires + * you to store a reference to the original builder. The benefit is you only need the new/updated + * information for an existing notification. We use this approach in the IntentService handlers to + * update existing notifications. + * + * IMPORTANT NOTE 1: You shouldn't save/modify the resulting Notification object using + * its member variables and/or legacy APIs. If you want to retain anything from update + * to update, retain the Builder as option 2 outlines. + * + * IMPORTANT NOTE 2: If the global Notification Builder is lost because the process is killed, you + * should have a way to recreate the Notification Builder from a persistent state. (We do this as + * well in the sample, check the IntentServices.) + */ +public final class GlobalNotificationBuilder { + + private static NotificationCompat.Builder sGlobalNotificationCompatBuilder = null; + + /* + * Empty constructor - We don't initialize builder because we rely on a null state to let us + * know the Application's process was killed. + */ + private GlobalNotificationBuilder () { } + + public static void setNotificationCompatBuilderInstance (NotificationCompat.Builder builder) { + sGlobalNotificationCompatBuilder = builder; + } + + public static NotificationCompat.Builder getNotificationCompatBuilderInstance(){ + return sGlobalNotificationCompatBuilder; + } +}
\ No newline at end of file diff --git a/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/MainActivity.java b/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/MainActivity.java new file mode 100644 index 000000000..65b0f7fcf --- /dev/null +++ b/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/MainActivity.java @@ -0,0 +1,828 @@ +/* +Copyright 2016 The Android Open Source Project + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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.wearable.wear.wearnotifications; + +import android.app.Notification; +import android.app.PendingIntent; +import android.content.Intent; +import android.graphics.BitmapFactory; +import android.os.Build; +import android.os.Bundle; +import android.support.design.widget.Snackbar; +import android.support.v4.app.NotificationCompat.BigPictureStyle; +import android.support.v4.app.NotificationCompat.BigTextStyle; +import android.support.v4.app.NotificationCompat.InboxStyle; +import android.support.v4.app.NotificationCompat.MessagingStyle; +import android.support.v4.app.NotificationManagerCompat; +import android.support.v4.app.RemoteInput; +import android.support.v4.app.TaskStackBuilder; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.app.NotificationCompat; +import android.util.Log; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.RelativeLayout; +import android.widget.Spinner; +import android.widget.TextView; + + + +import com.example.android.wearable.wear.wearnotifications.handlers.BigPictureSocialIntentService; +import com.example.android.wearable.wear.wearnotifications.handlers.BigPictureSocialMainActivity; +import com.example.android.wearable.wear.wearnotifications.handlers.BigTextIntentService; +import com.example.android.wearable.wear.wearnotifications.handlers.BigTextMainActivity; +import com.example.android.wearable.wear.wearnotifications.handlers.InboxMainActivity; +import com.example.android.wearable.wear.wearnotifications.handlers.MessagingIntentService; +import com.example.android.wearable.wear.wearnotifications.handlers.MessagingMainActivity; +import com.example.android.wearable.wear.wearnotifications.mock.MockDatabase; + +/** + * The Activity demonstrates several popular Notification.Style examples along with their best + * practices (include proper Android Wear support when you don't have a dedicated Android Wear + * app). + */ +public class MainActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener { + + public static final String TAG = "MainActivity"; + + public static final int NOTIFICATION_ID = 888; + + // Used for Notification Style array and switch statement for Spinner selection + private static final String BIG_TEXT_STYLE = "BIG_TEXT_STYLE"; + private static final String BIG_PICTURE_STYLE = "BIG_PICTURE_STYLE"; + private static final String INBOX_STYLE = "INBOX_STYLE"; + private static final String MESSAGING_STYLE = "MESSAGING_STYLE"; + + // Collection of notification styles to back ArrayAdapter for Spinner + private static final String[] NOTIFICATION_STYLES = + {BIG_TEXT_STYLE, BIG_PICTURE_STYLE, INBOX_STYLE, MESSAGING_STYLE}; + + private static final String[] NOTIFICATION_STYLES_DESCRIPTION = + { + "Demos reminder type app using BIG_TEXT_STYLE", + "Demos social type app using BIG_PICTURE_STYLE + inline notification response", + "Demos email type app using INBOX_STYLE", + "Demos messaging app using MESSAGING_STYLE + inline notification responses" + }; + + private NotificationManagerCompat mNotificationManagerCompat; + + private int mSelectedNotification = 0; + + // RelativeLayout is needed for SnackBars to alert users when Notifications are disabled for app + private RelativeLayout mMainRelativeLayout; + private Spinner mSpinner; + private TextView mNotificationDetailsTextView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + mMainRelativeLayout = (RelativeLayout) findViewById(R.id.mainRelativeLayout); + mNotificationDetailsTextView = (TextView) findViewById(R.id.notificationDetails); + mSpinner = (Spinner) findViewById(R.id.spinner); + + mNotificationManagerCompat = NotificationManagerCompat.from(getApplicationContext()); + + // Create an ArrayAdapter using the string array and a default spinner layout + ArrayAdapter<CharSequence> adapter = + new ArrayAdapter( + this, + android.R.layout.simple_spinner_item, + NOTIFICATION_STYLES); + // Specify the layout to use when the list of choices appears + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + // Apply the adapter to the spinner + mSpinner.setAdapter(adapter); + mSpinner.setOnItemSelectedListener(this); + } + + @Override + public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { + Log.d(TAG, "onItemSelected(): position: " + position + " id: " + id); + + mSelectedNotification = position; + + mNotificationDetailsTextView.setText( + NOTIFICATION_STYLES_DESCRIPTION[mSelectedNotification]); + } + @Override + public void onNothingSelected(AdapterView<?> parent) { + // Required + } + + public void onClick(View view) { + + Log.d(TAG, "onClick()"); + + boolean areNotificationsEnabled = mNotificationManagerCompat.areNotificationsEnabled(); + + if (!areNotificationsEnabled) { + // Because the user took an action to create a notification, we create a prompt to let + // the user re-enable notifications for this application again. + Snackbar snackbar = Snackbar + .make( + mMainRelativeLayout, + "You need to enable notifications for this app", + Snackbar.LENGTH_LONG) + .setAction("ENABLE", new View.OnClickListener() { + @Override + public void onClick(View view) { + // Links to this app's notification settings + openNotificationSettingsForApp(); + } + }); + snackbar.show(); + return; + } + + String notificationStyle = NOTIFICATION_STYLES[mSelectedNotification]; + + switch (notificationStyle) { + case BIG_TEXT_STYLE: + generateBigTextStyleNotification(); + break; + + case BIG_PICTURE_STYLE: + generateBigPictureStyleNotification(); + break; + + case INBOX_STYLE: + generateInboxStyleNotification(); + break; + + case MESSAGING_STYLE: + generateMessagingStyleNotification(); + break; + + default: + // continue below + } + } + + /* + * Generates a BIG_TEXT_STYLE Notification that supports both phone/tablet and wear. For devices + * on API level 16 (4.1.x - Jelly Bean) and after, displays BIG_TEXT_STYLE. Otherwise, displays + * a basic notification. + */ + private void generateBigTextStyleNotification() { + + Log.d(TAG, "generateBigTextStyleNotification()"); + + // Main steps for building a BIG_TEXT_STYLE notification: + // 0. Get your data + // 1. Build the BIG_TEXT_STYLE + // 2. Set up main Intent for notification + // 3. Create additional Actions for the Notification + // 4. Build and issue the notification + + // 0. Get your data (everything unique per Notification) + MockDatabase.BigTextStyleReminderAppData bigTextStyleReminderAppData = + MockDatabase.getBigTextStyleData(); + + // 1. Build the BIG_TEXT_STYLE + BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle() + // Overrides ContentText in the big form of the template + .bigText(bigTextStyleReminderAppData.getBigText()) + // Overrides ContentTitle in the big form of the template + .setBigContentTitle(bigTextStyleReminderAppData.getBigContentTitle()) + // Summary line after the detail section in the big form of the template + // Note: To improve readability, don't overload the user with info. If Summary Text + // doesn't add critical information, you should skip it. + .setSummaryText(bigTextStyleReminderAppData.getSummaryText()); + + + // 2. Set up main Intent for notification + Intent notifyIntent = new Intent(this, BigTextMainActivity.class); + + // When creating your Intent, you need to take into account the back state, i.e., what + // happens after your Activity launches and the user presses the back button. + + // There are two options: + // 1. Regular activity - You're starting an Activity that's part of the application's + // normal workflow. + + // 2. Special activity - The user only sees this Activity if it's started from a + // notification. In a sense, the Activity extends the notification by providing + // information that would be hard to display in the notification itself. + + // For the BIG_TEXT_STYLE notification, we will consider the activity launched by the main + // Intent as a special activity, so we will follow option 2. + + // For an example of option 1, check either the MESSAGING_STYLE or BIG_PICTURE_STYLE + // examples. + + // For more information, check out our dev article: + // https://developer.android.com/training/notify-user/navigation.html + + // Sets the Activity to start in a new, empty task + notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + + PendingIntent notifyPendingIntent = + PendingIntent.getActivity( + this, + 0, + notifyIntent, + PendingIntent.FLAG_UPDATE_CURRENT + ); + + + // 3. Create additional Actions (Intents) for the Notification + + // In our case, we create two additional actions: a Snooze action and a Dismiss action + // Snooze Action + Intent snoozeIntent = new Intent(this, BigTextIntentService.class); + snoozeIntent.setAction(BigTextIntentService.ACTION_SNOOZE); + + PendingIntent snoozePendingIntent = PendingIntent.getService(this, 0, snoozeIntent, 0); + NotificationCompat.Action snoozeAction = + new NotificationCompat.Action.Builder( + R.drawable.ic_alarm_white_48dp, + "Snooze", + snoozePendingIntent) + .build(); + + + // Dismiss Action + Intent dismissIntent = new Intent(this, BigTextIntentService.class); + dismissIntent.setAction(BigTextIntentService.ACTION_DISMISS); + + PendingIntent dismissPendingIntent = PendingIntent.getService(this, 0, dismissIntent, 0); + NotificationCompat.Action dismissAction = + new NotificationCompat.Action.Builder( + R.drawable.ic_cancel_white_48dp, + "Dismiss", + dismissPendingIntent) + .build(); + + + // 4. Build and issue the notification + + // Because we want this to be a new notification (not updating a previous notification), we + // create a new Builder. Later, we use the same global builder to get back the notification + // we built here for the snooze action, that is, canceling the notification and relaunching + // it several seconds later. + + NotificationCompat.Builder notificationCompatBuilder = + new NotificationCompat.Builder(getApplicationContext()); + + GlobalNotificationBuilder.setNotificationCompatBuilderInstance(notificationCompatBuilder); + + Notification notification = notificationCompatBuilder + // BIG_TEXT_STYLE sets title and content for API 16 (4.1 and after) + .setStyle(bigTextStyle) + // Title for API <16 (4.0 and below) devices + .setContentTitle(bigTextStyleReminderAppData.getContentTitle()) + // Content for API <24 (7.0 and below) devices + .setContentText(bigTextStyleReminderAppData.getContentText()) + .setSmallIcon(R.drawable.ic_launcher) + .setLargeIcon(BitmapFactory.decodeResource( + getResources(), + R.drawable.ic_alarm_white_48dp)) + .setContentIntent(notifyPendingIntent) + // Set primary color (important for Wear 2.0 Notifications) + .setColor(getResources().getColor(R.color.colorPrimary)) + + // SIDE NOTE: Auto-bundling is enabled for 4 or more notifications on API 24+ (N+) + // devices and all Android Wear devices. If you have more than one notification and + // you prefer a different summary notification, set a group key and create a + // summary notification via + // .setGroupSummary(true) + // .setGroup(GROUP_KEY_YOUR_NAME_HERE) + + .setCategory(Notification.CATEGORY_REMINDER) + .setPriority(Notification.PRIORITY_HIGH) + + // Shows content on the lock-screen + .setVisibility(Notification.VISIBILITY_PUBLIC) + + // Adds additional actions specified above + .addAction(snoozeAction) + .addAction(dismissAction) + + .build(); + + mNotificationManagerCompat.notify(NOTIFICATION_ID, notification); + } + + /* + * Generates a BIG_PICTURE_STYLE Notification that supports both phone/tablet and wear. For + * devices on API level 16 (4.1.x - Jelly Bean) and after, displays BIG_PICTURE_STYLE. + * Otherwise, displays a basic notification. + * + * This example Notification is a social post. It allows updating the notification with + * comments/responses via RemoteInput and the BigPictureSocialIntentService on 24+ (N+) and + * Android Wear devices. + */ + private void generateBigPictureStyleNotification() { + + Log.d(TAG, "generateBigPictureStyleNotification()"); + + // Main steps for building a BIG_PICTURE_STYLE notification: + // 0. Get your data + // 1. Build the BIG_PICTURE_STYLE + // 2. Set up main Intent for notification + // 3. Set up RemoteInput, so users can input (keyboard and voice) from notification + // 4. Build and issue the notification + + // 0. Get your data (everything unique per Notification) + MockDatabase.BigPictureStyleSocialAppData bigPictureStyleSocialAppData = + MockDatabase.getBigPictureStyleData(); + + // 1. Build the BIG_PICTURE_STYLE + BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle() + // Provides the bitmap for the BigPicture notification + .bigPicture( + BitmapFactory.decodeResource( + getResources(), + bigPictureStyleSocialAppData.getBigImage())) + // Overrides ContentTitle in the big form of the template + .setBigContentTitle(bigPictureStyleSocialAppData.getBigContentTitle()) + // Summary line after the detail section in the big form of the template + .setSummaryText(bigPictureStyleSocialAppData.getSummaryText()); + + // 2. Set up main Intent for notification + Intent mainIntent = new Intent(this, BigPictureSocialMainActivity.class); + + // When creating your Intent, you need to take into account the back state, i.e., what + // happens after your Activity launches and the user presses the back button. + + // There are two options: + // 1. Regular activity - You're starting an Activity that's part of the application's + // normal workflow. + + // 2. Special activity - The user only sees this Activity if it's started from a + // notification. In a sense, the Activity extends the notification by providing + // information that would be hard to display in the notification itself. + + // Even though this sample's MainActivity doesn't link to the Activity this Notification + // launches directly, i.e., it isn't part of the normal workflow, a social app generally + // always links to individual posts as part of the app flow, so we will follow option 1. + + // For an example of option 2, check out the BIG_TEXT_STYLE example. + + // For more information, check out our dev article: + // https://developer.android.com/training/notify-user/navigation.html + + TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); + // Adds the back stack + stackBuilder.addParentStack(BigPictureSocialMainActivity.class); + // Adds the Intent to the top of the stack + stackBuilder.addNextIntent(mainIntent); + // Gets a PendingIntent containing the entire back stack + PendingIntent mainPendingIntent = + PendingIntent.getActivity( + this, + 0, + mainIntent, + PendingIntent.FLAG_UPDATE_CURRENT + ); + + // 3. Set up RemoteInput, so users can input (keyboard and voice) from notification + + // Note: For API <24 (M and below) we need to use an Activity, so the lock-screen presents + // the auth challenge. For API 24+ (N and above), we use a Service (could be a + // BroadcastReceiver), so the user can input from Notification or lock-screen (they have + // choice to allow) without leaving the notification. + + // Create the RemoteInput + String replyLabel = getString(R.string.reply_label); + RemoteInput remoteInput = + new RemoteInput.Builder(BigPictureSocialIntentService.EXTRA_COMMENT) + .setLabel(replyLabel) + // List of quick response choices for any wearables paired with the phone + .setChoices(bigPictureStyleSocialAppData.getPossiblePostResponses()) + .build(); + + // Pending intent = + // API <24 (M and below): activity so the lock-screen presents the auth challenge + // API 24+ (N and above): this should be a Service or BroadcastReceiver + PendingIntent replyActionPendingIntent; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + Intent intent = new Intent(this, BigPictureSocialIntentService.class); + intent.setAction(BigPictureSocialIntentService.ACTION_COMMENT); + replyActionPendingIntent = PendingIntent.getService(this, 0, intent, 0); + + } else { + replyActionPendingIntent = mainPendingIntent; + } + + NotificationCompat.Action replyAction = + new NotificationCompat.Action.Builder( + R.drawable.ic_reply_white_18dp, + replyLabel, + replyActionPendingIntent) + .addRemoteInput(remoteInput) + .build(); + + // 4. Build and issue the notification + + // Because we want this to be a new notification (not updating a previous notification), we + // create a new Builder. Later, we use the same global builder to get back the notification + // we built here for a comment on the post. + + NotificationCompat.Builder notificationCompatBuilder = + new NotificationCompat.Builder(getApplicationContext()); + + GlobalNotificationBuilder.setNotificationCompatBuilderInstance(notificationCompatBuilder); + + // 4. Build and issue the notification + notificationCompatBuilder + // BIG_PICTURE_STYLE sets title and content for API 16 (4.1 and after) + .setStyle(bigPictureStyle) + // Title for API <16 (4.0 and below) devices + .setContentTitle(bigPictureStyleSocialAppData.getContentTitle()) + // Content for API <24 (7.0 and below) devices + .setContentText(bigPictureStyleSocialAppData.getContentText()) + .setSmallIcon(R.drawable.ic_launcher) + .setLargeIcon(BitmapFactory.decodeResource( + getResources(), + R.drawable.ic_person_black_48dp)) + .setContentIntent(mainPendingIntent) + // Set primary color (important for Wear 2.0 Notifications) + .setColor(getResources().getColor(R.color.colorPrimary)) + + // SIDE NOTE: Auto-bundling is enabled for 4 or more notifications on API 24+ (N+) + // devices and all Android Wear devices. If you have more than one notification and + // you prefer a different summary notification, set a group key and create a + // summary notification via + // .setGroupSummary(true) + // .setGroup(GROUP_KEY_YOUR_NAME_HERE) + + .setSubText(Integer.toString(1)) + .addAction(replyAction) + .setCategory(Notification.CATEGORY_SOCIAL) + .setPriority(Notification.PRIORITY_HIGH) + + // Hides content on the lock-screen + .setVisibility(Notification.VISIBILITY_PRIVATE); + + // If the phone is in "Do not disturb mode, the user will still be notified if + // the sender(s) is starred as a favorite. + for (String name : bigPictureStyleSocialAppData.getParticipants()) { + notificationCompatBuilder.addPerson(name); + } + + Notification notification = notificationCompatBuilder.build(); + + mNotificationManagerCompat.notify(NOTIFICATION_ID, notification); + } + + /* + * Generates a INBOX_STYLE Notification that supports both phone/tablet and wear. For devices + * on API level 16 (4.1.x - Jelly Bean) and after, displays INBOX_STYLE. Otherwise, displays a + * basic notification. + */ + private void generateInboxStyleNotification() { + + Log.d(TAG, "generateInboxStyleNotification()"); + + + // Main steps for building a INBOX_STYLE notification: + // 0. Get your data + // 1. Build the INBOX_STYLE + // 2. Set up main Intent for notification + // 3. Build and issue the notification + + // 0. Get your data (everything unique per Notification) + MockDatabase.InboxStyleEmailAppData inboxStyleEmailAppData = + MockDatabase.getInboxStyleData(); + + // 1. Build the INBOX_STYLE + InboxStyle inboxStyle = new NotificationCompat.InboxStyle() + // This title is slightly different than regular title, since I know INBOX_STYLE is + // available. + .setBigContentTitle(inboxStyleEmailAppData.getBigContentTitle()) + .setSummaryText(inboxStyleEmailAppData.getSummaryText()); + + // Add each summary line of the new emails, you can add up to 5 + for (String summary : inboxStyleEmailAppData.getIndividualEmailSummary()) { + inboxStyle.addLine(summary); + } + + // 2. Set up main Intent for notification + Intent mainIntent = new Intent(this, InboxMainActivity.class); + + // When creating your Intent, you need to take into account the back state, i.e., what + // happens after your Activity launches and the user presses the back button. + + // There are two options: + // 1. Regular activity - You're starting an Activity that's part of the application's + // normal workflow. + + // 2. Special activity - The user only sees this Activity if it's started from a + // notification. In a sense, the Activity extends the notification by providing + // information that would be hard to display in the notification itself. + + // Even though this sample's MainActivity doesn't link to the Activity this Notification + // launches directly, i.e., it isn't part of the normal workflow, a eamil app generally + // always links to individual emails as part of the app flow, so we will follow option 1. + + // For an example of option 2, check out the BIG_TEXT_STYLE example. + + // For more information, check out our dev article: + // https://developer.android.com/training/notify-user/navigation.html + + TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); + // Adds the back stack + stackBuilder.addParentStack(InboxMainActivity.class); + // Adds the Intent to the top of the stack + stackBuilder.addNextIntent(mainIntent); + // Gets a PendingIntent containing the entire back stack + PendingIntent mainPendingIntent = + PendingIntent.getActivity( + this, + 0, + mainIntent, + PendingIntent.FLAG_UPDATE_CURRENT + ); + + // 3. Build and issue the notification + + // Because we want this to be a new notification (not updating a previous notification), we + // create a new Builder. However, we don't need to update this notification later, so we + // will not need to set a global builder for access to the notification later. + + NotificationCompat.Builder notificationCompatBuilder = + new NotificationCompat.Builder(getApplicationContext()); + + GlobalNotificationBuilder.setNotificationCompatBuilderInstance(notificationCompatBuilder); + + // 4. Build and issue the notification + notificationCompatBuilder + + // INBOX_STYLE sets title and content for API 16+ (4.1 and after) when the + // notification is expanded + .setStyle(inboxStyle) + + // Title for API <16 (4.0 and below) devices and API 16+ (4.1 and after) when the + // notification is collapsed + .setContentTitle(inboxStyleEmailAppData.getContentTitle()) + + // Content for API <24 (7.0 and below) devices and API 16+ (4.1 and after) when the + // notification is collapsed + .setContentText(inboxStyleEmailAppData.getContentText()) + .setSmallIcon(R.drawable.ic_launcher) + .setLargeIcon(BitmapFactory.decodeResource( + getResources(), + R.drawable.ic_person_black_48dp)) + .setContentIntent(mainPendingIntent) + // Set primary color (important for Wear 2.0 Notifications) + .setColor(getResources().getColor(R.color.colorPrimary)) + + // SIDE NOTE: Auto-bundling is enabled for 4 or more notifications on API 24+ (N+) + // devices and all Android Wear devices. If you have more than one notification and + // you prefer a different summary notification, set a group key and create a + // summary notification via + // .setGroupSummary(true) + // .setGroup(GROUP_KEY_YOUR_NAME_HERE) + + // Sets large number at the right-hand side of the notification for API <24 devices + .setSubText(Integer.toString(inboxStyleEmailAppData.getNumberOfNewEmails())) + + .setCategory(Notification.CATEGORY_EMAIL) + .setPriority(Notification.PRIORITY_HIGH) + + // Hides content on the lock-screen + .setVisibility(Notification.VISIBILITY_PRIVATE); + + // If the phone is in "Do not disturb mode, the user will still be notified if + // the sender(s) is starred as a favorite. + for (String name : inboxStyleEmailAppData.getParticipants()) { + notificationCompatBuilder.addPerson(name); + } + + Notification notification = notificationCompatBuilder.build(); + + mNotificationManagerCompat.notify(NOTIFICATION_ID, notification); + } + + /* + * Generates a MESSAGING_STYLE Notification that supports both phone/tablet and wear. For + * devices on API level 24 (7.0 - Nougat) and after, displays MESSAGING_STYLE. Otherwise, + * displays a basic BIG_TEXT_STYLE. + */ + private void generateMessagingStyleNotification() { + + Log.d(TAG, "generateMessagingStyleNotification()"); + + // Main steps for building a MESSAGING_STYLE notification: + // 0. Get your data + // 1. Build the MESSAGING_STYLE + // 2. Add support for Wear 1.+ + // 3. Set up main Intent for notification + // 4. Set up RemoteInput (users can input directly from notification) + // 5. Build and issue the notification + + // 0. Get your data (everything unique per Notification) + MockDatabase.MessagingStyleCommsAppData messagingStyleCommsAppData = + MockDatabase.getMessagingStyleData(); + + // 1. Build the Notification.Style (MESSAGING_STYLE) + String contentTitle = messagingStyleCommsAppData.getContentTitle(); + + MessagingStyle messagingStyle = + new NotificationCompat.MessagingStyle(messagingStyleCommsAppData.getReplayName()) + // You could set a different title to appear when the messaging style + // is supported on device (24+) if you wish. In our case, we use the same + // title. + .setConversationTitle(contentTitle); + + // Adds all Messages + // Note: Messages include the text, timestamp, and sender + for (MessagingStyle.Message message : messagingStyleCommsAppData.getMessages()) { + messagingStyle.addMessage(message); + } + + + // 2. Add support for Wear 1.+ + + // Since Wear 1.0 doesn't support the MESSAGING_STYLE, we use the BIG_TEXT_STYLE, so all the + // text is visible. + + // This is basically a toString() of all the Messages above. + String fullMessageForWearVersion1 = messagingStyleCommsAppData.getFullConversation(); + + Notification chatHistoryForWearV1 = new NotificationCompat.Builder(getApplicationContext()) + .setStyle(new BigTextStyle().bigText(fullMessageForWearVersion1)) + .setContentTitle(contentTitle) + .setSmallIcon(R.drawable.ic_launcher) + .setContentText(fullMessageForWearVersion1) + .build(); + + // Adds page with all text to support Wear 1.+. + NotificationCompat.WearableExtender wearableExtenderForWearVersion1 = + new NotificationCompat.WearableExtender() + .addPage(chatHistoryForWearV1); + + + + // 3. Set up main Intent for notification + Intent notifyIntent = new Intent(this, MessagingMainActivity.class); + + // When creating your Intent, you need to take into account the back state, i.e., what + // happens after your Activity launches and the user presses the back button. + + // There are two options: + // 1. Regular activity - You're starting an Activity that's part of the application's + // normal workflow. + + // 2. Special activity - The user only sees this Activity if it's started from a + // notification. In a sense, the Activity extends the notification by providing + // information that would be hard to display in the notification itself. + + // Even though this sample's MainActivity doesn't link to the Activity this Notification + // launches directly, i.e., it isn't part of the normal workflow, a chat app generally + // always links to individual conversations as part of the app flow, so we will follow + // option 1. + + // For an example of option 2, check out the BIG_TEXT_STYLE example. + + // For more information, check out our dev article: + // https://developer.android.com/training/notify-user/navigation.html + + TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); + // Adds the back stack + stackBuilder.addParentStack(MessagingMainActivity.class); + // Adds the Intent to the top of the stack + stackBuilder.addNextIntent(notifyIntent); + // Gets a PendingIntent containing the entire back stack + PendingIntent mainPendingIntent = + PendingIntent.getActivity( + this, + 0, + notifyIntent, + PendingIntent.FLAG_UPDATE_CURRENT + ); + + + // 4. Set up RemoteInput, so users can input (keyboard and voice) from notification + + // Note: For API <24 (M and below) we need to use an Activity, so the lock-screen present + // the auth challenge. For API 24+ (N and above), we use a Service (could be a + // BroadcastReceiver), so the user can input from Notification or lock-screen (they have + // choice to allow) without leaving the notification. + + // Create the RemoteInput specifying this key + String replyLabel = getString(R.string.reply_label); + RemoteInput remoteInput = new RemoteInput.Builder(MessagingIntentService.EXTRA_REPLY) + .setLabel(replyLabel) + .build(); + + // Pending intent = + // API <24 (M and below): activity so the lock-screen presents the auth challenge + // API 24+ (N and above): this should be a Service or BroadcastReceiver + PendingIntent replyActionPendingIntent; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + Intent intent = new Intent(this, MessagingIntentService.class); + intent.setAction(MessagingIntentService.ACTION_REPLY); + replyActionPendingIntent = PendingIntent.getService(this, 0, intent, 0); + + } else { + replyActionPendingIntent = mainPendingIntent; + } + + NotificationCompat.Action replyAction = + new NotificationCompat.Action.Builder( + R.drawable.ic_reply_white_18dp, + replyLabel, + replyActionPendingIntent) + .addRemoteInput(remoteInput) + // Allows system to generate replies by context of conversation + .setAllowGeneratedReplies(true) + .build(); + + + // 5. Build and issue the notification + + // Because we want this to be a new notification (not updating current notification), we + // create a new Builder. Later, we update this same notification, so we need to save this + // Builder globally (as outlined earlier). + + NotificationCompat.Builder notificationCompatBuilder = + new NotificationCompat.Builder(getApplicationContext()); + + GlobalNotificationBuilder.setNotificationCompatBuilderInstance(notificationCompatBuilder); + + // Builds and issues notification + notificationCompatBuilder + // MESSAGING_STYLE sets title and content for API 24+ (N and above) devices + .setStyle(messagingStyle) + // Title for API <24 (M and below) devices + .setContentTitle(contentTitle) + // Content for API <24 (M and below) devices + .setContentText(messagingStyleCommsAppData.getContentText()) + .setSmallIcon(R.drawable.ic_launcher) + .setLargeIcon(BitmapFactory.decodeResource( + getResources(), + R.drawable.ic_person_black_48dp)) + .setContentIntent(mainPendingIntent) + // Set primary color (important for Wear 2.0 Notifications) + .setColor(getResources().getColor(R.color.colorPrimary)) + + // SIDE NOTE: Auto-bundling is enabled for 4 or more notifications on API 24+ (N+) + // devices and all Android Wear devices. If you have more than one notification and + // you prefer a different summary notification, set a group key and create a + // summary notification via + // .setGroupSummary(true) + // .setGroup(GROUP_KEY_YOUR_NAME_HERE) + + // Number of new notifications for API <24 (M and below) devices + .setSubText(Integer.toString(messagingStyleCommsAppData.getNumberOfNewMessages())) + + .addAction(replyAction) + .setCategory(Notification.CATEGORY_MESSAGE) + .setPriority(Notification.PRIORITY_HIGH) + + // Hides content on the lock-screen + .setVisibility(Notification.VISIBILITY_PRIVATE) + + // Adds multiple pages for easy consumption on a wear device. + .extend(wearableExtenderForWearVersion1); + + // If the phone is in "Do not disturb mode, the user will still be notified if + // the sender(s) is starred as a favorite. + for (String name : messagingStyleCommsAppData.getParticipants()) { + notificationCompatBuilder.addPerson(name); + } + + Notification notification = notificationCompatBuilder.build(); + mNotificationManagerCompat.notify(NOTIFICATION_ID, notification); + } + + /** + * Helper method for the SnackBar action, i.e., if the user has this application's notifications + * disabled, this opens up the dialog to turn them back on after the user requests a + * Notification launch. + * + * IMPORTANT NOTE: You should not do this action unless the user takes an action to see your + * Notifications like this sample demonstrates. Spamming users to re-enable your notifications + * is a bad idea. + */ + private void openNotificationSettingsForApp() { + // Links to this app's notification settings + Intent intent = new Intent(); + intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS"); + intent.putExtra("app_package", getPackageName()); + intent.putExtra("app_uid", getApplicationInfo().uid); + startActivity(intent); + } +}
\ No newline at end of file diff --git a/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/handlers/BigPictureSocialIntentService.java b/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/handlers/BigPictureSocialIntentService.java new file mode 100644 index 000000000..470eedb08 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/handlers/BigPictureSocialIntentService.java @@ -0,0 +1,228 @@ +/* +Copyright 2016 The Android Open Source Project + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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.wearable.wear.wearnotifications.handlers; + +import android.app.IntentService; +import android.app.Notification; +import android.app.PendingIntent; +import android.content.Intent; +import android.graphics.BitmapFactory; +import android.os.Build; +import android.os.Bundle; +import android.support.v4.app.NotificationCompat.BigPictureStyle; +import android.support.v4.app.NotificationManagerCompat; +import android.support.v4.app.RemoteInput; +import android.support.v4.app.TaskStackBuilder; +import android.support.v7.app.NotificationCompat; +import android.util.Log; + +import com.example.android.wearable.wear.wearnotifications.GlobalNotificationBuilder; +import com.example.android.wearable.wear.wearnotifications.MainActivity; +import com.example.android.wearable.wear.wearnotifications.R; +import com.example.android.wearable.wear.wearnotifications.mock.MockDatabase; + +/** + * Asynchronously handles updating social app posts (and active Notification) with comments from + * user. Notification for social app use BigPictureStyle. + */ +public class BigPictureSocialIntentService extends IntentService { + + private static final String TAG = "BigPictureService"; + + public static final String ACTION_COMMENT = + "com.example.android.wearable.wear.wearnotifications.handlers.action.COMMENT"; + + public static final String EXTRA_COMMENT = + "com.example.android.wearable.wear.wearnotifications.handlers.extra.COMMENT"; + + public BigPictureSocialIntentService() { + super("BigPictureSocialIntentService"); + } + + @Override + protected void onHandleIntent(Intent intent) { + Log.d(TAG, "onHandleIntent(): " + intent); + + if (intent != null) { + final String action = intent.getAction(); + if (ACTION_COMMENT.equals(action)) { + handleActionComment(getMessage(intent)); + } + } + } + + /** + * Handles action for adding a comment from the notification. + */ + private void handleActionComment(CharSequence comment) { + Log.d(TAG, "handleActionComment(): " + comment); + + if (comment != null) { + + // TODO: Asynchronously save your message to Database and servers. + + /* + * You have two options for updating your notification (this class uses approach #2): + * + * 1. Use a new NotificationCompatBuilder to create the Notification. This approach + * requires you to get *ALL* the information that existed in the previous + * Notification (and updates) and pass it to the builder. This is the approach used in + * the MainActivity. + * + * 2. Use the original NotificationCompatBuilder to create the Notification. This + * approach requires you to store a reference to the original builder. The benefit is + * you only need the new/updated information. In our case, the comment from the user + * regarding the post (which we already have here). + * + * IMPORTANT NOTE: You shouldn't save/modify the resulting Notification object using + * its member variables and/or legacy APIs. If you want to retain anything from update + * to update, retain the Builder as option 2 outlines. + */ + + // Retrieves NotificationCompat.Builder used to create initial Notification + NotificationCompat.Builder notificationCompatBuilder = + GlobalNotificationBuilder.getNotificationCompatBuilderInstance(); + + // Recreate builder from persistent state if app process is killed + if (notificationCompatBuilder == null) { + // Note: New builder set globally in the method + notificationCompatBuilder = recreateBuilderWithBigPictureStyle(); + } + + // Updates active Notification + Notification updatedNotification = notificationCompatBuilder + // Adds a line and comment below content in Notification + .setRemoteInputHistory(new CharSequence[]{comment}) + .build(); + + // Pushes out the updated Notification + NotificationManagerCompat notificationManagerCompat = + NotificationManagerCompat.from(getApplicationContext()); + notificationManagerCompat.notify(MainActivity.NOTIFICATION_ID, updatedNotification); + } + } + + /* + * Extracts CharSequence created from the RemoteInput associated with the Notification. + */ + private CharSequence getMessage(Intent intent) { + Bundle remoteInput = RemoteInput.getResultsFromIntent(intent); + if (remoteInput != null) { + return remoteInput.getCharSequence(EXTRA_COMMENT); + } + return null; + } + + /* + * This recreates the notification from the persistent state in case the app process was killed. + * It is basically the same code for creating the Notification from MainActivity. + */ + private NotificationCompat.Builder recreateBuilderWithBigPictureStyle() { + + // Main steps for building a BIG_PICTURE_STYLE notification (for more detailed comments on + // building this notification, check MainActivity.java): + // 0. Get your data + // 1. Build the BIG_PICTURE_STYLE + // 2. Set up main Intent for notification + // 3. Set up RemoteInput, so users can input (keyboard and voice) from notification + // 4. Build and issue the notification + + // 0. Get your data (everything unique per Notification) + MockDatabase.BigPictureStyleSocialAppData bigPictureStyleSocialAppData = + MockDatabase.getBigPictureStyleData(); + + // 1. Build the BIG_PICTURE_STYLE + BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle() + .bigPicture( + BitmapFactory.decodeResource( + getResources(), + bigPictureStyleSocialAppData.getBigImage())) + .setBigContentTitle(bigPictureStyleSocialAppData.getBigContentTitle()) + .setSummaryText(bigPictureStyleSocialAppData.getSummaryText()); + + // 2. Set up main Intent for notification + Intent mainIntent = new Intent(this, BigPictureSocialMainActivity.class); + + TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); + stackBuilder.addParentStack(BigPictureSocialMainActivity.class); + stackBuilder.addNextIntent(mainIntent); + + PendingIntent mainPendingIntent = + PendingIntent.getActivity( + this, + 0, + mainIntent, + PendingIntent.FLAG_UPDATE_CURRENT + ); + + // 3. Set up RemoteInput, so users can input (keyboard and voice) from notification + String replyLabel = getString(R.string.reply_label); + RemoteInput remoteInput = + new RemoteInput.Builder(BigPictureSocialIntentService.EXTRA_COMMENT) + .setLabel(replyLabel) + .setChoices(bigPictureStyleSocialAppData.getPossiblePostResponses()) + .build(); + + PendingIntent replyActionPendingIntent; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + Intent intent = new Intent(this, BigPictureSocialIntentService.class); + intent.setAction(BigPictureSocialIntentService.ACTION_COMMENT); + replyActionPendingIntent = PendingIntent.getService(this, 0, intent, 0); + + } else { + replyActionPendingIntent = mainPendingIntent; + } + + NotificationCompat.Action replyAction = + new NotificationCompat.Action.Builder( + R.drawable.ic_reply_white_18dp, + replyLabel, + replyActionPendingIntent) + .addRemoteInput(remoteInput) + .build(); + + // 4. Build and issue the notification + NotificationCompat.Builder notificationCompatBuilder = + new NotificationCompat.Builder(getApplicationContext()); + + GlobalNotificationBuilder.setNotificationCompatBuilderInstance(notificationCompatBuilder); + + notificationCompatBuilder + .setStyle(bigPictureStyle) + .setContentTitle(bigPictureStyleSocialAppData.getContentTitle()) + .setContentText(bigPictureStyleSocialAppData.getContentText()) + .setSmallIcon(R.drawable.ic_launcher) + .setLargeIcon(BitmapFactory.decodeResource( + getResources(), + R.drawable.ic_person_black_48dp)) + .setContentIntent(mainPendingIntent) + .setColor(getResources().getColor(R.color.colorPrimary)) + .setSubText(Integer.toString(1)) + .addAction(replyAction) + .setCategory(Notification.CATEGORY_SOCIAL) + .setPriority(Notification.PRIORITY_HIGH) + .setVisibility(Notification.VISIBILITY_PRIVATE); + + // If the phone is in "Do not disturb mode, the user will still be notified if + // the sender(s) is starred as a favorite. + for (String name : bigPictureStyleSocialAppData.getParticipants()) { + notificationCompatBuilder.addPerson(name); + } + + return notificationCompatBuilder; + } +}
\ No newline at end of file diff --git a/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/handlers/BigPictureSocialMainActivity.java b/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/handlers/BigPictureSocialMainActivity.java new file mode 100644 index 000000000..f9e13c24b --- /dev/null +++ b/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/handlers/BigPictureSocialMainActivity.java @@ -0,0 +1,45 @@ +/* +Copyright 2016 The Android Open Source Project + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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.wearable.wear.wearnotifications.handlers; + +import android.app.Activity; +import android.app.NotificationManager; +import android.content.Context; +import android.os.Bundle; + +import com.example.android.wearable.wear.wearnotifications.MainActivity; +import com.example.android.wearable.wear.wearnotifications.R; + +/** + * Template class meant to include functionality for your Social App. (This project's main focus + * is on Notification Styles.) + */ +public class BigPictureSocialMainActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_big_picture_main); + + // Cancel Notification + NotificationManager notificationManager = + (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + + notificationManager.cancel(MainActivity.NOTIFICATION_ID); + + // TODO: Handle and display social post from your database + } +}
\ No newline at end of file diff --git a/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/handlers/BigTextIntentService.java b/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/handlers/BigTextIntentService.java new file mode 100644 index 000000000..8f6664db7 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/handlers/BigTextIntentService.java @@ -0,0 +1,206 @@ +/* +Copyright 2016 The Android Open Source Project + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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.wearable.wear.wearnotifications.handlers; + +import android.app.IntentService; +import android.app.Notification; +import android.app.PendingIntent; +import android.content.Intent; +import android.graphics.BitmapFactory; +import android.support.v4.app.NotificationCompat.BigTextStyle; +import android.support.v4.app.NotificationManagerCompat; +import android.support.v7.app.NotificationCompat; +import android.util.Log; + +import com.example.android.wearable.wear.wearnotifications.GlobalNotificationBuilder; +import com.example.android.wearable.wear.wearnotifications.MainActivity; +import com.example.android.wearable.wear.wearnotifications.R; +import com.example.android.wearable.wear.wearnotifications.mock.MockDatabase; + +import java.util.concurrent.TimeUnit; + +/** + * Asynchronously handles snooze and dismiss actions for reminder app (and active Notification). + * Notification for for reminder app uses BigTextStyle. + */ +public class BigTextIntentService extends IntentService { + + private static final String TAG = "BigTextService"; + + public static final String ACTION_DISMISS = + "com.example.android.wearable.wear.wearnotifications.handlers.action.DISMISS"; + public static final String ACTION_SNOOZE = + "com.example.android.wearable.wear.wearnotifications.handlers.action.SNOOZE"; + + private static final long SNOOZE_TIME = TimeUnit.SECONDS.toMillis(5); + + public BigTextIntentService() { + super("BigTextIntentService"); + } + + @Override + protected void onHandleIntent(Intent intent) { + Log.d(TAG, "onHandleIntent(): " + intent); + + if (intent != null) { + final String action = intent.getAction(); + if (ACTION_DISMISS.equals(action)) { + handleActionDismiss(); + } else if (ACTION_SNOOZE.equals(action)) { + handleActionSnooze(); + } + } + } + + /** + * Handles action Dismiss in the provided background thread. + */ + private void handleActionDismiss() { + Log.d(TAG, "handleActionDismiss()"); + + NotificationManagerCompat notificationManagerCompat = + NotificationManagerCompat.from(getApplicationContext()); + notificationManagerCompat.cancel(MainActivity.NOTIFICATION_ID); + } + + /** + * Handles action Snooze in the provided background thread. + */ + private void handleActionSnooze() { + Log.d(TAG, "handleActionSnooze()"); + + // You could use NotificationManager.getActiveNotifications() if you are targeting SDK 23 + // and above, but we are targeting devices with lower SDK API numbers, so we saved the + // builder globally and get the notification back to recreate it later. + + NotificationCompat.Builder notificationCompatBuilder = + GlobalNotificationBuilder.getNotificationCompatBuilderInstance(); + + // Recreate builder from persistent state if app process is killed + if (notificationCompatBuilder == null) { + // Note: New builder set globally in the method + notificationCompatBuilder = recreateBuilderWithBigTextStyle(); + } + + Notification notification; + notification = notificationCompatBuilder.build(); + + + if (notification != null) { + NotificationManagerCompat notificationManagerCompat = + NotificationManagerCompat.from(getApplicationContext()); + + notificationManagerCompat.cancel(MainActivity.NOTIFICATION_ID); + + try { + Thread.sleep(SNOOZE_TIME); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } + notificationManagerCompat.notify(MainActivity.NOTIFICATION_ID, notification); + } + + } + + /* + * This recreates the notification from the persistent state in case the app process was killed. + * It is basically the same code for creating the Notification from MainActivity. + */ + private NotificationCompat.Builder recreateBuilderWithBigTextStyle() { + + // Main steps for building a BIG_TEXT_STYLE notification (for more detailed comments on + // building this notification, check MainActivity.java):: + // 0. Get your data + // 1. Build the BIG_TEXT_STYLE + // 2. Set up main Intent for notification + // 3. Create additional Actions for the Notification + // 4. Build and issue the notification + + // 0. Get your data + MockDatabase.BigTextStyleReminderAppData bigTextData = MockDatabase.getBigTextStyleData(); + + // 1. Build the BIG_TEXT_STYLE + BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle() + .bigText(bigTextData.getBigText()) + .setBigContentTitle(bigTextData.getBigContentTitle()) + .setSummaryText(bigTextData.getSummaryText()); + + + // 2. Set up main Intent for notification + Intent notifyIntent = new Intent(this, BigTextMainActivity.class); + notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + + PendingIntent notifyPendingIntent = + PendingIntent.getActivity( + this, + 0, + notifyIntent, + PendingIntent.FLAG_UPDATE_CURRENT + ); + + + // 3. Create additional Actions (Intents) for the Notification + + // Snooze Action + Intent snoozeIntent = new Intent(this, BigTextIntentService.class); + snoozeIntent.setAction(BigTextIntentService.ACTION_SNOOZE); + + PendingIntent snoozePendingIntent = PendingIntent.getService(this, 0, snoozeIntent, 0); + NotificationCompat.Action snoozeAction = + new NotificationCompat.Action.Builder( + R.drawable.ic_alarm_white_48dp, + "Snooze", + snoozePendingIntent) + .build(); + + + // Dismiss Action + Intent dismissIntent = new Intent(this, BigTextIntentService.class); + dismissIntent.setAction(BigTextIntentService.ACTION_DISMISS); + + PendingIntent dismissPendingIntent = PendingIntent.getService(this, 0, dismissIntent, 0); + NotificationCompat.Action dismissAction = + new NotificationCompat.Action.Builder( + R.drawable.ic_cancel_white_48dp, + "Dismiss", + dismissPendingIntent) + .build(); + + // 4. Build and issue the notification + NotificationCompat.Builder notificationCompatBuilder = + new NotificationCompat.Builder(getApplicationContext()); + + GlobalNotificationBuilder.setNotificationCompatBuilderInstance(notificationCompatBuilder); + + notificationCompatBuilder + .setStyle(bigTextStyle) + .setContentTitle(bigTextData.getContentTitle()) + .setContentText(bigTextData.getContentText()) + .setSmallIcon(R.drawable.ic_launcher) + .setLargeIcon(BitmapFactory.decodeResource( + getResources(), + R.drawable.ic_alarm_white_48dp)) + .setContentIntent(notifyPendingIntent) + .setColor(getResources().getColor(R.color.colorPrimary)) + .setCategory(Notification.CATEGORY_REMINDER) + .setPriority(Notification.PRIORITY_HIGH) + .setVisibility(Notification.VISIBILITY_PUBLIC) + .addAction(snoozeAction) + .addAction(dismissAction); + + return notificationCompatBuilder; + } +}
\ No newline at end of file diff --git a/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/handlers/BigTextMainActivity.java b/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/handlers/BigTextMainActivity.java new file mode 100644 index 000000000..92ae257ab --- /dev/null +++ b/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/handlers/BigTextMainActivity.java @@ -0,0 +1,45 @@ +/* +Copyright 2016 The Android Open Source Project + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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.wearable.wear.wearnotifications.handlers; + +import android.app.Activity; +import android.app.NotificationManager; +import android.content.Context; +import android.os.Bundle; + +import com.example.android.wearable.wear.wearnotifications.MainActivity; +import com.example.android.wearable.wear.wearnotifications.R; + +/** + * Template class meant to include functionality for your Reminder/Alarm App. (This project's main + * focus is on Notification Styles.) + */ +public class BigTextMainActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_big_text_main); + + // Cancel Notification + NotificationManager notificationManager = + (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + + notificationManager.cancel(MainActivity.NOTIFICATION_ID); + + // TODO: Handle and display reminder from your database + } +}
\ No newline at end of file diff --git a/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/handlers/InboxMainActivity.java b/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/handlers/InboxMainActivity.java new file mode 100644 index 000000000..403874666 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/handlers/InboxMainActivity.java @@ -0,0 +1,45 @@ +/* +Copyright 2016 The Android Open Source Project + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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.wearable.wear.wearnotifications.handlers; + +import android.app.Activity; +import android.app.NotificationManager; +import android.content.Context; +import android.os.Bundle; + +import com.example.android.wearable.wear.wearnotifications.MainActivity; +import com.example.android.wearable.wear.wearnotifications.R; + +/** + * Template class meant to include functionality for your email app. (This project's main focus + * is on Notification Styles.) + */ +public class InboxMainActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_inbox_main); + + // Cancel Notification + NotificationManager notificationManager = + (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + + notificationManager.cancel(MainActivity.NOTIFICATION_ID); + + // TODO: Handle and display email from your database + } +}
\ No newline at end of file diff --git a/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/handlers/MessagingIntentService.java b/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/handlers/MessagingIntentService.java new file mode 100644 index 000000000..6d30c4f20 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/handlers/MessagingIntentService.java @@ -0,0 +1,262 @@ +/* +Copyright 2016 The Android Open Source Project + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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.wearable.wear.wearnotifications.handlers; + +import android.app.IntentService; +import android.app.Notification; +import android.app.PendingIntent; +import android.content.Intent; +import android.graphics.BitmapFactory; +import android.os.Build; +import android.os.Bundle; +import android.support.v4.app.NotificationCompat.MessagingStyle; +import android.support.v4.app.NotificationManagerCompat; +import android.support.v4.app.RemoteInput; +import android.support.v4.app.TaskStackBuilder; +import android.support.v7.app.NotificationCompat; +import android.util.Log; + +import com.example.android.wearable.wear.wearnotifications.GlobalNotificationBuilder; +import com.example.android.wearable.wear.wearnotifications.MainActivity; +import com.example.android.wearable.wear.wearnotifications.R; +import com.example.android.wearable.wear.wearnotifications.mock.MockDatabase; + +/** + * Asynchronously handles updating messaging app posts (and active Notification) with replies from + * user in a conversation. Notification for social app use MessagingStyle. + */ +public class MessagingIntentService extends IntentService { + + private static final String TAG = "MessagingIntentService"; + + public static final String ACTION_REPLY = + "com.example.android.wearable.wear.wearnotifications.handlers.action.REPLY"; + + public static final String EXTRA_REPLY = + "com.example.android.wearable.wear.wearnotifications.handlers.extra.REPLY"; + + + public MessagingIntentService() { + super("MessagingIntentService"); + } + + @Override + protected void onHandleIntent(Intent intent) { + Log.d(TAG, "onHandleIntent(): " + intent); + + if (intent != null) { + final String action = intent.getAction(); + if (ACTION_REPLY.equals(action)) { + handleActionReply(getMessage(intent)); + } + } + } + + /** + * Handles action for replying to messages from the notification. + */ + private void handleActionReply(CharSequence replyCharSequence) { + Log.d(TAG, "handleActionReply(): " + replyCharSequence); + + if (replyCharSequence != null) { + + // TODO: Asynchronously save your message to Database and servers. + + /* + * You have two options for updating your notification (this class uses approach #2): + * + * 1. Use a new NotificationCompatBuilder to create the Notification. This approach + * requires you to get *ALL* the information that existed in the previous + * Notification (and updates) and pass it to the builder. This is the approach used in + * the MainActivity. + * + * 2. Use the original NotificationCompatBuilder to create the Notification. This + * approach requires you to store a reference to the original builder. The benefit is + * you only need the new/updated information. In our case, the reply from the user + * which we already have here. + * + * IMPORTANT NOTE: You shouldn't save/modify the resulting Notification object using + * its member variables and/or legacy APIs. If you want to retain anything from update + * to update, retain the Builder as option 2 outlines. + */ + + // Retrieves NotificationCompat.Builder used to create initial Notification + NotificationCompat.Builder notificationCompatBuilder = + GlobalNotificationBuilder.getNotificationCompatBuilderInstance(); + + // Recreate builder from persistent state if app process is killed + if (notificationCompatBuilder == null) { + // Note: New builder set globally in the method + notificationCompatBuilder = recreateBuilderWithMessagingStyle(); + } + + + // Since we are adding to the MessagingStyle, we need to first retrieve the + // current MessagingStyle from the Notification itself. + Notification notification = notificationCompatBuilder.build(); + MessagingStyle messagingStyle = + NotificationCompat.MessagingStyle + .extractMessagingStyleFromNotification(notification); + + // Add new message to the MessagingStyle + messagingStyle.addMessage(replyCharSequence, System.currentTimeMillis(), null); + + // Updates the Notification + notification = notificationCompatBuilder + .setStyle(messagingStyle) + .build(); + + // Pushes out the updated Notification + NotificationManagerCompat notificationManagerCompat = + NotificationManagerCompat.from(getApplicationContext()); + notificationManagerCompat.notify(MainActivity.NOTIFICATION_ID, notification); + } + } + + /* + * Extracts CharSequence created from the RemoteInput associated with the Notification. + */ + private CharSequence getMessage(Intent intent) { + Bundle remoteInput = RemoteInput.getResultsFromIntent(intent); + if (remoteInput != null) { + return remoteInput.getCharSequence(EXTRA_REPLY); + } + return null; + } + + /* + * This recreates the notification from the persistent state in case the app process was killed. + * It is basically the same code for creating the Notification from MainActivity. + */ + private NotificationCompat.Builder recreateBuilderWithMessagingStyle() { + + // Main steps for building a MESSAGING_STYLE notification (for more detailed comments on + // building this notification, check MainActivity.java):: + // 0. Get your data + // 1. Build the MESSAGING_STYLE + // 2. Add support for Wear 1.+ + // 3. Set up main Intent for notification + // 4. Set up RemoteInput (users can input directly from notification) + // 5. Build and issue the notification + + // 0. Get your data + MockDatabase.MessagingStyleCommsAppData messagingData = + MockDatabase.getMessagingStyleData(); + + // 1. Build the Notification.Style (MESSAGING_STYLE) + String contentTitle = messagingData.getContentTitle(); + + MessagingStyle messagingStyle = + new NotificationCompat.MessagingStyle(messagingData.getReplayName()) + .setConversationTitle(contentTitle); + + // Adds all Messages + // Note: Messages include the text, timestamp, and sender + for (MessagingStyle.Message message : messagingData.getMessages()) { + messagingStyle.addMessage(message); + } + + + // 2. Add support for Wear 1.+ + String fullMessageForWearVersion1 = messagingData.getFullConversation(); + + Notification chatHistoryForWearV1 = new NotificationCompat.Builder(getApplicationContext()) + .setStyle(new NotificationCompat.BigTextStyle().bigText(fullMessageForWearVersion1)) + .setContentTitle(contentTitle) + .setSmallIcon(R.drawable.ic_launcher) + .setContentText(fullMessageForWearVersion1) + .build(); + + NotificationCompat.WearableExtender wearableExtenderForWearVersion1 = + new NotificationCompat.WearableExtender() + .addPage(chatHistoryForWearV1); + + + + // 3. Set up main Intent for notification + Intent notifyIntent = new Intent(this, MessagingMainActivity.class); + + TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); + stackBuilder.addParentStack(MessagingMainActivity.class); + stackBuilder.addNextIntent(notifyIntent); + + PendingIntent mainPendingIntent = + PendingIntent.getActivity( + this, + 0, + notifyIntent, + PendingIntent.FLAG_UPDATE_CURRENT + ); + + + // 4. Set up RemoteInput, so users can input (keyboard and voice) from notification + String replyLabel = getString(R.string.reply_label); + RemoteInput remoteInput = new RemoteInput.Builder(MessagingIntentService.EXTRA_REPLY) + .setLabel(replyLabel) + .build(); + + PendingIntent replyActionPendingIntent; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + Intent intent = new Intent(this, MessagingIntentService.class); + intent.setAction(MessagingIntentService.ACTION_REPLY); + replyActionPendingIntent = PendingIntent.getService(this, 0, intent, 0); + + } else { + replyActionPendingIntent = mainPendingIntent; + } + + NotificationCompat.Action replyAction = + new NotificationCompat.Action.Builder( + R.drawable.ic_reply_white_18dp, + replyLabel, + replyActionPendingIntent) + .addRemoteInput(remoteInput) + // Allows system to generate replies by context of conversation + .setAllowGeneratedReplies(true) + .build(); + + + // 5. Build and issue the notification + NotificationCompat.Builder notificationCompatBuilder = + new NotificationCompat.Builder(getApplicationContext()); + + GlobalNotificationBuilder.setNotificationCompatBuilderInstance(notificationCompatBuilder); + + notificationCompatBuilder + .setStyle(messagingStyle) + .setContentTitle(contentTitle) + .setContentText(messagingData.getContentText()) + .setSmallIcon(R.drawable.ic_launcher) + .setLargeIcon(BitmapFactory.decodeResource( + getResources(), + R.drawable.ic_person_black_48dp)) + .setContentIntent(mainPendingIntent) + .setColor(getResources().getColor(R.color.colorPrimary)) + .setSubText(Integer.toString(messagingData.getNumberOfNewMessages())) + .addAction(replyAction) + .setCategory(Notification.CATEGORY_MESSAGE) + .setPriority(Notification.PRIORITY_HIGH) + .setVisibility(Notification.VISIBILITY_PRIVATE) + .extend(wearableExtenderForWearVersion1); + + for (String name : messagingData.getParticipants()) { + notificationCompatBuilder.addPerson(name); + } + + return notificationCompatBuilder; + } +}
\ No newline at end of file diff --git a/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/handlers/MessagingMainActivity.java b/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/handlers/MessagingMainActivity.java new file mode 100644 index 000000000..77d9d0cc7 --- /dev/null +++ b/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/handlers/MessagingMainActivity.java @@ -0,0 +1,47 @@ +/* +Copyright 2016 The Android Open Source Project + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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.wearable.wear.wearnotifications.handlers; + +import android.app.Activity; +import android.app.NotificationManager; +import android.content.Context; +import android.os.Bundle; + +import com.example.android.wearable.wear.wearnotifications.MainActivity; +import com.example.android.wearable.wear.wearnotifications.R; + +/** + * Template class meant to include functionality for your Messaging App. (This project's main focus + * is on Notification Styles.) + */ +public class MessagingMainActivity extends Activity { + + private static final String TAG = "MessagingMainActivity"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_messaging_main); + + // Cancel Notification + NotificationManager notificationManager = + (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + + notificationManager.cancel(MainActivity.NOTIFICATION_ID); + + // TODO: Handle and display message/conversation from your database + } +}
\ No newline at end of file diff --git a/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/mock/MockDatabase.java b/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/mock/MockDatabase.java new file mode 100644 index 000000000..b552f6d3a --- /dev/null +++ b/samples/browseable/WearNotifications/Application/src/com.example.android.wearable.wear.wearnotifications/mock/MockDatabase.java @@ -0,0 +1,400 @@ +package com.example.android.wearable.wear.wearnotifications.mock; + +import android.support.v4.app.NotificationCompat.MessagingStyle; + +import com.example.android.wearable.wear.wearnotifications.R; + +import java.util.ArrayList; + +/** + * Mock data for each of the Notification Style Demos. + */ +public final class MockDatabase { + + public static BigTextStyleReminderAppData getBigTextStyleData() { + return BigTextStyleReminderAppData.getInstance(); + } + + public static BigPictureStyleSocialAppData getBigPictureStyleData() { + return BigPictureStyleSocialAppData.getInstance(); + } + + public static InboxStyleEmailAppData getInboxStyleData() { + return InboxStyleEmailAppData.getInstance(); + } + + public static MessagingStyleCommsAppData getMessagingStyleData() { + return MessagingStyleCommsAppData.getInstance(); + } + + /** + * Represents data needed for BigTextStyle Notification. + */ + public static class BigTextStyleReminderAppData { + + private static BigTextStyleReminderAppData sInstance = null; + + // Standard notification values + private String mContentTitle; + private String mContentText; + + // Style notification values + private String mBigContentTitle; + private String mBigText; + private String mSummaryText; + + + public static BigTextStyleReminderAppData getInstance() { + if (sInstance == null) { + sInstance = getSync(); + } + + return sInstance; + } + + private static synchronized BigTextStyleReminderAppData getSync() { + if (sInstance == null) { + sInstance = new BigTextStyleReminderAppData(); + } + + return sInstance; + } + + private BigTextStyleReminderAppData() { + // Standard Notification values + // Title for API <16 (4.0 and below) devices + mContentTitle = "Don't forget to..."; + // Content for API <24 (4.0 and below) devices + mContentText = "Feed Dogs and check garage!"; + + // BigText Style Notification values + mBigContentTitle = "Don't forget to..."; + mBigText = "... feed the dogs before you leave for work, and check the garage to " + + "make sure the door is closed."; + mSummaryText = "Dogs and Garage"; + } + public String getContentTitle() { + return mContentTitle; + } + + public String getContentText() { + return mContentText; + } + + public String getBigContentTitle() { + return mBigContentTitle; + } + + public String getBigText() { + return mBigText; + } + + public String getSummaryText() { + return mSummaryText; + } + + @Override + public String toString() { + return getBigContentTitle() + getBigText(); + } + } + + /** + * Represents data needed for BigPictureStyle Notification. + */ + public static class BigPictureStyleSocialAppData { + private static BigPictureStyleSocialAppData sInstance = null; + + // Standard notification values + private String mContentTitle; + private String mContentText; + + // Style notification values + private int mBigImage; + private String mBigContentTitle; + private String mSummaryText; + + private CharSequence[] mPossiblePostResponses; + + private ArrayList<String> mParticipants; + + + public static BigPictureStyleSocialAppData getInstance() { + if (sInstance == null) { + sInstance = getSync(); + } + return sInstance; + } + + private static synchronized BigPictureStyleSocialAppData getSync() { + if (sInstance == null) { + sInstance = new BigPictureStyleSocialAppData(); + } + + return sInstance; + } + + private BigPictureStyleSocialAppData() { + // Standard Notification values + // Title/Content for API <16 (4.0 and below) devices + mContentTitle = "Bob's Post"; + mContentText = "[Picture] Like my shot of Earth?"; + + // Style notification values + mBigImage = R.drawable.earth; + mBigContentTitle = "Bob's Post"; + mSummaryText = "Like my shot of Earth?"; + + // This would be possible responses based on the contents of the post + mPossiblePostResponses = new CharSequence[]{"Yes", "No", "Maybe?"}; + + mParticipants = new ArrayList<>(); + mParticipants.add("Bob Smith"); + } + + public String getContentTitle() { + return mContentTitle; + } + + public String getContentText() { + return mContentText; + } + + public int getBigImage() { + return mBigImage; + } + + public String getBigContentTitle() { + return mBigContentTitle; + } + + public String getSummaryText() { + return mSummaryText; + } + + public CharSequence[] getPossiblePostResponses() { + return mPossiblePostResponses; + } + + public ArrayList<String> getParticipants() { + return mParticipants; + } + + @Override + public String toString() { + return getContentTitle() + " - " + getContentText(); + } + } + + /** + * Represents data needed for InboxStyle Notification. + */ + public static class InboxStyleEmailAppData { + private static InboxStyleEmailAppData sInstance = null; + + // Standard notification values + private String mContentTitle; + private String mContentText; + private int mNumberOfNewEmails; + + // Style notification values + private String mBigContentTitle; + private String mSummaryText; + private ArrayList<String> mIndividualEmailSummary; + + private ArrayList<String> mParticipants; + + public static InboxStyleEmailAppData getInstance() { + if (sInstance == null) { + sInstance = getSync(); + } + return sInstance; + } + + private static synchronized InboxStyleEmailAppData getSync() { + if (sInstance == null) { + sInstance = new InboxStyleEmailAppData(); + } + + return sInstance; + } + + private InboxStyleEmailAppData() { + // Standard Notification values + // Title/Content for API <16 (4.0 and below) devices + mContentTitle = "5 new emails"; + mContentText = "from Jane, Jay, Alex +2 more"; + mNumberOfNewEmails = 5; + + // Style notification values + mBigContentTitle = "5 new emails from Jane, Jay, Alex +2"; + mSummaryText = "New emails"; + + // Add each summary line of the new emails, you can add up to 5 + mIndividualEmailSummary = new ArrayList<>(); + mIndividualEmailSummary.add("Jane Faab - Launch Party is here..."); + mIndividualEmailSummary.add("Jay Walker - There's a turtle on the server!"); + mIndividualEmailSummary.add("Alex Chang - Check this out..."); + mIndividualEmailSummary.add("Jane Johns - Check in code?"); + mIndividualEmailSummary.add("John Smith - Movies later...."); + + // If the phone is in "Do not disturb mode, the user will still be notified if + // the user(s) is starred as a favorite. + mParticipants = new ArrayList<>(); + mParticipants.add("Jane Faab"); + mParticipants.add("Jay Walker"); + mParticipants.add("Alex Chang"); + mParticipants.add("Jane Johns"); + mParticipants.add("John Smith"); + } + + public String getContentTitle() { + return mContentTitle; + } + + public String getContentText() { + return mContentText; + } + + public int getNumberOfNewEmails() { + return mNumberOfNewEmails; + } + + public String getBigContentTitle() { + return mBigContentTitle; + } + + public String getSummaryText() { + return mSummaryText; + } + + public ArrayList<String> getIndividualEmailSummary() { + return mIndividualEmailSummary; + } + + public ArrayList<String> getParticipants() { + return mParticipants; + } + + @Override + public String toString() { + return getContentTitle() + " " + getContentText(); + } + } + + /** + * Represents data needed for MessagingStyle Notification. + */ + public static class MessagingStyleCommsAppData { + + private static MessagingStyleCommsAppData sInstance = null; + + // Standard notification values + private String mContentTitle; + private String mContentText; + + // Style notification values + private ArrayList<MessagingStyle.Message> mMessages; + // Basically, String of all mMessages + private String mFullConversation; + // Name preferred when replying to chat + private String mReplayName; + private int mNumberOfNewMessages; + private ArrayList<String> mParticipants; + + public static MessagingStyleCommsAppData getInstance() { + if (sInstance == null) { + sInstance = getSync(); + } + return sInstance; + } + + private static synchronized MessagingStyleCommsAppData getSync() { + if (sInstance == null) { + sInstance = new MessagingStyleCommsAppData(); + } + + return sInstance; + } + + private MessagingStyleCommsAppData() { + // Standard notification values + // Content for API <24 (M and below) devices + mContentTitle = "2 Messages w/ Famous McFamously"; + mContentText = "Dude! ... You know I am a Pesce-pescetarian. :P"; + + // Style notification values + + // For each message, you need the timestamp, in this case, we are using arbitrary ones. + long currentTime = System.currentTimeMillis(); + + mMessages = new ArrayList<>(); + mMessages.add(new MessagingStyle.Message( + "What are you doing tonight?", currentTime - 4000, "Famous")); + mMessages.add(new MessagingStyle.Message( + "I don't know, dinner maybe?", currentTime - 3000, null)); + mMessages.add(new MessagingStyle.Message( + "Sounds good.", currentTime - 2000, "Famous")); + mMessages.add(new MessagingStyle.Message( + "How about BBQ?", currentTime - 1000, null)); + // Last two are the newest message (2) from friend + mMessages.add(new MessagingStyle.Message( + "Dude!", currentTime, "Famous")); + mMessages.add(new MessagingStyle.Message( + "You know I am a Pesce-pescetarian. :P", currentTime, "Famous")); + + + // String version of the mMessages above + mFullConversation = "Famous: What are you doing tonight?\n\n" + + "Me: I don't know, dinner maybe?\n\n" + + "Famous: Sounds good.\n\n" + + "Me: How about BBQ?\n\n" + + "Famous: Dude!\n\n" + + "Famous: You know I am a Pesce-pescetarian. :P\n\n"; + + mNumberOfNewMessages = 2; + + // Name preferred when replying to chat + mReplayName = "Me"; + + // If the phone is in "Do not disturb mode, the user will still be notified if + // the user(s) is starred as a favorite. + mParticipants = new ArrayList<>(); + mParticipants.add("Famous McFamously"); + + } + + public String getContentTitle() { + return mContentTitle; + } + + public String getContentText() { + return mContentText; + } + + public ArrayList<MessagingStyle.Message> getMessages() { + return mMessages; + } + + public String getFullConversation() { + return mFullConversation; + } + + public String getReplayName() { + return mReplayName; + } + + public int getNumberOfNewMessages() { + return mNumberOfNewMessages; + } + + public ArrayList<String> getParticipants() { + return mParticipants; + } + + @Override + public String toString() { + return getFullConversation(); + } + } +}
\ No newline at end of file |