MapMceTestFragment.java revision 0ab0af545dcc2cc34e540778da5db926bb593163
1/*
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.annotation.TargetApi;
20import android.app.PendingIntent;
21import android.bluetooth.BluetoothAdapter;
22import android.bluetooth.BluetoothDevice;
23import android.bluetooth.BluetoothDevicePicker;
24import android.bluetooth.BluetoothMapClient;
25import android.bluetooth.BluetoothProfile;
26import android.content.BroadcastReceiver;
27import android.content.Context;
28import android.content.Intent;
29import android.content.IntentFilter;
30import android.content.pm.PackageManager;
31import android.Manifest;
32import android.net.Uri;
33import android.net.Uri.Builder;
34import android.os.Build;
35import android.os.Bundle;
36import android.provider.ContactsContract.PhoneLookup;
37import android.support.annotation.Nullable;
38import android.support.v4.app.Fragment;
39import android.telecom.PhoneAccount;
40import android.util.Log;
41import android.view.LayoutInflater;
42import android.view.View;
43import android.view.ViewGroup;
44import android.widget.Button;
45import android.widget.CheckBox;
46import android.widget.EditText;
47import android.widget.TextView;
48import android.widget.Toast;
49
50import com.google.android.car.kitchensink.KitchenSinkActivity;
51import com.google.android.car.kitchensink.R;
52
53import java.util.List;
54
55@TargetApi(Build.VERSION_CODES.LOLLIPOP)
56public class MapMceTestFragment extends Fragment {
57    static final String MESSAGE_TO_SEND = "Im Busy Driving";
58    static final String NEW_MESSAGE_TO_SEND = "This is new msg";
59    private static final String TAG = "CAR.BLUETOOTH.KS";
60    private static final int SEND_SMS_PERMISSIONS_REQUEST = 1;
61    BluetoothMapClient mMapProfile;
62    BluetoothAdapter mBluetoothAdapter;
63    Button mDevicePicker;
64    Button mDeviceDisconnect;
65    TextView mMessage;
66    EditText mOriginator;
67    EditText mSmsTelNum;
68    TextView mOriginatorDisplayName;
69    CheckBox mSent;
70    CheckBox mDelivered;
71    TextView mBluetoothDevice;
72    PendingIntent mSentIntent;
73    PendingIntent mDeliveredIntent;
74    NotificationReceiver mTransmissionStatusReceiver;
75    Object mLock = new Object();
76    private KitchenSinkActivity mActivity;
77    private Intent mSendIntent;
78    private Intent mDeliveryIntent;
79
80    @Override
81    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
82            @Nullable Bundle savedInstanceState) {
83        View v = inflater.inflate(R.layout.sms_received, container, false);
84        mActivity = (KitchenSinkActivity) getHost();
85        Button reply = (Button) v.findViewById(R.id.reply);
86        Button checkMessages = (Button) v.findViewById(R.id.check_messages);
87        mBluetoothDevice = (TextView) v.findViewById(R.id.bluetoothDevice);
88        Button sendNewMsg = (Button) v.findViewById(R.id.sms_new_message);
89        mSmsTelNum = (EditText) v.findViewById(R.id.sms_tel_num);
90        mOriginator = (EditText) v.findViewById(R.id.messageOriginator);
91        mOriginatorDisplayName = (TextView) v.findViewById(R.id.messageOriginatorDisplayName);
92        mSent = (CheckBox) v.findViewById(R.id.sent_checkbox);
93        mDelivered = (CheckBox) v.findViewById(R.id.delivered_checkbox);
94        mSendIntent = new Intent(BluetoothMapClient.ACTION_MESSAGE_SENT_SUCCESSFULLY);
95        mDeliveryIntent = new Intent(BluetoothMapClient.ACTION_MESSAGE_DELIVERED_SUCCESSFULLY);
96        mMessage = (TextView) v.findViewById(R.id.messageContent);
97        mDevicePicker = (Button) v.findViewById(R.id.bluetooth_pick_device);
98        mDeviceDisconnect = (Button) v.findViewById(R.id.bluetooth_disconnect_device);
99        //TODO add manual entry option for phone number
100        reply.setOnClickListener(new View.OnClickListener() {
101            @Override
102            public void onClick(View view) {
103                sendMessage(new Uri[]{Uri.parse(mOriginator.getText().toString())},
104                        MESSAGE_TO_SEND);
105            }
106        });
107
108        sendNewMsg.setOnClickListener(new View.OnClickListener() {
109            @Override
110            public void onClick(View view) {
111                String s = mSmsTelNum.getText().toString();
112                Toast.makeText(getContext(), "sending msg to " + s, Toast.LENGTH_SHORT).show();
113                Uri.Builder builder = new Uri.Builder();
114                Uri uri = builder.appendPath(s).scheme(PhoneAccount.SCHEME_TEL).build();
115                sendMessage(new Uri[]{uri}, NEW_MESSAGE_TO_SEND);
116            }
117        });
118
119        checkMessages.setOnClickListener(new View.OnClickListener() {
120            @Override
121            public void onClick(View view) {
122                getMessages();
123            }
124        });
125
126        // Pick a bluetooth device
127        mDevicePicker.setOnClickListener(new View.OnClickListener() {
128            @Override
129            public void onClick(View view) {
130                launchDevicePicker();
131            }
132        });
133        mDeviceDisconnect.setOnClickListener(new View.OnClickListener() {
134            @Override
135            public void onClick(View view) {
136                disconnectDevice(mBluetoothDevice.getText().toString());
137            }
138        });
139
140        mTransmissionStatusReceiver = new NotificationReceiver();
141        return v;
142    }
143
144    void launchDevicePicker() {
145        IntentFilter filter = new IntentFilter();
146        filter.addAction(BluetoothDevicePicker.ACTION_DEVICE_SELECTED);
147        getContext().registerReceiver(mPickerReceiver, filter);
148
149        Intent intent = new Intent(BluetoothDevicePicker.ACTION_LAUNCH);
150        intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
151        getContext().startActivity(intent);
152    }
153
154    void disconnectDevice(String device) {
155        mMapProfile.disconnect(mBluetoothAdapter.getRemoteDevice((device)));
156    }
157
158    @Override
159    public void onResume() {
160        super.onResume();
161
162        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
163        mBluetoothAdapter.getProfileProxy(getContext(), new MapServiceListener(),
164                BluetoothProfile.MAP_CLIENT);
165
166        IntentFilter intentFilter = new IntentFilter();
167        intentFilter.addAction(BluetoothMapClient.ACTION_MESSAGE_SENT_SUCCESSFULLY);
168        intentFilter.addAction(BluetoothMapClient.ACTION_MESSAGE_DELIVERED_SUCCESSFULLY);
169        intentFilter.addAction(BluetoothMapClient.ACTION_MESSAGE_RECEIVED);
170        intentFilter.addAction(BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED);
171        getContext().registerReceiver(mTransmissionStatusReceiver, intentFilter);
172    }
173
174    @Override
175    public void onPause() {
176        super.onPause();
177        getContext().unregisterReceiver(mTransmissionStatusReceiver);
178    }
179
180    private void getMessages() {
181        synchronized (mLock) {
182            BluetoothDevice remoteDevice;
183            try {
184                remoteDevice = mBluetoothAdapter.getRemoteDevice(
185                        mBluetoothDevice.getText().toString());
186            } catch (java.lang.IllegalArgumentException e) {
187                Log.e(TAG, e.toString());
188                return;
189            }
190
191            if (mMapProfile != null) {
192                Log.d(TAG, "Getting Messages");
193                mMapProfile.getUnreadMessages(remoteDevice);
194            }
195        }
196    }
197
198    private void sendMessage(Uri[] recipients, String message) {
199        if (mActivity.checkSelfPermission(Manifest.permission.SEND_SMS)
200                != PackageManager.PERMISSION_GRANTED) {
201            Log.d(TAG,"Don't have SMS permission in kitchesink app. Requesting it");
202            mActivity.requestPermissions(new String[]{Manifest.permission.SEND_SMS},
203                    SEND_SMS_PERMISSIONS_REQUEST);
204            Toast.makeText(getContext(), "Try again after granting SEND_SMS perm!",
205                    Toast.LENGTH_SHORT).show();
206            return;
207        }
208        synchronized (mLock) {
209            BluetoothDevice remoteDevice;
210            try {
211                remoteDevice = mBluetoothAdapter.getRemoteDevice(
212                        mBluetoothDevice.getText().toString());
213            } catch (java.lang.IllegalArgumentException e) {
214                Log.e(TAG, e.toString());
215                return;
216            }
217            mSent.setChecked(false);
218            mDelivered.setChecked(false);
219            if (mMapProfile != null) {
220                Log.d(TAG, "Sending reply");
221                if (recipients == null) {
222                    Log.d(TAG, "Recipients is null");
223                    return;
224                }
225                if (mBluetoothDevice == null) {
226                    Log.d(TAG, "BluetoothDevice is null");
227                    return;
228                }
229
230                mSentIntent = PendingIntent.getBroadcast(getContext(), 0, mSendIntent,
231                        PendingIntent.FLAG_ONE_SHOT);
232                mDeliveredIntent = PendingIntent.getBroadcast(getContext(), 0, mDeliveryIntent,
233                        PendingIntent.FLAG_ONE_SHOT);
234                Log.d(TAG,"Sending message in kitchesink app: " + message);
235                mMapProfile.sendMessage(
236                        remoteDevice,
237                        recipients, message, mSentIntent, mDeliveredIntent);
238            }
239        }
240    }
241
242    @Override
243    public void onRequestPermissionsResult(int requestCode, String[] permissions,
244            int[] grantResults) {
245        Log.d(TAG, "onRequestPermissionsResult reqCode=" + requestCode);
246        if (SEND_SMS_PERMISSIONS_REQUEST == requestCode) {
247            for (int i=0; i<permissions.length; i++) {
248                if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
249                    if (permissions[i] == Manifest.permission.SEND_SMS) {
250                        Log.d(TAG, "Got the SEND_SMS perm");
251                        return;
252                    }
253                }
254            }
255        }
256    }
257
258    class MapServiceListener implements BluetoothProfile.ServiceListener {
259        @Override
260        public void onServiceConnected(int profile, BluetoothProfile proxy) {
261            synchronized (mLock) {
262                mMapProfile = (BluetoothMapClient) proxy;
263                List<BluetoothDevice> connectedDevices = proxy.getConnectedDevices();
264                if (connectedDevices.size() > 0) {
265                    mBluetoothDevice.setText(connectedDevices.get(0).getAddress());
266                }
267            }
268        }
269
270        @Override
271        public void onServiceDisconnected(int profile) {
272            synchronized (mLock) {
273                mMapProfile = null;
274            }
275        }
276    }
277
278    private class NotificationReceiver extends BroadcastReceiver {
279        @Override
280        public void onReceive(Context context, Intent intent) {
281            String action = intent.getAction();
282            synchronized (mLock) {
283                if (action.equals(BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED)) {
284                    if (intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0)
285                            == BluetoothProfile.STATE_CONNECTED) {
286                        mBluetoothDevice.setText(((BluetoothDevice) intent.getParcelableExtra(
287                                BluetoothDevice.EXTRA_DEVICE)).getAddress());
288                    } else if (intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0)
289                            == BluetoothProfile.STATE_DISCONNECTED) {
290                        mBluetoothDevice.setText("Disconnected");
291                    }
292                } else if (action.equals(BluetoothMapClient.ACTION_MESSAGE_SENT_SUCCESSFULLY)) {
293                    mSent.setChecked(true);
294                } else if (action.equals(
295                        BluetoothMapClient.ACTION_MESSAGE_DELIVERED_SUCCESSFULLY)) {
296                    mDelivered.setChecked(true);
297                } else if (action.equals(BluetoothMapClient.ACTION_MESSAGE_RECEIVED)) {
298                    String senderUri =
299                            intent.getStringExtra(BluetoothMapClient.EXTRA_SENDER_CONTACT_URI);
300                    if (senderUri == null) {
301                        senderUri = "<null>";
302                    }
303
304                    String senderName = intent.getStringExtra(
305                            BluetoothMapClient.EXTRA_SENDER_CONTACT_NAME);
306                    if (senderName == null) {
307                        senderName = "<null>";
308                    }
309
310                    mMessage.setText(intent.getStringExtra(android.content.Intent.EXTRA_TEXT));
311                    mOriginator.setText(senderUri);
312                    mOriginatorDisplayName.setText(senderName);
313                }
314            }
315        }
316    }
317
318    private final BroadcastReceiver mPickerReceiver = new BroadcastReceiver() {
319        @Override
320        public void onReceive(Context context, Intent intent) {
321            String action = intent.getAction();
322
323            Log.v(TAG, "mPickerReceiver got " + action);
324
325            if (BluetoothDevicePicker.ACTION_DEVICE_SELECTED.equals(action)) {
326                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
327                Log.v(TAG, "mPickerReceiver got " + device);
328                mMapProfile.connect(device);
329
330                // The receiver can now be disabled.
331                getContext().unregisterReceiver(mPickerReceiver);
332            }
333        }
334    };
335}