blob: b4915cc162cb1ae9bb30ab4463db648b5482ac3b [file] [log] [blame]
Joseph Pirozzocaa94c62016-10-06 09:29:43 -07001/*
2 * Copyright (C) 2016 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
17package com.google.android.car.kitchensink.bluetooth;
18
19import android.app.PendingIntent;
20import android.bluetooth.BluetoothAdapter;
21import android.bluetooth.BluetoothDevice;
Joseph Pirozzo9cddbe92017-02-08 18:23:56 -080022import android.bluetooth.BluetoothDevicePicker;
Joseph Pirozzocaa94c62016-10-06 09:29:43 -070023import android.bluetooth.BluetoothMapClient;
24import android.bluetooth.BluetoothProfile;
25import android.content.BroadcastReceiver;
26import android.content.Context;
27import android.content.Intent;
28import android.content.IntentFilter;
29import android.net.Uri;
30import android.os.Bundle;
31import android.support.annotation.Nullable;
32import android.support.v4.app.Fragment;
33import android.util.Log;
34import android.view.LayoutInflater;
35import android.view.View;
36import android.view.ViewGroup;
37import android.widget.Button;
38import android.widget.CheckBox;
Joseph Pirozzo9cddbe92017-02-08 18:23:56 -080039import android.widget.EditText;
Joseph Pirozzocaa94c62016-10-06 09:29:43 -070040import android.widget.TextView;
41
42import com.google.android.car.kitchensink.R;
43
44import java.util.List;
45
46public class MapMceTestFragment extends Fragment {
47 static final String MESSAGE_TO_SEND = "Im Busy Driving";
48 private static final String TAG = "CAR.BLUETOOTH.KS";
49 BluetoothMapClient mMapProfile;
50 BluetoothAdapter mBluetoothAdapter;
Joseph Pirozzo9cddbe92017-02-08 18:23:56 -080051 Button mDevicePicker;
52 Button mDeviceDisconnect;
Joseph Pirozzocaa94c62016-10-06 09:29:43 -070053 TextView mMessage;
Joseph Pirozzo9cddbe92017-02-08 18:23:56 -080054 EditText mOriginator;
Joseph Pirozzoa90995a2016-10-13 09:48:50 -070055 TextView mOriginatorDisplayName;
Joseph Pirozzocaa94c62016-10-06 09:29:43 -070056 CheckBox mSent;
57 CheckBox mDelivered;
58 TextView mBluetoothDevice;
59 PendingIntent mSentIntent;
60 PendingIntent mDeliveredIntent;
61 NotificationReceiver mTransmissionStatusReceiver;
62 Object mLock = new Object();
63 private Intent mSendIntent;
64 private Intent mDeliveryIntent;
65
66 @Override
67 public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
68 @Nullable Bundle savedInstanceState) {
69 View v = inflater.inflate(R.layout.sms_received, container, false);
70
71 Button reply = (Button) v.findViewById(R.id.reply);
72 Button checkMessages = (Button) v.findViewById(R.id.check_messages);
73 mBluetoothDevice = (TextView) v.findViewById(R.id.bluetoothDevice);
Joseph Pirozzo9cddbe92017-02-08 18:23:56 -080074 mOriginator = (EditText) v.findViewById(R.id.messageOriginator);
Joseph Pirozzoa90995a2016-10-13 09:48:50 -070075 mOriginatorDisplayName = (TextView) v.findViewById(R.id.messageOriginatorDisplayName);
Joseph Pirozzocaa94c62016-10-06 09:29:43 -070076 mSent = (CheckBox) v.findViewById(R.id.sent_checkbox);
77 mDelivered = (CheckBox) v.findViewById(R.id.delivered_checkbox);
78 mSendIntent = new Intent(BluetoothMapClient.ACTION_MESSAGE_SENT_SUCCESSFULLY);
79 mDeliveryIntent = new Intent(BluetoothMapClient.ACTION_MESSAGE_DELIVERED_SUCCESSFULLY);
80 mMessage = (TextView) v.findViewById(R.id.messageContent);
Joseph Pirozzo9cddbe92017-02-08 18:23:56 -080081 mDevicePicker = (Button) v.findViewById(R.id.bluetooth_pick_device);
82 mDeviceDisconnect = (Button) v.findViewById(R.id.bluetooth_disconnect_device);
Joseph Pirozzocaa94c62016-10-06 09:29:43 -070083 //TODO add manual entry option for phone number
84 reply.setOnClickListener(new View.OnClickListener() {
85 @Override
86 public void onClick(View view) {
87 sendMessage(new Uri[]{Uri.parse(mOriginator.getText().toString())},
88 MESSAGE_TO_SEND);
89 }
90 });
91
92 checkMessages.setOnClickListener(new View.OnClickListener() {
93 @Override
94 public void onClick(View view) {
95 getMessages();
96 }
97 });
98
Joseph Pirozzo9cddbe92017-02-08 18:23:56 -080099 // Pick a bluetooth device
100 mDevicePicker.setOnClickListener(new View.OnClickListener() {
101 @Override
102 public void onClick(View view) {
103 launchDevicePicker();
104 }
105 });
106 mDeviceDisconnect.setOnClickListener(new View.OnClickListener() {
107 @Override
108 public void onClick(View view) {
109 disconnectDevice(mBluetoothDevice.getText().toString());
110 }
111 });
112
Joseph Pirozzocaa94c62016-10-06 09:29:43 -0700113 mTransmissionStatusReceiver = new NotificationReceiver();
114 return v;
115 }
116
Joseph Pirozzo9cddbe92017-02-08 18:23:56 -0800117 void launchDevicePicker() {
118 IntentFilter filter = new IntentFilter();
119 filter.addAction(BluetoothDevicePicker.ACTION_DEVICE_SELECTED);
120 getContext().registerReceiver(mPickerReceiver, filter);
121
122 Intent intent = new Intent(BluetoothDevicePicker.ACTION_LAUNCH);
123 intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
124 getContext().startActivity(intent);
125 }
126
127 void disconnectDevice(String device) {
128 mMapProfile.disconnect(mBluetoothAdapter.getRemoteDevice((device)));
129 }
130
Joseph Pirozzocaa94c62016-10-06 09:29:43 -0700131 @Override
132 public void onResume() {
133 super.onResume();
134
135 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
136 mBluetoothAdapter.getProfileProxy(getContext(), new MapServiceListener(),
137 BluetoothProfile.MAP_CLIENT);
138
139 IntentFilter intentFilter = new IntentFilter();
140 intentFilter.addAction(BluetoothMapClient.ACTION_MESSAGE_SENT_SUCCESSFULLY);
141 intentFilter.addAction(BluetoothMapClient.ACTION_MESSAGE_DELIVERED_SUCCESSFULLY);
142 intentFilter.addAction(BluetoothMapClient.ACTION_MESSAGE_RECEIVED);
Joseph Pirozzo9cddbe92017-02-08 18:23:56 -0800143 intentFilter.addAction(BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED);
Joseph Pirozzocaa94c62016-10-06 09:29:43 -0700144 getContext().registerReceiver(mTransmissionStatusReceiver, intentFilter);
145 }
146
147 @Override
148 public void onPause() {
149 super.onPause();
150 getContext().unregisterReceiver(mTransmissionStatusReceiver);
151 }
152
153 private void getMessages() {
154 synchronized (mLock) {
Joseph Pirozzo9cddbe92017-02-08 18:23:56 -0800155 BluetoothDevice remoteDevice;
156 try {
157 remoteDevice = mBluetoothAdapter.getRemoteDevice(
158 mBluetoothDevice.getText().toString());
159 } catch (java.lang.IllegalArgumentException e) {
160 Log.e(TAG, e.toString());
161 return;
162 }
163
Joseph Pirozzocaa94c62016-10-06 09:29:43 -0700164 if (mMapProfile != null) {
165 Log.d(TAG, "Getting Messages");
Joseph Pirozzo9cddbe92017-02-08 18:23:56 -0800166 mMapProfile.getUnreadMessages(remoteDevice);
Joseph Pirozzocaa94c62016-10-06 09:29:43 -0700167 }
168 }
169 }
170
171 private void sendMessage(Uri[] recipients, String message) {
172 synchronized (mLock) {
Joseph Pirozzo9cddbe92017-02-08 18:23:56 -0800173 BluetoothDevice remoteDevice;
174 try {
175 remoteDevice = mBluetoothAdapter.getRemoteDevice(
176 mBluetoothDevice.getText().toString());
177 } catch (java.lang.IllegalArgumentException e) {
178 Log.e(TAG, e.toString());
179 return;
180 }
Joseph Pirozzocaa94c62016-10-06 09:29:43 -0700181 mSent.setChecked(false);
182 mDelivered.setChecked(false);
183 if (mMapProfile != null) {
184 Log.d(TAG, "Sending reply");
185 if (recipients == null) {
186 Log.d(TAG, "Recipients is null");
187 return;
188 }
189 if (mBluetoothDevice == null) {
190 Log.d(TAG, "BluetoothDevice is null");
191 return;
192 }
193
194 mSentIntent = PendingIntent.getBroadcast(getContext(), 0, mSendIntent,
195 PendingIntent.FLAG_ONE_SHOT);
196 mDeliveredIntent = PendingIntent.getBroadcast(getContext(), 0, mDeliveryIntent,
197 PendingIntent.FLAG_ONE_SHOT);
198 mMapProfile.sendMessage(
Joseph Pirozzo9cddbe92017-02-08 18:23:56 -0800199 remoteDevice,
Joseph Pirozzocaa94c62016-10-06 09:29:43 -0700200 recipients, message, mSentIntent, mDeliveredIntent);
201 }
202 }
203 }
204
205 class MapServiceListener implements BluetoothProfile.ServiceListener {
206 @Override
207 public void onServiceConnected(int profile, BluetoothProfile proxy) {
208 synchronized (mLock) {
209 mMapProfile = (BluetoothMapClient) proxy;
210 List<BluetoothDevice> connectedDevices = proxy.getConnectedDevices();
211 if (connectedDevices.size() > 0) {
212 mBluetoothDevice.setText(connectedDevices.get(0).getAddress());
213 }
214 }
215 }
216
217 @Override
218 public void onServiceDisconnected(int profile) {
219 synchronized (mLock) {
220 mMapProfile = null;
221 }
222 }
223 }
224
225 private class NotificationReceiver extends BroadcastReceiver {
226 @Override
227 public void onReceive(Context context, Intent intent) {
228 String action = intent.getAction();
229 synchronized (mLock) {
Joseph Pirozzo9cddbe92017-02-08 18:23:56 -0800230 if (action.equals(BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED)) {
231 if (intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0)
232 == BluetoothProfile.STATE_CONNECTED) {
233 mBluetoothDevice.setText(((BluetoothDevice) intent.getParcelableExtra(
234 BluetoothDevice.EXTRA_DEVICE)).getAddress());
235 } else if (intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0)
236 == BluetoothProfile.STATE_DISCONNECTED) {
237 mBluetoothDevice.setText("Disconnected");
238 }
239 } else if (action.equals(BluetoothMapClient.ACTION_MESSAGE_SENT_SUCCESSFULLY)) {
Joseph Pirozzocaa94c62016-10-06 09:29:43 -0700240 mSent.setChecked(true);
241 } else if (action.equals(
242 BluetoothMapClient.ACTION_MESSAGE_DELIVERED_SUCCESSFULLY)) {
243 mDelivered.setChecked(true);
244 } else if (action.equals(BluetoothMapClient.ACTION_MESSAGE_RECEIVED)) {
Joseph Pirozzoa90995a2016-10-13 09:48:50 -0700245
Srinivas Visvanathan6b90bbf2017-03-03 10:01:09 -0800246 String[] recipients = intent.getStringArrayExtra(
247 BluetoothMapClient.EXTRA_SENDER_CONTACT_URI);
Joseph Pirozzocaa94c62016-10-06 09:29:43 -0700248 StringBuilder stringBuilder = new StringBuilder();
249 if (recipients != null) {
250 for (String s : recipients) {
251 stringBuilder.append(s);
252 }
253 }
254
Srinivas Visvanathan6b90bbf2017-03-03 10:01:09 -0800255 String[] recipientsName = intent.getStringArrayExtra(
256 BluetoothMapClient.EXTRA_SENDER_CONTACT_NAME);
Joseph Pirozzoa90995a2016-10-13 09:48:50 -0700257 StringBuilder stringBuilderName = new StringBuilder();
258 if (recipientsName != null) {
259 for (String s : recipientsName) {
260 stringBuilderName.append(s);
261 }
262 }
263
Joseph Pirozzocaa94c62016-10-06 09:29:43 -0700264 mMessage.setText(intent.getStringExtra(android.content.Intent.EXTRA_TEXT));
265 mOriginator.setText(stringBuilder.toString());
Joseph Pirozzoa90995a2016-10-13 09:48:50 -0700266 mOriginatorDisplayName.setText(stringBuilderName.toString());
Joseph Pirozzocaa94c62016-10-06 09:29:43 -0700267 }
268 }
269 }
270 }
Joseph Pirozzo9cddbe92017-02-08 18:23:56 -0800271
272 private final BroadcastReceiver mPickerReceiver = new BroadcastReceiver() {
273 @Override
274 public void onReceive(Context context, Intent intent) {
275 String action = intent.getAction();
276
277 Log.v(TAG, "mPickerReceiver got " + action);
278
279 if (BluetoothDevicePicker.ACTION_DEVICE_SELECTED.equals(action)) {
280 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
281 Log.v(TAG, "mPickerReceiver got " + device);
282 mMapProfile.connect(device);
283
284 // The receiver can now be disabled.
285 getContext().unregisterReceiver(mPickerReceiver);
286 }
287 }
288 };
Joseph Pirozzocaa94c62016-10-06 09:29:43 -0700289}