diff options
author | Xin Li <delphij@google.com> | 2017-12-06 11:52:06 -0800 |
---|---|---|
committer | Xin Li <delphij@google.com> | 2017-12-06 14:24:52 -0800 |
commit | c6afb36e77d24ebbad4a693ab8c5f66d66ea8e41 (patch) | |
tree | 43d8e691aeb3fc8ae219f0f119e5c33eb326cea5 | |
parent | 917af90df473a739aca62bc0404fa2f25977307d (diff) | |
parent | 811cfca9026ae98a15718a678d1089c9b7c6c63a (diff) | |
download | Messenger-c6afb36e77d24ebbad4a693ab8c5f66d66ea8e41.tar.gz |
DO NOT MERGE: Merge Oreo MR1 into masterandroid-wear-8.0.0_r1
Exempt-From-Owner-Approval: Changes already landed internally
Change-Id: I10a690d9f43a511569c94a9d0e4eb444d9ec0b9d
-rw-r--r-- | Android.mk | 4 | ||||
-rw-r--r-- | AndroidManifest.xml | 4 | ||||
-rw-r--r-- | res/anim/trans_bottom_in.xml | 32 | ||||
-rw-r--r-- | res/anim/trans_bottom_out.xml | 32 | ||||
-rw-r--r-- | res/drawable/circle_bg.xml | 24 | ||||
-rw-r--r-- | res/drawable/gradient_transparent.xml | 26 | ||||
-rw-r--r-- | res/drawable/ic_voice_out.xml | 29 | ||||
-rw-r--r-- | res/drawable/round_corner.xml | 29 | ||||
-rw-r--r-- | res/drawable/rounded_corner_btn_bg.xml | 25 | ||||
-rw-r--r-- | res/layout/play_message_layout.xml | 128 | ||||
-rw-r--r-- | res/values/dimens.xml | 3 | ||||
-rw-r--r-- | res/values/integers.xml | 26 | ||||
-rw-r--r-- | res/values/strings.xml | 10 | ||||
-rw-r--r-- | res/values/styles.xml | 38 | ||||
-rw-r--r-- | src/com/android/car/messenger/MapMessageMonitor.java | 218 | ||||
-rw-r--r-- | src/com/android/car/messenger/MessengerService.java | 17 | ||||
-rw-r--r-- | src/com/android/car/messenger/PlayMessageActivity.java | 237 |
17 files changed, 746 insertions, 136 deletions
@@ -14,6 +14,8 @@ # limitations under the License. # +ifneq ($(TARGET_BUILD_PDK), true) + LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) @@ -79,3 +81,5 @@ include $(BUILD_PREBUILT) ifeq (,$(ONE_SHOT_MAKEFILE)) include $(call all-makefiles-under,$(LOCAL_PATH)) endif + +endif diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 096e699..b0e4502 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -42,7 +42,9 @@ <category android:name="android.intent.category.APP_MESSAGING"/> </intent-filter> </activity> - <activity android:name=".PlayMessageActivity" android:exported="true"> + <activity android:name=".PlayMessageActivity" android:exported="true" + android:launchMode="singleTop" + android:theme="@style/FloatingWindow"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.APP_MESSAGING"/> diff --git a/res/anim/trans_bottom_in.xml b/res/anim/trans_bottom_in.xml new file mode 100644 index 0000000..0635de3 --- /dev/null +++ b/res/anim/trans_bottom_in.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2017 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<set xmlns:android="http://schemas.android.com/apk/res/android"> + <objectAnimator + android:interpolator="@android:interpolator/decelerate_quint" + android:valueFrom="100dp" + android:valueTo="0dp" + android:valueType="floatType" + android:propertyName="translationY" + android:duration="@integer/anim_time" /> + <objectAnimator + android:interpolator="@android:interpolator/decelerate_quint" + android:valueFrom="0.0" + android:valueTo="1.0" + android:valueType="floatType" + android:propertyName="alpha" + android:duration="@integer/anim_time" /> +</set>
\ No newline at end of file diff --git a/res/anim/trans_bottom_out.xml b/res/anim/trans_bottom_out.xml new file mode 100644 index 0000000..81295e8 --- /dev/null +++ b/res/anim/trans_bottom_out.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2017 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<set xmlns:android="http://schemas.android.com/apk/res/android"> + <objectAnimator + android:interpolator="@android:interpolator/decelerate_quint" + android:valueFrom="0dp" + android:valueTo="-100dp" + android:valueType="floatType" + android:propertyName="translationY" + android:duration="@integer/anim_time" /> + <objectAnimator + android:interpolator="@android:interpolator/decelerate_quint" + android:valueFrom="1.0" + android:valueTo="0.0" + android:valueType="floatType" + android:propertyName="alpha" + android:duration="@integer/anim_time" /> +</set>
\ No newline at end of file diff --git a/res/drawable/circle_bg.xml b/res/drawable/circle_bg.xml new file mode 100644 index 0000000..1770aab --- /dev/null +++ b/res/drawable/circle_bg.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2017 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="oval"> + <solid android:color="@color/car_blue_grey_900" /> + <size + android:height="@dimen/car_touch_target" + android:width="@dimen/car_touch_target" /> +</shape>
\ No newline at end of file diff --git a/res/drawable/gradient_transparent.xml b/res/drawable/gradient_transparent.xml new file mode 100644 index 0000000..369ccef --- /dev/null +++ b/res/drawable/gradient_transparent.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2017 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <gradient android:endColor="@android:color/transparent" + android:startColor="#88000000" + android:angle="90" + android:type="linear" + android:useLevel="true" + /> +</shape>
\ No newline at end of file diff --git a/res/drawable/ic_voice_out.xml b/res/drawable/ic_voice_out.xml new file mode 100644 index 0000000..a4a3c07 --- /dev/null +++ b/res/drawable/ic_voice_out.xml @@ -0,0 +1,29 @@ +<!-- + ~ Copyright (C) 2017 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> + +<vector android:height="24dp" android:viewportHeight="48.0" + android:viewportWidth="50.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> + <path android:fillColor="#00796B" android:pathData="M22,0h6v48h-6z" + android:strokeColor="#00000000" android:strokeWidth="1"/> + <path android:fillColor="#00796B" android:pathData="M33,10h6v28h-6z" + android:strokeColor="#00000000" android:strokeWidth="1"/> + <path android:fillColor="#00796B" android:pathData="M11,10h6v28h-6z" + android:strokeColor="#00000000" android:strokeWidth="1"/> + <path android:fillColor="#00796B" android:pathData="M0,19h6v10h-6z" + android:strokeColor="#00000000" android:strokeWidth="1"/> + <path android:fillColor="#00796B" android:pathData="M44,19h6v10h-6z" + android:strokeColor="#00000000" android:strokeWidth="1"/> +</vector> diff --git a/res/drawable/round_corner.xml b/res/drawable/round_corner.xml new file mode 100644 index 0000000..0b5dba7 --- /dev/null +++ b/res/drawable/round_corner.xml @@ -0,0 +1,29 @@ +<!-- + ~ Copyright (C) 2017 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + + <solid android:color="@color/car_card" /> + <padding + android:bottom="5dp" + android:left="5dp" + android:right="5dp" + android:top="5dp" /> + <corners android:topLeftRadius="20dp" + android:topRightRadius="20dp"/> + +</shape>
\ No newline at end of file diff --git a/res/drawable/rounded_corner_btn_bg.xml b/res/drawable/rounded_corner_btn_bg.xml new file mode 100644 index 0000000..dba56a6 --- /dev/null +++ b/res/drawable/rounded_corner_btn_bg.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2017 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <solid android:color="@color/car_blue_grey_900" /> + <corners android:radius="55dp"/> + <size + android:height="@dimen/car_touch_target" + android:width="@dimen/big_btn_bg_width" /> +</shape>
\ No newline at end of file diff --git a/res/layout/play_message_layout.xml b/res/layout/play_message_layout.xml index b6bc788..058414d 100644 --- a/res/layout/play_message_layout.xml +++ b/res/layout/play_message_layout.xml @@ -15,27 +15,119 @@ ~ limitations under the License --> -<!-- Eng mock, waiting for UX spec --> -<RelativeLayout +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/container" + android:orientation="vertical" + android:layout_gravity="bottom" + android:elevation="@dimen/car_card_view_elevation" + android:background="@drawable/round_corner" + android:animateLayoutChanges="true" + android:alpha="0" + android:layout_marginStart="@dimen/side_margin" + android:layout_marginEnd="@dimen/side_margin" android:layout_width="match_parent" - android:layout_height="match_parent" > - <TextView - android:id="@+id/play_pause_btn" - style="@style/CarBody1" - android:layout_centerInParent="true" - android:layout_width="wrap_content" - android:layout_height="wrap_content"> - </TextView> + android:layout_height="wrap_content"> + <GridLayout + android:id="@+id/message_container" + android:visibility="gone" + android:layout_weight="1" + android:layout_marginStart="@dimen/stream_card_keyline_3" + android:layout_marginEnd="@dimen/stream_card_keyline_3" + android:layout_height="0dp" + android:layout_width="match_parent" + android:useDefaultMargins="true" + android:alignmentMode="alignBounds" + android:columnOrderPreserved="false" + android:columnCount="4" + > + <TextView + android:id="@+id/emoji1" + style="@style/MessageEmoji"> + </TextView> + <TextView + android:id="@+id/emoji2" + style="@style/MessageEmoji"> + </TextView> + <TextView + android:id="@+id/emoji3" + style="@style/MessageEmoji"> + </TextView> + <TextView + android:id="@+id/emoji4" + style="@style/MessageEmoji"> + </TextView> + <TextView + android:id="@+id/emoji5" + style="@style/MessageEmoji"> + </TextView> + <TextView + android:id="@+id/canned_message" + style="@style/CarBody1.Light" + android:layout_column="1" + android:layout_rowSpan="1" + android:layout_columnSpan="3" + android:gravity="center" + android:textStyle="italic" + android:layout_gravity="center" + android:background="@drawable/rounded_corner_btn_bg" + android:text="@string/caned_message_driving_right_now" + android:layout_width="614dp" + android:layout_height="@dimen/car_touch_target"> + </TextView> + </GridLayout> <TextView - android:id="@+id/exit_btn" + android:id="@+id/reply_notice" style="@style/CarBody1" - android:text="Exit" - android:layout_centerHorizontal="true" - android:layout_alignParentBottom="true" - android:layout_marginBottom="100dp" - android:layout_width="wrap_content" - android:layout_height="wrap_content"> + android:layout_gravity="center" + android:gravity="center" + android:visibility="gone" + android:layout_width="match_parent" + android:layout_height="@dimen/single_line_item_height"> </TextView> -</RelativeLayout> + + <LinearLayout + android:id="@+id/voice_plate" + android:background="@color/car_card" + android:orientation="horizontal" + android:layout_width="match_parent" + android:layout_height="@dimen/single_line_item_height"> + <TextView + android:id="@+id/left_btn" + style="@style/CarBody1" + android:layout_weight="1" + android:gravity="center" + android:layout_gravity="center_vertical" + android:textAllCaps="true" + android:maxLines="1" + android:layout_marginStart="@dimen/stream_content_keyline_1" + android:layout_marginEnd="@dimen/voice_plate_button_margin" + android:layout_width="0dp" + android:layout_height="wrap_content"> + </TextView> + + <ImageView + android:id="@+id/voice_icon" + android:layout_width="@dimen/stream_button_icon_size" + android:layout_height="@dimen/stream_button_icon_size" + android:layout_gravity="center" + android:src="@drawable/ic_voice_out" + android:scaleType="fitCenter"> + </ImageView> + + <TextView + android:id="@+id/right_btn" + style="@style/CarBody1" + android:layout_weight="1" + android:gravity="center" + android:layout_gravity="center_vertical" + android:textAllCaps="true" + android:maxLines="1" + android:layout_marginStart="@dimen/voice_plate_button_margin" + android:layout_marginEnd="@dimen/stream_content_keyline_1" + android:layout_width="0dp" + android:layout_height="wrap_content"> + </TextView> + </LinearLayout> +</LinearLayout>
\ No newline at end of file diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 7308708..b0eafa5 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -16,4 +16,7 @@ --> <resources> <dimen name="notification_contact_photo_size">300dp</dimen> + <dimen name="voice_plate_button_margin">32dp</dimen> + <dimen name="big_btn_bg_width">614dp</dimen> + <dimen name="car_emoji_size">56dp</dimen> </resources> diff --git a/res/values/integers.xml b/res/values/integers.xml new file mode 100644 index 0000000..bb8aa4b --- /dev/null +++ b/res/values/integers.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2017 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> + +<resources> + <integer name="emoji_thumb_up">0x1F44D</integer> + <integer name="emoji_thumb_down">0x1F44E</integer> + <integer name="emoji_ok_hand_sign">0x1F44C</integer> + <integer name="emoji_heart">0x1F49B</integer> + <integer name="emoji_smiling_face">0x1F642</integer> + + <integer name="anim_time">1000</integer> +</resources>
\ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index 9509e86..66d69ad 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -23,14 +23,18 @@ </plurals> <string name="action_mute">Mute</string> + <string name="action_unmute">Unmute</string> <string name="action_play">Play</string> + <string name="action_repeat">Repeat</string> + <string name="action_reply">Reply</string> <string name="action_stop">Stop</string> - <string name="action_auto_reply">Reply: I\'m driving</string> - - <string name="auto_reply_message">I\'m driving right now</string> + <string name="action_close_messages">Close</string> <string name="auto_reply_failed_message">Unable to send reply. Please try again.</string> <string name="tts_sender_says">%s says</string> <string name="tts_failed_toast">Text playout failed!</string> + <string name="reply_message_display_template">\"%s\"</string> + <string name="caned_message_driving_right_now">Auto-reply: I’m driving.</string> + <string name="message_sent_notice">Reply sent to %s</string> </resources> diff --git a/res/values/styles.xml b/res/values/styles.xml new file mode 100644 index 0000000..c9ae141 --- /dev/null +++ b/res/values/styles.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2017 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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> + <!-- Pop up window that does not block interaction to other activity behind it. --> + <style name="FloatingWindow" parent="@android:style/Theme.Dialog"> + <item name="android:windowIsTranslucent">true</item> + <item name="android:windowBackground">@drawable/gradient_transparent</item> + <item name="android:background">@android:color/transparent</item> + <item name="android:backgroundDimEnabled">false</item> + <item name="android:windowCloseOnTouchOutside">true</item> + <item name="android:windowIsFloating">false</item> + <item name="android:windowNoTitle">true</item> + </style> + + <style name="MessageEmoji" parent="@style/CarBody1"> + <item name="android:background">@drawable/circle_bg</item> + <item name="android:textSize">@dimen/car_emoji_size</item> + <item name="android:gravity">center</item> + <item name="android:layout_gravity">center</item> + <item name="android:layout_columnWeight">1</item> + <item name="android:layout_rowWeight">1</item> + <item name="android:layout_height">@dimen/car_touch_target</item> + </style> +</resources>
\ No newline at end of file diff --git a/src/com/android/car/messenger/MapMessageMonitor.java b/src/com/android/car/messenger/MapMessageMonitor.java index 1d12ee9..b07d263 100644 --- a/src/com/android/car/messenger/MapMessageMonitor.java +++ b/src/com/android/car/messenger/MapMessageMonitor.java @@ -35,14 +35,14 @@ import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; -import android.media.Ringtone; -import android.media.RingtoneManager; +import android.media.AudioManager; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; import android.provider.ContactsContract; +import android.provider.Settings; import android.support.annotation.Nullable; -import android.telecom.PhoneAccount; +import android.text.TextUtils; import android.util.Log; import android.widget.Toast; @@ -79,6 +79,9 @@ class MapMessageMonitor { // reply or "upload" feature is indicated by the 3rd bit private static final int REPLY_FEATURE_POS = 3; + private static final int REQUEST_CODE_VOICE_PLATE = 1; + private static final int REQUEST_CODE_AUTO_REPLY = 2; + private static final int ACTION_COUNT = 2; private static final String TAG = "Messenger.MsgMonitor"; private static final boolean DBG = MessengerService.DBG; @@ -89,8 +92,9 @@ class MapMessageMonitor { private final Map<MessageKey, MapMessage> mMessages = new HashMap<>(); private final Map<SenderKey, NotificationInfo> mNotificationInfos = new HashMap<>(); private final TTSHelper mTTSHelper; - private final Ringtone mNotificationTone; private final HashMap<String, Boolean> mReplyFeatureMap = new HashMap<>(); + private final AudioManager mAudioManager; + private final AudioManager.OnAudioFocusChangeListener mNoOpAFChangeListener = (f) -> {}; MapMessageMonitor(Context context) { mContext = context; @@ -100,9 +104,7 @@ class MapMessageMonitor { (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); mTTSHelper = new TTSHelper(mContext); - // Fetch default notification ringtone. - Uri notificationUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); - mNotificationTone = RingtoneManager.getRingtone(mContext, notificationUri); + mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); } public boolean isPlaying() { @@ -115,7 +117,7 @@ class MapMessageMonitor { } try { MapMessage message = MapMessage.parseFrom(intent); - if (MessengerService.VDBG) { + if (MessengerService.DBG) { Log.v(TAG, "Parsed message: " + message); } MessageKey messageKey = new MessageKey(message); @@ -142,10 +144,6 @@ class MapMessageMonitor { mNotificationInfos.put(senderKey, notificationInfo); } notificationInfo.mMessageKeys.add(messageKey); - // Play notification when handling new message, if not muted. - if (!notificationInfo.muted) { - mNotificationTone.play(); - } updateNotificationFor(senderKey, notificationInfo); } @@ -153,23 +151,29 @@ class MapMessageMonitor { ContactsContract.PhoneLookup._ID }; - private static int getContactIdFromNumber(ContentResolver cr, String number) { - if (number == null || number.isEmpty()) { + private static int getContactIdFromName(ContentResolver cr, String name) { + if (DBG) { + Log.d(TAG, "getting contactId for: " + name); + } + if (TextUtils.isEmpty(name)) { return 0; } - Uri uri = Uri.withAppendedPath( - ContactsContract.PhoneLookup.CONTENT_FILTER_URI, - Uri.encode(number)); - Cursor cursor = cr.query(uri, CONTACT_ID, null, null, null); + String[] mSelectionArgs = { name }; + Cursor cursor = + cr.query( + ContactsContract.Contacts.CONTENT_URI, + CONTACT_ID, + ContactsContract.Contacts.DISPLAY_NAME_PRIMARY + " LIKE ?", + mSelectionArgs, + null); try { if (cursor != null && cursor.moveToFirst()) { int id = cursor.getInt(cursor.getColumnIndex(ContactsContract.PhoneLookup._ID)); return id; } - } - finally { + } finally { if (cursor != null) { cursor.close(); } @@ -187,11 +191,9 @@ class MapMessageMonitor { long lastReceivedTimeMs = mMessages.get(notificationInfo.mMessageKeys.getLast()).getReceivedTimeMs(); - String phoneNumber = notificationInfo.mSenderContactUri.substring( - (PhoneAccount.SCHEME_TEL + ":").length()); Uri photoUri = ContentUris.withAppendedId( - ContactsContract.Contacts.CONTENT_URI, getContactIdFromNumber( - mContext.getContentResolver(), phoneNumber)); + ContactsContract.Contacts.CONTENT_URI, getContactIdFromName( + mContext.getContentResolver(), notificationInfo.mSenderName)); if (DBG) { Log.d(TAG, "start Glide loading... " + photoUri); } @@ -219,22 +221,21 @@ class MapMessageMonitor { LetterTileDrawable letterTileDrawable = new LetterTileDrawable(mContext.getResources()); letterTileDrawable.setContactDetails( - notificationInfo.mSenderName, phoneNumber); + notificationInfo.mSenderName, notificationInfo.mSenderName); letterTileDrawable.setIsCircular(true); bitmap = letterTileDrawable.toBitmap( mContext.getResources().getDimensionPixelSize( R.dimen.notification_contact_photo_size)); } - Intent intent = new Intent(mContext, PlayMessageActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(PlayMessageActivity.MESSAGE_KEY, senderKey); - PendingIntent LaunchMessageActivityIntent = PendingIntent.getActivity( - mContext, 0, intent, 0); - - Notification.Builder builder = - new Notification.Builder( - mContext, NotificationChannel.DEFAULT_CHANNEL_ID) - .setContentIntent(LaunchMessageActivityIntent) + PendingIntent LaunchPlayMessageActivityIntent = PendingIntent.getActivity( + mContext, + REQUEST_CODE_VOICE_PLATE, + getPlayMessageIntent(senderKey, notificationInfo), + 0); + + Notification.Builder builder = new Notification.Builder( + mContext, NotificationChannel.DEFAULT_CHANNEL_ID) + .setContentIntent(LaunchPlayMessageActivityIntent) .setLargeIcon(bitmap) .setSmallIcon(R.drawable.ic_message) .setContentTitle(notificationInfo.mSenderName) @@ -245,57 +246,69 @@ class MapMessageMonitor { .setDeleteIntent(buildIntentFor( MessengerService.ACTION_CLEAR_NOTIFICATION_STATE, senderKey, notificationInfo)); + if (notificationInfo.muted) { + builder.setPriority(Notification.PRIORITY_MIN); + } else { + builder.setPriority(Notification.PRIORITY_HIGH) + .setSound(Settings.System.DEFAULT_NOTIFICATION_URI); + } mNotificationManager.notify( notificationInfo.mNotificationId, builder.build()); } }); } - private Notification.Action[] getActionsFor(SenderKey senderKey, + private Intent getPlayMessageIntent(SenderKey senderKey, NotificationInfo notificationInfo) { + Intent intent = new Intent(mContext, PlayMessageActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(PlayMessageActivity.EXTRA_MESSAGE_KEY, senderKey); + intent.putExtra( + PlayMessageActivity.EXTRA_SENDER_NAME, + notificationInfo.mSenderName); + if (!supportsReply(senderKey.mDeviceAddress)) { + intent.putExtra( + PlayMessageActivity.EXTRA_REPLY_DISABLED_FLAG, + true); + } + return intent; + } + + private boolean supportsReply(String deviceAddress) { + return mReplyFeatureMap.containsKey(deviceAddress) + && mReplyFeatureMap.get(deviceAddress); + } + + private Notification.Action[] getActionsFor( + SenderKey senderKey, NotificationInfo notificationInfo) { // Icon doesn't appear to be used; using fixed icon for all actions. final Icon icon = Icon.createWithResource(mContext, android.R.drawable.ic_media_play); - // We can have upto 3 actions. - List<Notification.Action.Builder> builders = new ArrayList<>(3); - - // Add play/mute. - String playMuteAction; - int playMuteResId; - Intent intent = new Intent(); - if (mTTSHelper.isSpeaking()) { - intent.setAction(MessengerService.ACTION_PLAY_MESSAGES_STARTED); - playMuteAction = MessengerService.ACTION_STOP_PLAYOUT; - playMuteResId = R.string.action_stop; - } else { - intent.setAction(MessengerService.ACTION_PLAY_MESSAGES_STOPPED); - playMuteAction = MessengerService.ACTION_PLAY_MESSAGES; - playMuteResId = R.string.action_play; - } - mContext.sendBroadcast(intent); - PendingIntent playMuteIntent = buildIntentFor(playMuteAction, - senderKey, notificationInfo); - builders.add(new Notification.Action.Builder(icon, - mContext.getString(playMuteResId), playMuteIntent)); - - // Add auto-reply - if (mReplyFeatureMap.containsKey(senderKey.mDeviceAddress) - && mReplyFeatureMap.get(senderKey.mDeviceAddress)) { - PendingIntent autoReplyIntent = buildIntentFor(MessengerService.ACTION_AUTO_REPLY, - senderKey, notificationInfo); + List<Notification.Action.Builder> builders = new ArrayList<>(ACTION_COUNT); + + // show auto reply options of device supports it + if (supportsReply(senderKey.mDeviceAddress)) { + Intent replyIntent = getPlayMessageIntent(senderKey, notificationInfo); + replyIntent.putExtra(PlayMessageActivity.EXTRA_SHOW_REPLY_LIST_FLAG, true); + PendingIntent autoReplyIntent = PendingIntent.getActivity( + mContext, REQUEST_CODE_AUTO_REPLY, replyIntent, 0); builders.add(new Notification.Action.Builder(icon, - mContext.getString(R.string.action_auto_reply), autoReplyIntent)); + mContext.getString(R.string.action_reply), autoReplyIntent)); } - // Optionally add mute. - if (!notificationInfo.muted) { + // add mute/unmute. + if (notificationInfo.muted) { + PendingIntent muteIntent = buildIntentFor(MessengerService.ACTION_UNMUTE_CONVERSATION, + senderKey, notificationInfo); + builders.add(new Notification.Action.Builder(icon, + mContext.getString(R.string.action_unmute), muteIntent)); + } else { PendingIntent muteIntent = buildIntentFor(MessengerService.ACTION_MUTE_CONVERSATION, senderKey, notificationInfo); builders.add(new Notification.Action.Builder(icon, mContext.getString(R.string.action_mute), muteIntent)); } - Notification.Action actions[] = new Notification.Action[builders.size()]; for (int i = 0; i < builders.size(); i++) { actions[i] = builders.get(i).build(); @@ -325,48 +338,60 @@ class MapMessageMonitor { Log.e(TAG, "Unknown senderKey! " + senderKey); return; } - List<CharSequence> ttsMessages = + List<CharSequence> ttsMessages = new ArrayList<>(); + // TODO: play unread messages instead of the last. + String ttsMessage = notificationInfo.mMessageKeys.stream().map((key) -> mMessages.get(key).getText()) - .collect(Collectors.toCollection(LinkedList::new)); + .collect(Collectors.toCollection(LinkedList::new)).getLast(); // Insert something like "foo says" before their message content. - ttsMessages.add(0, - mContext.getString(R.string.tts_sender_says, notificationInfo.mSenderName)); - mTTSHelper.requestPlay(ttsMessages, - new TTSHelper.Listener() { - @Override - public void onTTSStarted() { - Intent intent = new Intent(ACTION_MESSAGE_PLAY_START); - mContext.sendBroadcast(intent); - updateNotificationFor(senderKey, notificationInfo); - } + ttsMessages.add(mContext.getString(R.string.tts_sender_says, notificationInfo.mSenderName)); + ttsMessages.add(ttsMessage); + + int result = mAudioManager.requestAudioFocus(mNoOpAFChangeListener, + // Use the music stream. + AudioManager.STREAM_MUSIC, + // Request permanent focus. + AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); + if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { + mTTSHelper.requestPlay(ttsMessages, + new TTSHelper.Listener() { + @Override + public void onTTSStarted() { + Intent intent = new Intent(ACTION_MESSAGE_PLAY_START); + mContext.sendBroadcast(intent); + } - @Override - public void onTTSStopped(boolean error) { - Intent intent = new Intent(ACTION_MESSAGE_PLAY_STOP); - mContext.sendBroadcast(intent); - if (error) { - Toast.makeText(mContext, R.string.tts_failed_toast, Toast.LENGTH_SHORT).show(); + @Override + public void onTTSStopped(boolean error) { + mAudioManager.abandonAudioFocus(mNoOpAFChangeListener); + Intent intent = new Intent(ACTION_MESSAGE_PLAY_STOP); + mContext.sendBroadcast(intent); + if (error) { + Toast.makeText(mContext, R.string.tts_failed_toast, + Toast.LENGTH_SHORT).show(); + } } - updateNotificationFor(senderKey, notificationInfo); - } - }); + }); + } else { + Log.w(TAG, "failed to require audio focus."); + } } void stopPlayout() { mTTSHelper.requestStop(); } - void muteConversation(SenderKey senderKey) { + void toggleMuteConversation(SenderKey senderKey, boolean mute) { NotificationInfo notificationInfo = mNotificationInfos.get(senderKey); if (notificationInfo == null) { Log.e(TAG, "Unknown senderKey! " + senderKey); return; } - notificationInfo.muted = true; + notificationInfo.muted = mute; updateNotificationFor(senderKey, notificationInfo); } - boolean sendAutoReply(SenderKey senderKey, BluetoothMapClient mapClient) { + boolean sendAutoReply(SenderKey senderKey, BluetoothMapClient mapClient, String message) { if (DBG) { Log.d(TAG, "Sending auto-reply to: " + senderKey); } @@ -388,7 +413,6 @@ class MapMessageMonitor { PendingIntent.getBroadcast(mContext, requestCode, new Intent( BluetoothMapClient.ACTION_MESSAGE_SENT_SUCCESSFULLY), PendingIntent.FLAG_ONE_SHOT); - String message = mContext.getString(R.string.auto_reply_message); return mapClient.sendMessage(device, recipientUris, message, sentIntent, null); } @@ -444,8 +468,14 @@ class MapMessageMonitor { if (DBG) { Log.d(TAG, "get SDP record: " + intent.getExtras()); } - SdpMasRecord masRecord = - intent.getParcelableExtra(BluetoothDevice.EXTRA_SDP_RECORD); + Parcelable parcelable = intent.getParcelableExtra(BluetoothDevice.EXTRA_SDP_RECORD); + if (!(parcelable instanceof SdpMasRecord)) { + if (DBG) { + Log.d(TAG, "not SdpMasRecord: " + parcelable); + } + return; + } + SdpMasRecord masRecord = (SdpMasRecord) parcelable; int features = masRecord.getSupportedFeatures(); int version = masRecord.getProfileVersion(); boolean supportsReply = false; diff --git a/src/com/android/car/messenger/MessengerService.java b/src/com/android/car/messenger/MessengerService.java index 01a2069..01fc954 100644 --- a/src/com/android/car/messenger/MessengerService.java +++ b/src/com/android/car/messenger/MessengerService.java @@ -42,7 +42,6 @@ import android.widget.Toast; public class MessengerService extends Service { static final String TAG = "MessengerService"; static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); - static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE); // Used to start this service at boot-complete. Takes no arguments. static final String ACTION_START = "com.android.car.messenger.ACTION_START"; @@ -53,6 +52,9 @@ public class MessengerService extends Service { // Used to stop further audio notifications from the conversation. static final String ACTION_MUTE_CONVERSATION = "com.android.car.messenger.ACTION_MUTE_CONVERSATION"; + // Used to resume further audio notifications from the conversation. + static final String ACTION_UNMUTE_CONVERSATION = + "com.android.car.messenger.ACTION_UNMUTE_CONVERSATION"; // Used to clear notification state when user dismisses notification. static final String ACTION_CLEAR_NOTIFICATION_STATE = "com.android.car.messenger.ACTION_CLEAR_NOTIFICATION_STATE"; @@ -62,6 +64,8 @@ public class MessengerService extends Service { // Common extra for ACTION_AUTO_REPLY and ACTION_PLAY_MESSAGES. static final String EXTRA_SENDER_KEY = "com.android.car.messenger.EXTRA_SENDER_KEY"; + static final String EXTRA_REPLY_MESSAGE = "com.android.car.messenger.EXTRA_REPLY_MESSAGE"; + // Used to notify that this service started to play out the messages. static final String ACTION_PLAY_MESSAGES_STARTED = "com.android.car.messenger.ACTION_PLAY_MESSAGES_STARTED"; @@ -133,7 +137,9 @@ public class MessengerService extends Service { boolean success; if (mMapClient != null) { success = mMessageMonitor.sendAutoReply( - intent.getParcelableExtra(EXTRA_SENDER_KEY), mMapClient); + intent.getParcelableExtra(EXTRA_SENDER_KEY), + mMapClient, + intent.getStringExtra(EXTRA_REPLY_MESSAGE)); } else { Log.e(TAG, "Unable to send reply; MAP profile disconnected!"); success = false; @@ -147,7 +153,12 @@ public class MessengerService extends Service { mMessageMonitor.playMessages(intent.getParcelableExtra(EXTRA_SENDER_KEY)); break; case ACTION_MUTE_CONVERSATION: - mMessageMonitor.muteConversation(intent.getParcelableExtra(EXTRA_SENDER_KEY)); + mMessageMonitor.toggleMuteConversation( + intent.getParcelableExtra(EXTRA_SENDER_KEY), true); + break; + case ACTION_UNMUTE_CONVERSATION: + mMessageMonitor.toggleMuteConversation( + intent.getParcelableExtra(EXTRA_SENDER_KEY), false); break; case ACTION_STOP_PLAYOUT: mMessageMonitor.stopPlayout(); diff --git a/src/com/android/car/messenger/PlayMessageActivity.java b/src/com/android/car/messenger/PlayMessageActivity.java index 4d7e56b..0381c15 100644 --- a/src/com/android/car/messenger/PlayMessageActivity.java +++ b/src/com/android/car/messenger/PlayMessageActivity.java @@ -16,6 +16,8 @@ package com.android.car.messenger; +import android.animation.AnimatorInflater; +import android.animation.AnimatorSet; import android.annotation.Nullable; import android.app.Activity; import android.content.BroadcastReceiver; @@ -26,59 +28,260 @@ import android.content.IntentFilter; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; import android.widget.TextView; +import com.android.car.messenger.tts.TTSHelper; + +import java.util.ArrayList; +import java.util.List; + /** * Controls the TTS of the message received. */ public class PlayMessageActivity extends Activity { - public static final String MESSAGE_KEY = "car.messenger.MESSAGE_KEY"; - private TextView mPlayPauseBtn; + private static final String TAG = "PlayMessageActivity"; + + public static final String EXTRA_MESSAGE_KEY = "car.messenger.EXTRA_MESSAGE_KEY"; + public static final String EXTRA_SENDER_NAME = "car.messenger.EXTRA_SENDER_NAME"; + public static final String EXTRA_SHOW_REPLY_LIST_FLAG = + "car.messenger.EXTRA_SHOW_REPLY_LIST_FLAG"; + public static final String EXTRA_REPLY_DISABLED_FLAG = + "car.messenger.EXTRA_REPLY_DISABLED_FLAG"; + private View mContainer; + private View mMessageContainer; + private View mVoicePlate; + private TextView mReplyNotice; + private TextView mLeftButton; + private TextView mRightButton; + private ImageView mVoiceIcon; private MessengerService mMessengerService; private MessengerServiceBroadcastReceiver mMessengerServiceBroadcastReceiver = new MessengerServiceBroadcastReceiver(); + private MapMessageMonitor.SenderKey mSenderKey; + private TTSHelper mTTSHelper; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.play_message_layout); - mPlayPauseBtn = (TextView) findViewById(R.id.play_pause_btn); - TextView exitBtn = (TextView) findViewById(R.id.exit_btn); - exitBtn.setOnClickListener(v -> finish()); - mPlayPauseBtn.setText(getString(R.string.action_play)); - mPlayPauseBtn.setOnClickListener(v -> playMessage()); + mContainer = findViewById(R.id.container); + mMessageContainer = findViewById(R.id.message_container); + mReplyNotice = (TextView) findViewById(R.id.reply_notice); + mVoicePlate = findViewById(R.id.voice_plate); + mLeftButton = (TextView) findViewById(R.id.left_btn); + mRightButton = (TextView) findViewById(R.id.right_btn); + mVoiceIcon = (ImageView) findViewById(R.id.voice_icon); + + mTTSHelper = new TTSHelper(this); + setupEmojis(); + hideAutoReply(); + setupAutoReply(); + updateViewForMessagePlaying(); + + AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this, + R.anim.trans_bottom_in); + set.setTarget(mContainer); + set.start(); + } + + private void setupEmojis() { + TextView emoji1 = (TextView) findViewById(R.id.emoji1); + emoji1.setText(getEmojiByUnicode(getResources().getInteger(R.integer.emoji_ok_hand_sign))); + TextView emoji2 = (TextView) findViewById(R.id.emoji2); + emoji2.setText(getEmojiByUnicode(getResources().getInteger(R.integer.emoji_thumb_up))); + TextView emoji3 = (TextView) findViewById(R.id.emoji3); + emoji3.setText(getEmojiByUnicode(getResources().getInteger(R.integer.emoji_thumb_down))); + TextView emoji4 = (TextView) findViewById(R.id.emoji4); + emoji4.setText(getEmojiByUnicode(getResources().getInteger(R.integer.emoji_heart))); + TextView emoji5 = (TextView) findViewById(R.id.emoji5); + emoji5.setText(getEmojiByUnicode(getResources().getInteger(R.integer.emoji_smiling_face))); + } + + private String getEmojiByUnicode(int unicode){ + return new String(Character.toChars(unicode)); + } + + private void setupAutoReply() { + TextView cannedMessage = (TextView) findViewById(R.id.canned_message); + cannedMessage.setText(getString(R.string.reply_message_display_template, + getString(R.string.caned_message_driving_right_now))); + cannedMessage.setOnClickListener( + v -> sendReply(getString(R.string.caned_message_driving_right_now))); + findViewById(R.id.emoji1).setOnClickListener(this::sendReply); + findViewById(R.id.emoji2).setOnClickListener(this::sendReply); + findViewById(R.id.emoji3).setOnClickListener(this::sendReply); + findViewById(R.id.emoji4).setOnClickListener(this::sendReply); + findViewById(R.id.emoji5).setOnClickListener(this::sendReply); + } + + /** + * View needs to be TextView. Leave it as View, so can take advantage of lambda syntax + */ + private void sendReply(View view) { + sendReply(((TextView) view).getText()); + } + + private void sendReply(CharSequence message) { + // send auto reply + Intent intent = new Intent(getBaseContext(), MessengerService.class) + .setAction(MessengerService.ACTION_AUTO_REPLY) + .putExtra(MessengerService.EXTRA_SENDER_KEY, mSenderKey) + .putExtra( + MessengerService.EXTRA_REPLY_MESSAGE, + message); + startService(intent); + + String messageSent = getString( + R.string.message_sent_notice, + getIntent().getStringExtra(EXTRA_SENDER_NAME)); + // hide all view and show reply sent notice text + mContainer.invalidate(); + mMessageContainer.setVisibility(View.GONE); + mVoicePlate.setVisibility(View.GONE); + mReplyNotice.setText(messageSent); + mReplyNotice.setVisibility(View.VISIBLE); + ViewGroup.LayoutParams layoutParams = mContainer.getLayoutParams(); + layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT; + mContainer.requestLayout(); + + // read out the reply sent notice. Finish activity after TTS is done. + List<CharSequence> ttsMessages = new ArrayList<>(); + ttsMessages.add(messageSent); + mTTSHelper.requestPlay(ttsMessages, + new TTSHelper.Listener() { + @Override + public void onTTSStarted() { + } + + @Override + public void onTTSStopped(boolean error) { + if (error) { + Log.w(TAG, "TTS error."); + } + finish(); + } + }); + } + + private void showAutoReply() { + mContainer.invalidate(); + mMessageContainer.setVisibility(View.VISIBLE); + mLeftButton.setText(getString(R.string.action_close_messages)); + mLeftButton.setOnClickListener(v -> finish()); + ViewGroup.LayoutParams layoutParams = mContainer.getLayoutParams(); + layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT; + mContainer.requestLayout(); + } + + private void hideAutoReply() { + mContainer.invalidate(); + mMessageContainer.setVisibility(View.GONE); + mLeftButton.setText(getString(R.string.action_reply)); + mLeftButton.setOnClickListener(v -> showAutoReply()); + ViewGroup.LayoutParams layoutParams = mContainer.getLayoutParams(); + layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT; + mContainer.requestLayout(); + } + + /** + * If there's a touch outside the voice plate, exit the activity. + */ + @Override + public boolean onTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_UP) { + if (event.getX() < mContainer.getX() + || event.getX() > mContainer.getX() + mContainer.getWidth() + || event.getY() < mContainer.getY() + || event.getY() > mContainer.getY() + mContainer.getHeight()) { + finish(); + + } + } + return super.onTouchEvent(event); } @Override protected void onStart() { super.onStart(); + // Bind to LocalService Intent intent = new Intent(this, MessengerService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); mMessengerServiceBroadcastReceiver.start(); + processIntent(); + } + + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + processIntent(); + } + + private void processIntent() { + mSenderKey = getIntent().getParcelableExtra(EXTRA_MESSAGE_KEY); playMessage(); + if (getIntent().getBooleanExtra(EXTRA_SHOW_REPLY_LIST_FLAG, false)) { + showAutoReply(); + } + if (getIntent().getBooleanExtra(EXTRA_REPLY_DISABLED_FLAG, false)) { + mLeftButton.setVisibility(View.GONE); + } + } + + @Override + protected void onDestroy() { + AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this, + R.anim.trans_bottom_out); + set.setTarget(mContainer); + set.start(); + super.onDestroy(); } @Override protected void onStop() { super.onStop(); + mTTSHelper.cleanup(); mMessengerServiceBroadcastReceiver.cleanup(); + unbindService(mConnection); } private void playMessage() { - MapMessageMonitor.SenderKey senderKey = getIntent().getParcelableExtra(MESSAGE_KEY); Intent intent = new Intent(getBaseContext(), MessengerService.class) .setAction(MessengerService.ACTION_PLAY_MESSAGES) - .putExtra(MessengerService.EXTRA_SENDER_KEY, senderKey); + .putExtra(MessengerService.EXTRA_SENDER_KEY, mSenderKey); + startService(intent); + } + + private void stopMessage() { + Intent intent = new Intent(getBaseContext(), MessengerService.class) + .setAction(MessengerService.ACTION_STOP_PLAYOUT) + .putExtra(MessengerService.EXTRA_SENDER_KEY, mSenderKey); startService(intent); } + private void updateViewForMessagePlaying() { + mRightButton.setText(getString(R.string.action_stop)); + mRightButton.setOnClickListener(v -> stopMessage()); + mVoiceIcon.setVisibility(View.VISIBLE); + } + + private void updateViewFoeMessageStopped() { + mRightButton.setText(getString(R.string.action_repeat)); + mRightButton.setOnClickListener(v -> playMessage()); + mVoiceIcon.setVisibility(View.INVISIBLE); + } + private class MessengerServiceBroadcastReceiver extends BroadcastReceiver { private final IntentFilter mIntentFilter; MessengerServiceBroadcastReceiver() { mIntentFilter = new IntentFilter(); - mIntentFilter.addAction(MessengerService.ACTION_PLAY_MESSAGES_STARTED); - mIntentFilter.addAction(MessengerService.ACTION_PLAY_MESSAGES_STOPPED); + mIntentFilter.addAction(MapMessageMonitor.ACTION_MESSAGE_PLAY_START); + mIntentFilter.addAction(MapMessageMonitor.ACTION_MESSAGE_PLAY_STOP); } void start() { @@ -92,11 +295,11 @@ public class PlayMessageActivity extends Activity { @Override public void onReceive(Context context, Intent intent) { switch (intent.getAction()) { - case MessengerService.ACTION_PLAY_MESSAGES_STARTED: - mPlayPauseBtn.setText(getString(R.string.action_stop)); + case MapMessageMonitor.ACTION_MESSAGE_PLAY_START: + updateViewForMessagePlaying(); break; - case MessengerService.ACTION_PLAY_MESSAGES_STOPPED: - mPlayPauseBtn.setText(getString(R.string.action_play)); + case MapMessageMonitor.ACTION_MESSAGE_PLAY_STOP: + updateViewFoeMessageStopped(); break; default: break; @@ -110,9 +313,9 @@ public class PlayMessageActivity extends Activity { MessengerService.LocalBinder binder = (MessengerService.LocalBinder) service; mMessengerService = binder.getService(); if (mMessengerService.isPlaying()) { - mPlayPauseBtn.setText(getString(R.string.action_stop)); + updateViewForMessagePlaying(); } else { - mPlayPauseBtn.setText(getString(R.string.action_play)); + updateViewFoeMessageStopped(); } } |