• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.car.messenger;
18 
19 import android.animation.AnimatorInflater;
20 import android.animation.AnimatorSet;
21 import android.annotation.Nullable;
22 import android.app.Activity;
23 import android.content.BroadcastReceiver;
24 import android.content.ComponentName;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.content.IntentFilter;
28 import android.content.ServiceConnection;
29 import android.os.Bundle;
30 import android.os.IBinder;
31 import android.util.Log;
32 import android.view.MotionEvent;
33 import android.view.View;
34 import android.view.ViewGroup;
35 import android.widget.ImageView;
36 import android.widget.TextView;
37 
38 import com.android.car.messenger.tts.TTSHelper;
39 
40 import java.util.ArrayList;
41 import java.util.List;
42 
43 /**
44  * Controls the TTS of the message received.
45  */
46 public class PlayMessageActivity extends Activity {
47     private static final String TAG = "PlayMessageActivity";
48 
49     public static final String EXTRA_MESSAGE_KEY = "car.messenger.EXTRA_MESSAGE_KEY";
50     public static final String EXTRA_SENDER_NAME = "car.messenger.EXTRA_SENDER_NAME";
51     public static final String EXTRA_SHOW_REPLY_LIST_FLAG =
52             "car.messenger.EXTRA_SHOW_REPLY_LIST_FLAG";
53     public static final String EXTRA_REPLY_DISABLED_FLAG =
54             "car.messenger.EXTRA_REPLY_DISABLED_FLAG";
55     private View mContainer;
56     private View mMessageContainer;
57     private View mVoicePlate;
58     private TextView mReplyNotice;
59     private TextView mLeftButton;
60     private TextView mRightButton;
61     private ImageView mVoiceIcon;
62     private MessengerService mMessengerService;
63     private MessengerServiceBroadcastReceiver mMessengerServiceBroadcastReceiver =
64             new MessengerServiceBroadcastReceiver();
65     private MapMessageMonitor.SenderKey mSenderKey;
66     private TTSHelper mTTSHelper;
67 
68     @Override
onCreate(@ullable Bundle savedInstanceState)69     protected void onCreate(@Nullable Bundle savedInstanceState) {
70         super.onCreate(savedInstanceState);
71         setContentView(R.layout.play_message_layout);
72         mContainer = findViewById(R.id.container);
73         mMessageContainer = findViewById(R.id.message_container);
74         mReplyNotice = (TextView) findViewById(R.id.reply_notice);
75         mVoicePlate = findViewById(R.id.voice_plate);
76         mLeftButton = (TextView) findViewById(R.id.left_btn);
77         mRightButton = (TextView) findViewById(R.id.right_btn);
78         mVoiceIcon = (ImageView) findViewById(R.id.voice_icon);
79 
80         mTTSHelper = new TTSHelper(this);
81         setupEmojis();
82         hideAutoReply();
83         setupAutoReply();
84         updateViewForMessagePlaying();
85 
86         AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this,
87                 R.anim.trans_bottom_in);
88         set.setTarget(mContainer);
89         set.start();
90     }
91 
setupEmojis()92     private void setupEmojis() {
93         TextView emoji1 = (TextView) findViewById(R.id.emoji1);
94         emoji1.setText(getEmojiByUnicode(getResources().getInteger(R.integer.emoji_ok_hand_sign)));
95         TextView emoji2 = (TextView) findViewById(R.id.emoji2);
96         emoji2.setText(getEmojiByUnicode(getResources().getInteger(R.integer.emoji_thumb_up)));
97         TextView emoji3 = (TextView) findViewById(R.id.emoji3);
98         emoji3.setText(getEmojiByUnicode(getResources().getInteger(R.integer.emoji_thumb_down)));
99         TextView emoji4 = (TextView) findViewById(R.id.emoji4);
100         emoji4.setText(getEmojiByUnicode(getResources().getInteger(R.integer.emoji_heart)));
101         TextView emoji5 = (TextView) findViewById(R.id.emoji5);
102         emoji5.setText(getEmojiByUnicode(getResources().getInteger(R.integer.emoji_smiling_face)));
103     }
104 
getEmojiByUnicode(int unicode)105     private String getEmojiByUnicode(int unicode){
106         return new String(Character.toChars(unicode));
107     }
108 
setupAutoReply()109     private void setupAutoReply() {
110         TextView cannedMessage = (TextView) findViewById(R.id.canned_message);
111         cannedMessage.setText(getString(R.string.reply_message_display_template,
112                 getString(R.string.caned_message_driving_right_now)));
113         cannedMessage.setOnClickListener(
114                 v -> sendReply(getString(R.string.caned_message_driving_right_now)));
115         findViewById(R.id.emoji1).setOnClickListener(this::sendReply);
116         findViewById(R.id.emoji2).setOnClickListener(this::sendReply);
117         findViewById(R.id.emoji3).setOnClickListener(this::sendReply);
118         findViewById(R.id.emoji4).setOnClickListener(this::sendReply);
119         findViewById(R.id.emoji5).setOnClickListener(this::sendReply);
120     }
121 
122     /**
123      * View needs to be TextView. Leave it as View, so can take advantage of lambda syntax
124      */
sendReply(View view)125     private void sendReply(View view) {
126         sendReply(((TextView) view).getText());
127     }
128 
sendReply(CharSequence message)129     private void sendReply(CharSequence message) {
130         // send auto reply
131         Intent intent = new Intent(getBaseContext(), MessengerService.class)
132                 .setAction(MessengerService.ACTION_AUTO_REPLY)
133                 .putExtra(MessengerService.EXTRA_SENDER_KEY, mSenderKey)
134                 .putExtra(
135                         MessengerService.EXTRA_REPLY_MESSAGE,
136                         message);
137         startService(intent);
138 
139         String messageSent = getString(
140                 R.string.message_sent_notice,
141                 getIntent().getStringExtra(EXTRA_SENDER_NAME));
142         // hide all view and show reply sent notice text
143         mContainer.invalidate();
144         mMessageContainer.setVisibility(View.GONE);
145         mVoicePlate.setVisibility(View.GONE);
146         mReplyNotice.setText(messageSent);
147         mReplyNotice.setVisibility(View.VISIBLE);
148         ViewGroup.LayoutParams layoutParams = mContainer.getLayoutParams();
149         layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
150         mContainer.requestLayout();
151 
152         // read out the reply sent notice. Finish activity after TTS is done.
153         List<CharSequence> ttsMessages = new ArrayList<>();
154         ttsMessages.add(messageSent);
155         mTTSHelper.requestPlay(ttsMessages,
156                 new TTSHelper.Listener() {
157                     @Override
158                     public void onTTSStarted() {
159                     }
160 
161                     @Override
162                     public void onTTSStopped(boolean error) {
163                         if (error) {
164                             Log.w(TAG, "TTS error.");
165                         }
166                         finish();
167                     }
168                 });
169     }
170 
showAutoReply()171     private void showAutoReply() {
172         mContainer.invalidate();
173         mMessageContainer.setVisibility(View.VISIBLE);
174         mLeftButton.setText(getString(R.string.action_close_messages));
175         mLeftButton.setOnClickListener(v -> finish());
176         ViewGroup.LayoutParams layoutParams = mContainer.getLayoutParams();
177         layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
178         mContainer.requestLayout();
179     }
180 
hideAutoReply()181     private void hideAutoReply() {
182         mContainer.invalidate();
183         mMessageContainer.setVisibility(View.GONE);
184         mLeftButton.setText(getString(R.string.action_reply));
185         mLeftButton.setOnClickListener(v -> showAutoReply());
186         ViewGroup.LayoutParams layoutParams = mContainer.getLayoutParams();
187         layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
188         mContainer.requestLayout();
189     }
190 
191     /**
192      * If there's a touch outside the voice plate, exit the activity.
193      */
194     @Override
onTouchEvent(MotionEvent event)195     public boolean onTouchEvent(MotionEvent event) {
196         if (event.getAction() == MotionEvent.ACTION_UP) {
197             if (event.getX() < mContainer.getX()
198                     || event.getX() > mContainer.getX() + mContainer.getWidth()
199                     || event.getY() < mContainer.getY()
200                     || event.getY() > mContainer.getY() + mContainer.getHeight()) {
201                 finish();
202 
203             }
204         }
205         return super.onTouchEvent(event);
206     }
207 
208     @Override
onStart()209     protected void onStart() {
210         super.onStart();
211 
212         // Bind to LocalService
213         Intent intent = new Intent(this, MessengerService.class);
214         bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
215         mMessengerServiceBroadcastReceiver.start();
216         processIntent();
217     }
218 
219     @Override
onNewIntent(Intent intent)220     protected void onNewIntent(Intent intent) {
221         super.onNewIntent(intent);
222         processIntent();
223     }
224 
processIntent()225     private void processIntent() {
226         mSenderKey = getIntent().getParcelableExtra(EXTRA_MESSAGE_KEY);
227         playMessage();
228         if (getIntent().getBooleanExtra(EXTRA_SHOW_REPLY_LIST_FLAG, false)) {
229             showAutoReply();
230         }
231         if (getIntent().getBooleanExtra(EXTRA_REPLY_DISABLED_FLAG, false)) {
232             mLeftButton.setVisibility(View.GONE);
233         }
234     }
235 
236     @Override
onDestroy()237     protected void onDestroy() {
238         AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this,
239                 R.anim.trans_bottom_out);
240         set.setTarget(mContainer);
241         set.start();
242         super.onDestroy();
243     }
244 
245     @Override
onStop()246     protected void onStop() {
247         super.onStop();
248         mTTSHelper.cleanup();
249         mMessengerServiceBroadcastReceiver.cleanup();
250         unbindService(mConnection);
251     }
252 
playMessage()253     private void playMessage() {
254         Intent intent = new Intent(getBaseContext(), MessengerService.class)
255                 .setAction(MessengerService.ACTION_PLAY_MESSAGES)
256                 .putExtra(MessengerService.EXTRA_SENDER_KEY, mSenderKey);
257         startService(intent);
258     }
259 
stopMessage()260     private void stopMessage() {
261         Intent intent = new Intent(getBaseContext(), MessengerService.class)
262                 .setAction(MessengerService.ACTION_STOP_PLAYOUT)
263                 .putExtra(MessengerService.EXTRA_SENDER_KEY, mSenderKey);
264         startService(intent);
265     }
266 
updateViewForMessagePlaying()267     private void updateViewForMessagePlaying() {
268         mRightButton.setText(getString(R.string.action_stop));
269         mRightButton.setOnClickListener(v -> stopMessage());
270         mVoiceIcon.setVisibility(View.VISIBLE);
271     }
272 
updateViewFoeMessageStopped()273     private void updateViewFoeMessageStopped() {
274         mRightButton.setText(getString(R.string.action_repeat));
275         mRightButton.setOnClickListener(v -> playMessage());
276         mVoiceIcon.setVisibility(View.INVISIBLE);
277     }
278 
279     private class MessengerServiceBroadcastReceiver extends BroadcastReceiver {
280         private final IntentFilter mIntentFilter;
MessengerServiceBroadcastReceiver()281         MessengerServiceBroadcastReceiver() {
282             mIntentFilter = new IntentFilter();
283             mIntentFilter.addAction(MapMessageMonitor.ACTION_MESSAGE_PLAY_START);
284             mIntentFilter.addAction(MapMessageMonitor.ACTION_MESSAGE_PLAY_STOP);
285         }
286 
start()287         void start() {
288             registerReceiver(this, mIntentFilter);
289         }
290 
cleanup()291         void cleanup() {
292             unregisterReceiver(this);
293         }
294 
295         @Override
onReceive(Context context, Intent intent)296         public void onReceive(Context context, Intent intent) {
297             switch (intent.getAction()) {
298                 case MapMessageMonitor.ACTION_MESSAGE_PLAY_START:
299                     updateViewForMessagePlaying();
300                     break;
301                 case MapMessageMonitor.ACTION_MESSAGE_PLAY_STOP:
302                     updateViewFoeMessageStopped();
303                     break;
304                 default:
305                     break;
306             }
307         }
308     }
309 
310     private final ServiceConnection mConnection = new ServiceConnection() {
311         @Override
312         public void onServiceConnected(ComponentName className, IBinder service) {
313             MessengerService.LocalBinder binder = (MessengerService.LocalBinder) service;
314             mMessengerService = binder.getService();
315             if (mMessengerService.isPlaying()) {
316                 updateViewForMessagePlaying();
317             } else {
318                 updateViewFoeMessageStopped();
319             }
320         }
321 
322         @Override
323         public void onServiceDisconnected(ComponentName arg0) {
324             mMessengerService = null;
325         }
326     };
327 }
328