1*90c8c64dSAndroid Build Coastguard Worker /*
2*90c8c64dSAndroid Build Coastguard Worker  * Copyright (C) 2014 The Android Open Source Project
3*90c8c64dSAndroid Build Coastguard Worker  *
4*90c8c64dSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*90c8c64dSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*90c8c64dSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*90c8c64dSAndroid Build Coastguard Worker  *
8*90c8c64dSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*90c8c64dSAndroid Build Coastguard Worker  *
10*90c8c64dSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*90c8c64dSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*90c8c64dSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*90c8c64dSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*90c8c64dSAndroid Build Coastguard Worker  * limitations under the License.
15*90c8c64dSAndroid Build Coastguard Worker  */
16*90c8c64dSAndroid Build Coastguard Worker 
17*90c8c64dSAndroid Build Coastguard Worker package com.example.android.bluetoothchat;
18*90c8c64dSAndroid Build Coastguard Worker 
19*90c8c64dSAndroid Build Coastguard Worker import android.app.ActionBar;
20*90c8c64dSAndroid Build Coastguard Worker import android.app.Activity;
21*90c8c64dSAndroid Build Coastguard Worker import android.bluetooth.BluetoothAdapter;
22*90c8c64dSAndroid Build Coastguard Worker import android.bluetooth.BluetoothDevice;
23*90c8c64dSAndroid Build Coastguard Worker import android.content.Intent;
24*90c8c64dSAndroid Build Coastguard Worker import android.os.Bundle;
25*90c8c64dSAndroid Build Coastguard Worker import android.os.Handler;
26*90c8c64dSAndroid Build Coastguard Worker import android.os.Message;
27*90c8c64dSAndroid Build Coastguard Worker import android.support.annotation.Nullable;
28*90c8c64dSAndroid Build Coastguard Worker import android.support.v4.app.Fragment;
29*90c8c64dSAndroid Build Coastguard Worker import android.support.v4.app.FragmentActivity;
30*90c8c64dSAndroid Build Coastguard Worker import android.view.KeyEvent;
31*90c8c64dSAndroid Build Coastguard Worker import android.view.LayoutInflater;
32*90c8c64dSAndroid Build Coastguard Worker import android.view.Menu;
33*90c8c64dSAndroid Build Coastguard Worker import android.view.MenuInflater;
34*90c8c64dSAndroid Build Coastguard Worker import android.view.MenuItem;
35*90c8c64dSAndroid Build Coastguard Worker import android.view.View;
36*90c8c64dSAndroid Build Coastguard Worker import android.view.ViewGroup;
37*90c8c64dSAndroid Build Coastguard Worker import android.view.inputmethod.EditorInfo;
38*90c8c64dSAndroid Build Coastguard Worker import android.widget.ArrayAdapter;
39*90c8c64dSAndroid Build Coastguard Worker import android.widget.Button;
40*90c8c64dSAndroid Build Coastguard Worker import android.widget.EditText;
41*90c8c64dSAndroid Build Coastguard Worker import android.widget.ListView;
42*90c8c64dSAndroid Build Coastguard Worker import android.widget.TextView;
43*90c8c64dSAndroid Build Coastguard Worker import android.widget.Toast;
44*90c8c64dSAndroid Build Coastguard Worker 
45*90c8c64dSAndroid Build Coastguard Worker import com.example.android.common.logger.Log;
46*90c8c64dSAndroid Build Coastguard Worker 
47*90c8c64dSAndroid Build Coastguard Worker /**
48*90c8c64dSAndroid Build Coastguard Worker  * This fragment controls Bluetooth to communicate with other devices.
49*90c8c64dSAndroid Build Coastguard Worker  */
50*90c8c64dSAndroid Build Coastguard Worker public class BluetoothChatFragment extends Fragment {
51*90c8c64dSAndroid Build Coastguard Worker 
52*90c8c64dSAndroid Build Coastguard Worker     private static final String TAG = "BluetoothChatFragment";
53*90c8c64dSAndroid Build Coastguard Worker 
54*90c8c64dSAndroid Build Coastguard Worker     // Intent request codes
55*90c8c64dSAndroid Build Coastguard Worker     private static final int REQUEST_CONNECT_DEVICE_SECURE = 1;
56*90c8c64dSAndroid Build Coastguard Worker     private static final int REQUEST_CONNECT_DEVICE_INSECURE = 2;
57*90c8c64dSAndroid Build Coastguard Worker     private static final int REQUEST_ENABLE_BT = 3;
58*90c8c64dSAndroid Build Coastguard Worker 
59*90c8c64dSAndroid Build Coastguard Worker     // Layout Views
60*90c8c64dSAndroid Build Coastguard Worker     private ListView mConversationView;
61*90c8c64dSAndroid Build Coastguard Worker     private EditText mOutEditText;
62*90c8c64dSAndroid Build Coastguard Worker     private Button mSendButton;
63*90c8c64dSAndroid Build Coastguard Worker 
64*90c8c64dSAndroid Build Coastguard Worker     /**
65*90c8c64dSAndroid Build Coastguard Worker      * Name of the connected device
66*90c8c64dSAndroid Build Coastguard Worker      */
67*90c8c64dSAndroid Build Coastguard Worker     private String mConnectedDeviceName = null;
68*90c8c64dSAndroid Build Coastguard Worker 
69*90c8c64dSAndroid Build Coastguard Worker     /**
70*90c8c64dSAndroid Build Coastguard Worker      * Array adapter for the conversation thread
71*90c8c64dSAndroid Build Coastguard Worker      */
72*90c8c64dSAndroid Build Coastguard Worker     private ArrayAdapter<String> mConversationArrayAdapter;
73*90c8c64dSAndroid Build Coastguard Worker 
74*90c8c64dSAndroid Build Coastguard Worker     /**
75*90c8c64dSAndroid Build Coastguard Worker      * String buffer for outgoing messages
76*90c8c64dSAndroid Build Coastguard Worker      */
77*90c8c64dSAndroid Build Coastguard Worker     private StringBuffer mOutStringBuffer;
78*90c8c64dSAndroid Build Coastguard Worker 
79*90c8c64dSAndroid Build Coastguard Worker     /**
80*90c8c64dSAndroid Build Coastguard Worker      * Local Bluetooth adapter
81*90c8c64dSAndroid Build Coastguard Worker      */
82*90c8c64dSAndroid Build Coastguard Worker     private BluetoothAdapter mBluetoothAdapter = null;
83*90c8c64dSAndroid Build Coastguard Worker 
84*90c8c64dSAndroid Build Coastguard Worker     /**
85*90c8c64dSAndroid Build Coastguard Worker      * Member object for the chat services
86*90c8c64dSAndroid Build Coastguard Worker      */
87*90c8c64dSAndroid Build Coastguard Worker     private BluetoothChatService mChatService = null;
88*90c8c64dSAndroid Build Coastguard Worker 
89*90c8c64dSAndroid Build Coastguard Worker     @Override
onCreate(Bundle savedInstanceState)90*90c8c64dSAndroid Build Coastguard Worker     public void onCreate(Bundle savedInstanceState) {
91*90c8c64dSAndroid Build Coastguard Worker         super.onCreate(savedInstanceState);
92*90c8c64dSAndroid Build Coastguard Worker         setHasOptionsMenu(true);
93*90c8c64dSAndroid Build Coastguard Worker         // Get local Bluetooth adapter
94*90c8c64dSAndroid Build Coastguard Worker         mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
95*90c8c64dSAndroid Build Coastguard Worker 
96*90c8c64dSAndroid Build Coastguard Worker         // If the adapter is null, then Bluetooth is not supported
97*90c8c64dSAndroid Build Coastguard Worker         if (mBluetoothAdapter == null) {
98*90c8c64dSAndroid Build Coastguard Worker             FragmentActivity activity = getActivity();
99*90c8c64dSAndroid Build Coastguard Worker             Toast.makeText(activity, "Bluetooth is not available", Toast.LENGTH_LONG).show();
100*90c8c64dSAndroid Build Coastguard Worker             activity.finish();
101*90c8c64dSAndroid Build Coastguard Worker         }
102*90c8c64dSAndroid Build Coastguard Worker     }
103*90c8c64dSAndroid Build Coastguard Worker 
104*90c8c64dSAndroid Build Coastguard Worker 
105*90c8c64dSAndroid Build Coastguard Worker     @Override
onStart()106*90c8c64dSAndroid Build Coastguard Worker     public void onStart() {
107*90c8c64dSAndroid Build Coastguard Worker         super.onStart();
108*90c8c64dSAndroid Build Coastguard Worker         // If BT is not on, request that it be enabled.
109*90c8c64dSAndroid Build Coastguard Worker         // setupChat() will then be called during onActivityResult
110*90c8c64dSAndroid Build Coastguard Worker         if (!mBluetoothAdapter.isEnabled()) {
111*90c8c64dSAndroid Build Coastguard Worker             Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
112*90c8c64dSAndroid Build Coastguard Worker             startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
113*90c8c64dSAndroid Build Coastguard Worker             // Otherwise, setup the chat session
114*90c8c64dSAndroid Build Coastguard Worker         } else if (mChatService == null) {
115*90c8c64dSAndroid Build Coastguard Worker             setupChat();
116*90c8c64dSAndroid Build Coastguard Worker         }
117*90c8c64dSAndroid Build Coastguard Worker     }
118*90c8c64dSAndroid Build Coastguard Worker 
119*90c8c64dSAndroid Build Coastguard Worker     @Override
onDestroy()120*90c8c64dSAndroid Build Coastguard Worker     public void onDestroy() {
121*90c8c64dSAndroid Build Coastguard Worker         super.onDestroy();
122*90c8c64dSAndroid Build Coastguard Worker         if (mChatService != null) {
123*90c8c64dSAndroid Build Coastguard Worker             mChatService.stop();
124*90c8c64dSAndroid Build Coastguard Worker         }
125*90c8c64dSAndroid Build Coastguard Worker     }
126*90c8c64dSAndroid Build Coastguard Worker 
127*90c8c64dSAndroid Build Coastguard Worker     @Override
onResume()128*90c8c64dSAndroid Build Coastguard Worker     public void onResume() {
129*90c8c64dSAndroid Build Coastguard Worker         super.onResume();
130*90c8c64dSAndroid Build Coastguard Worker 
131*90c8c64dSAndroid Build Coastguard Worker         // Performing this check in onResume() covers the case in which BT was
132*90c8c64dSAndroid Build Coastguard Worker         // not enabled during onStart(), so we were paused to enable it...
133*90c8c64dSAndroid Build Coastguard Worker         // onResume() will be called when ACTION_REQUEST_ENABLE activity returns.
134*90c8c64dSAndroid Build Coastguard Worker         if (mChatService != null) {
135*90c8c64dSAndroid Build Coastguard Worker             // Only if the state is STATE_NONE, do we know that we haven't started already
136*90c8c64dSAndroid Build Coastguard Worker             if (mChatService.getState() == BluetoothChatService.STATE_NONE) {
137*90c8c64dSAndroid Build Coastguard Worker                 // Start the Bluetooth chat services
138*90c8c64dSAndroid Build Coastguard Worker                 mChatService.start();
139*90c8c64dSAndroid Build Coastguard Worker             }
140*90c8c64dSAndroid Build Coastguard Worker         }
141*90c8c64dSAndroid Build Coastguard Worker     }
142*90c8c64dSAndroid Build Coastguard Worker 
143*90c8c64dSAndroid Build Coastguard Worker     @Override
onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)144*90c8c64dSAndroid Build Coastguard Worker     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
145*90c8c64dSAndroid Build Coastguard Worker                              @Nullable Bundle savedInstanceState) {
146*90c8c64dSAndroid Build Coastguard Worker         return inflater.inflate(R.layout.fragment_bluetooth_chat, container, false);
147*90c8c64dSAndroid Build Coastguard Worker     }
148*90c8c64dSAndroid Build Coastguard Worker 
149*90c8c64dSAndroid Build Coastguard Worker     @Override
onViewCreated(View view, @Nullable Bundle savedInstanceState)150*90c8c64dSAndroid Build Coastguard Worker     public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
151*90c8c64dSAndroid Build Coastguard Worker         mConversationView = (ListView) view.findViewById(R.id.in);
152*90c8c64dSAndroid Build Coastguard Worker         mOutEditText = (EditText) view.findViewById(R.id.edit_text_out);
153*90c8c64dSAndroid Build Coastguard Worker         mSendButton = (Button) view.findViewById(R.id.button_send);
154*90c8c64dSAndroid Build Coastguard Worker     }
155*90c8c64dSAndroid Build Coastguard Worker 
156*90c8c64dSAndroid Build Coastguard Worker     /**
157*90c8c64dSAndroid Build Coastguard Worker      * Set up the UI and background operations for chat.
158*90c8c64dSAndroid Build Coastguard Worker      */
setupChat()159*90c8c64dSAndroid Build Coastguard Worker     private void setupChat() {
160*90c8c64dSAndroid Build Coastguard Worker         Log.d(TAG, "setupChat()");
161*90c8c64dSAndroid Build Coastguard Worker 
162*90c8c64dSAndroid Build Coastguard Worker         // Initialize the array adapter for the conversation thread
163*90c8c64dSAndroid Build Coastguard Worker         mConversationArrayAdapter = new ArrayAdapter<String>(getActivity(), R.layout.message);
164*90c8c64dSAndroid Build Coastguard Worker 
165*90c8c64dSAndroid Build Coastguard Worker         mConversationView.setAdapter(mConversationArrayAdapter);
166*90c8c64dSAndroid Build Coastguard Worker 
167*90c8c64dSAndroid Build Coastguard Worker         // Initialize the compose field with a listener for the return key
168*90c8c64dSAndroid Build Coastguard Worker         mOutEditText.setOnEditorActionListener(mWriteListener);
169*90c8c64dSAndroid Build Coastguard Worker 
170*90c8c64dSAndroid Build Coastguard Worker         // Initialize the send button with a listener that for click events
171*90c8c64dSAndroid Build Coastguard Worker         mSendButton.setOnClickListener(new View.OnClickListener() {
172*90c8c64dSAndroid Build Coastguard Worker             public void onClick(View v) {
173*90c8c64dSAndroid Build Coastguard Worker                 // Send a message using content of the edit text widget
174*90c8c64dSAndroid Build Coastguard Worker                 View view = getView();
175*90c8c64dSAndroid Build Coastguard Worker                 if (null != view) {
176*90c8c64dSAndroid Build Coastguard Worker                     TextView textView = (TextView) view.findViewById(R.id.edit_text_out);
177*90c8c64dSAndroid Build Coastguard Worker                     String message = textView.getText().toString();
178*90c8c64dSAndroid Build Coastguard Worker                     sendMessage(message);
179*90c8c64dSAndroid Build Coastguard Worker                 }
180*90c8c64dSAndroid Build Coastguard Worker             }
181*90c8c64dSAndroid Build Coastguard Worker         });
182*90c8c64dSAndroid Build Coastguard Worker 
183*90c8c64dSAndroid Build Coastguard Worker         // Initialize the BluetoothChatService to perform bluetooth connections
184*90c8c64dSAndroid Build Coastguard Worker         mChatService = new BluetoothChatService(getActivity(), mHandler);
185*90c8c64dSAndroid Build Coastguard Worker 
186*90c8c64dSAndroid Build Coastguard Worker         // Initialize the buffer for outgoing messages
187*90c8c64dSAndroid Build Coastguard Worker         mOutStringBuffer = new StringBuffer("");
188*90c8c64dSAndroid Build Coastguard Worker     }
189*90c8c64dSAndroid Build Coastguard Worker 
190*90c8c64dSAndroid Build Coastguard Worker     /**
191*90c8c64dSAndroid Build Coastguard Worker      * Makes this device discoverable for 300 seconds (5 minutes).
192*90c8c64dSAndroid Build Coastguard Worker      */
ensureDiscoverable()193*90c8c64dSAndroid Build Coastguard Worker     private void ensureDiscoverable() {
194*90c8c64dSAndroid Build Coastguard Worker         if (mBluetoothAdapter.getScanMode() !=
195*90c8c64dSAndroid Build Coastguard Worker                 BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
196*90c8c64dSAndroid Build Coastguard Worker             Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
197*90c8c64dSAndroid Build Coastguard Worker             discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
198*90c8c64dSAndroid Build Coastguard Worker             startActivity(discoverableIntent);
199*90c8c64dSAndroid Build Coastguard Worker         }
200*90c8c64dSAndroid Build Coastguard Worker     }
201*90c8c64dSAndroid Build Coastguard Worker 
202*90c8c64dSAndroid Build Coastguard Worker     /**
203*90c8c64dSAndroid Build Coastguard Worker      * Sends a message.
204*90c8c64dSAndroid Build Coastguard Worker      *
205*90c8c64dSAndroid Build Coastguard Worker      * @param message A string of text to send.
206*90c8c64dSAndroid Build Coastguard Worker      */
sendMessage(String message)207*90c8c64dSAndroid Build Coastguard Worker     private void sendMessage(String message) {
208*90c8c64dSAndroid Build Coastguard Worker         // Check that we're actually connected before trying anything
209*90c8c64dSAndroid Build Coastguard Worker         if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) {
210*90c8c64dSAndroid Build Coastguard Worker             Toast.makeText(getActivity(), R.string.not_connected, Toast.LENGTH_SHORT).show();
211*90c8c64dSAndroid Build Coastguard Worker             return;
212*90c8c64dSAndroid Build Coastguard Worker         }
213*90c8c64dSAndroid Build Coastguard Worker 
214*90c8c64dSAndroid Build Coastguard Worker         // Check that there's actually something to send
215*90c8c64dSAndroid Build Coastguard Worker         if (message.length() > 0) {
216*90c8c64dSAndroid Build Coastguard Worker             // Get the message bytes and tell the BluetoothChatService to write
217*90c8c64dSAndroid Build Coastguard Worker             byte[] send = message.getBytes();
218*90c8c64dSAndroid Build Coastguard Worker             mChatService.write(send);
219*90c8c64dSAndroid Build Coastguard Worker 
220*90c8c64dSAndroid Build Coastguard Worker             // Reset out string buffer to zero and clear the edit text field
221*90c8c64dSAndroid Build Coastguard Worker             mOutStringBuffer.setLength(0);
222*90c8c64dSAndroid Build Coastguard Worker             mOutEditText.setText(mOutStringBuffer);
223*90c8c64dSAndroid Build Coastguard Worker         }
224*90c8c64dSAndroid Build Coastguard Worker     }
225*90c8c64dSAndroid Build Coastguard Worker 
226*90c8c64dSAndroid Build Coastguard Worker     /**
227*90c8c64dSAndroid Build Coastguard Worker      * The action listener for the EditText widget, to listen for the return key
228*90c8c64dSAndroid Build Coastguard Worker      */
229*90c8c64dSAndroid Build Coastguard Worker     private TextView.OnEditorActionListener mWriteListener
230*90c8c64dSAndroid Build Coastguard Worker             = new TextView.OnEditorActionListener() {
231*90c8c64dSAndroid Build Coastguard Worker         public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
232*90c8c64dSAndroid Build Coastguard Worker             // If the action is a key-up event on the return key, send the message
233*90c8c64dSAndroid Build Coastguard Worker             if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_UP) {
234*90c8c64dSAndroid Build Coastguard Worker                 String message = view.getText().toString();
235*90c8c64dSAndroid Build Coastguard Worker                 sendMessage(message);
236*90c8c64dSAndroid Build Coastguard Worker             }
237*90c8c64dSAndroid Build Coastguard Worker             return true;
238*90c8c64dSAndroid Build Coastguard Worker         }
239*90c8c64dSAndroid Build Coastguard Worker     };
240*90c8c64dSAndroid Build Coastguard Worker 
241*90c8c64dSAndroid Build Coastguard Worker     /**
242*90c8c64dSAndroid Build Coastguard Worker      * Updates the status on the action bar.
243*90c8c64dSAndroid Build Coastguard Worker      *
244*90c8c64dSAndroid Build Coastguard Worker      * @param resId a string resource ID
245*90c8c64dSAndroid Build Coastguard Worker      */
setStatus(int resId)246*90c8c64dSAndroid Build Coastguard Worker     private void setStatus(int resId) {
247*90c8c64dSAndroid Build Coastguard Worker         FragmentActivity activity = getActivity();
248*90c8c64dSAndroid Build Coastguard Worker         if (null == activity) {
249*90c8c64dSAndroid Build Coastguard Worker             return;
250*90c8c64dSAndroid Build Coastguard Worker         }
251*90c8c64dSAndroid Build Coastguard Worker         final ActionBar actionBar = activity.getActionBar();
252*90c8c64dSAndroid Build Coastguard Worker         if (null == actionBar) {
253*90c8c64dSAndroid Build Coastguard Worker             return;
254*90c8c64dSAndroid Build Coastguard Worker         }
255*90c8c64dSAndroid Build Coastguard Worker         actionBar.setSubtitle(resId);
256*90c8c64dSAndroid Build Coastguard Worker     }
257*90c8c64dSAndroid Build Coastguard Worker 
258*90c8c64dSAndroid Build Coastguard Worker     /**
259*90c8c64dSAndroid Build Coastguard Worker      * Updates the status on the action bar.
260*90c8c64dSAndroid Build Coastguard Worker      *
261*90c8c64dSAndroid Build Coastguard Worker      * @param subTitle status
262*90c8c64dSAndroid Build Coastguard Worker      */
setStatus(CharSequence subTitle)263*90c8c64dSAndroid Build Coastguard Worker     private void setStatus(CharSequence subTitle) {
264*90c8c64dSAndroid Build Coastguard Worker         FragmentActivity activity = getActivity();
265*90c8c64dSAndroid Build Coastguard Worker         if (null == activity) {
266*90c8c64dSAndroid Build Coastguard Worker             return;
267*90c8c64dSAndroid Build Coastguard Worker         }
268*90c8c64dSAndroid Build Coastguard Worker         final ActionBar actionBar = activity.getActionBar();
269*90c8c64dSAndroid Build Coastguard Worker         if (null == actionBar) {
270*90c8c64dSAndroid Build Coastguard Worker             return;
271*90c8c64dSAndroid Build Coastguard Worker         }
272*90c8c64dSAndroid Build Coastguard Worker         actionBar.setSubtitle(subTitle);
273*90c8c64dSAndroid Build Coastguard Worker     }
274*90c8c64dSAndroid Build Coastguard Worker 
275*90c8c64dSAndroid Build Coastguard Worker     /**
276*90c8c64dSAndroid Build Coastguard Worker      * The Handler that gets information back from the BluetoothChatService
277*90c8c64dSAndroid Build Coastguard Worker      */
278*90c8c64dSAndroid Build Coastguard Worker     private final Handler mHandler = new Handler() {
279*90c8c64dSAndroid Build Coastguard Worker         @Override
280*90c8c64dSAndroid Build Coastguard Worker         public void handleMessage(Message msg) {
281*90c8c64dSAndroid Build Coastguard Worker             FragmentActivity activity = getActivity();
282*90c8c64dSAndroid Build Coastguard Worker             switch (msg.what) {
283*90c8c64dSAndroid Build Coastguard Worker                 case Constants.MESSAGE_STATE_CHANGE:
284*90c8c64dSAndroid Build Coastguard Worker                     switch (msg.arg1) {
285*90c8c64dSAndroid Build Coastguard Worker                         case BluetoothChatService.STATE_CONNECTED:
286*90c8c64dSAndroid Build Coastguard Worker                             setStatus(getString(R.string.title_connected_to, mConnectedDeviceName));
287*90c8c64dSAndroid Build Coastguard Worker                             mConversationArrayAdapter.clear();
288*90c8c64dSAndroid Build Coastguard Worker                             break;
289*90c8c64dSAndroid Build Coastguard Worker                         case BluetoothChatService.STATE_CONNECTING:
290*90c8c64dSAndroid Build Coastguard Worker                             setStatus(R.string.title_connecting);
291*90c8c64dSAndroid Build Coastguard Worker                             break;
292*90c8c64dSAndroid Build Coastguard Worker                         case BluetoothChatService.STATE_LISTEN:
293*90c8c64dSAndroid Build Coastguard Worker                         case BluetoothChatService.STATE_NONE:
294*90c8c64dSAndroid Build Coastguard Worker                             setStatus(R.string.title_not_connected);
295*90c8c64dSAndroid Build Coastguard Worker                             break;
296*90c8c64dSAndroid Build Coastguard Worker                     }
297*90c8c64dSAndroid Build Coastguard Worker                     break;
298*90c8c64dSAndroid Build Coastguard Worker                 case Constants.MESSAGE_WRITE:
299*90c8c64dSAndroid Build Coastguard Worker                     byte[] writeBuf = (byte[]) msg.obj;
300*90c8c64dSAndroid Build Coastguard Worker                     // construct a string from the buffer
301*90c8c64dSAndroid Build Coastguard Worker                     String writeMessage = new String(writeBuf);
302*90c8c64dSAndroid Build Coastguard Worker                     mConversationArrayAdapter.add("Me:  " + writeMessage);
303*90c8c64dSAndroid Build Coastguard Worker                     break;
304*90c8c64dSAndroid Build Coastguard Worker                 case Constants.MESSAGE_READ:
305*90c8c64dSAndroid Build Coastguard Worker                     byte[] readBuf = (byte[]) msg.obj;
306*90c8c64dSAndroid Build Coastguard Worker                     // construct a string from the valid bytes in the buffer
307*90c8c64dSAndroid Build Coastguard Worker                     String readMessage = new String(readBuf, 0, msg.arg1);
308*90c8c64dSAndroid Build Coastguard Worker                     mConversationArrayAdapter.add(mConnectedDeviceName + ":  " + readMessage);
309*90c8c64dSAndroid Build Coastguard Worker                     break;
310*90c8c64dSAndroid Build Coastguard Worker                 case Constants.MESSAGE_DEVICE_NAME:
311*90c8c64dSAndroid Build Coastguard Worker                     // save the connected device's name
312*90c8c64dSAndroid Build Coastguard Worker                     mConnectedDeviceName = msg.getData().getString(Constants.DEVICE_NAME);
313*90c8c64dSAndroid Build Coastguard Worker                     if (null != activity) {
314*90c8c64dSAndroid Build Coastguard Worker                         Toast.makeText(activity, "Connected to "
315*90c8c64dSAndroid Build Coastguard Worker                                 + mConnectedDeviceName, Toast.LENGTH_SHORT).show();
316*90c8c64dSAndroid Build Coastguard Worker                     }
317*90c8c64dSAndroid Build Coastguard Worker                     break;
318*90c8c64dSAndroid Build Coastguard Worker                 case Constants.MESSAGE_TOAST:
319*90c8c64dSAndroid Build Coastguard Worker                     if (null != activity) {
320*90c8c64dSAndroid Build Coastguard Worker                         Toast.makeText(activity, msg.getData().getString(Constants.TOAST),
321*90c8c64dSAndroid Build Coastguard Worker                                 Toast.LENGTH_SHORT).show();
322*90c8c64dSAndroid Build Coastguard Worker                     }
323*90c8c64dSAndroid Build Coastguard Worker                     break;
324*90c8c64dSAndroid Build Coastguard Worker             }
325*90c8c64dSAndroid Build Coastguard Worker         }
326*90c8c64dSAndroid Build Coastguard Worker     };
327*90c8c64dSAndroid Build Coastguard Worker 
onActivityResult(int requestCode, int resultCode, Intent data)328*90c8c64dSAndroid Build Coastguard Worker     public void onActivityResult(int requestCode, int resultCode, Intent data) {
329*90c8c64dSAndroid Build Coastguard Worker         switch (requestCode) {
330*90c8c64dSAndroid Build Coastguard Worker             case REQUEST_CONNECT_DEVICE_SECURE:
331*90c8c64dSAndroid Build Coastguard Worker                 // When DeviceListActivity returns with a device to connect
332*90c8c64dSAndroid Build Coastguard Worker                 if (resultCode == Activity.RESULT_OK) {
333*90c8c64dSAndroid Build Coastguard Worker                     connectDevice(data, true);
334*90c8c64dSAndroid Build Coastguard Worker                 }
335*90c8c64dSAndroid Build Coastguard Worker                 break;
336*90c8c64dSAndroid Build Coastguard Worker             case REQUEST_CONNECT_DEVICE_INSECURE:
337*90c8c64dSAndroid Build Coastguard Worker                 // When DeviceListActivity returns with a device to connect
338*90c8c64dSAndroid Build Coastguard Worker                 if (resultCode == Activity.RESULT_OK) {
339*90c8c64dSAndroid Build Coastguard Worker                     connectDevice(data, false);
340*90c8c64dSAndroid Build Coastguard Worker                 }
341*90c8c64dSAndroid Build Coastguard Worker                 break;
342*90c8c64dSAndroid Build Coastguard Worker             case REQUEST_ENABLE_BT:
343*90c8c64dSAndroid Build Coastguard Worker                 // When the request to enable Bluetooth returns
344*90c8c64dSAndroid Build Coastguard Worker                 if (resultCode == Activity.RESULT_OK) {
345*90c8c64dSAndroid Build Coastguard Worker                     // Bluetooth is now enabled, so set up a chat session
346*90c8c64dSAndroid Build Coastguard Worker                     setupChat();
347*90c8c64dSAndroid Build Coastguard Worker                 } else {
348*90c8c64dSAndroid Build Coastguard Worker                     // User did not enable Bluetooth or an error occurred
349*90c8c64dSAndroid Build Coastguard Worker                     Log.d(TAG, "BT not enabled");
350*90c8c64dSAndroid Build Coastguard Worker                     Toast.makeText(getActivity(), R.string.bt_not_enabled_leaving,
351*90c8c64dSAndroid Build Coastguard Worker                             Toast.LENGTH_SHORT).show();
352*90c8c64dSAndroid Build Coastguard Worker                     getActivity().finish();
353*90c8c64dSAndroid Build Coastguard Worker                 }
354*90c8c64dSAndroid Build Coastguard Worker         }
355*90c8c64dSAndroid Build Coastguard Worker     }
356*90c8c64dSAndroid Build Coastguard Worker 
357*90c8c64dSAndroid Build Coastguard Worker     /**
358*90c8c64dSAndroid Build Coastguard Worker      * Establish connection with other device
359*90c8c64dSAndroid Build Coastguard Worker      *
360*90c8c64dSAndroid Build Coastguard Worker      * @param data   An {@link Intent} with {@link DeviceListActivity#EXTRA_DEVICE_ADDRESS} extra.
361*90c8c64dSAndroid Build Coastguard Worker      * @param secure Socket Security type - Secure (true) , Insecure (false)
362*90c8c64dSAndroid Build Coastguard Worker      */
connectDevice(Intent data, boolean secure)363*90c8c64dSAndroid Build Coastguard Worker     private void connectDevice(Intent data, boolean secure) {
364*90c8c64dSAndroid Build Coastguard Worker         // Get the device MAC address
365*90c8c64dSAndroid Build Coastguard Worker         String address = data.getExtras()
366*90c8c64dSAndroid Build Coastguard Worker                 .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
367*90c8c64dSAndroid Build Coastguard Worker         // Get the BluetoothDevice object
368*90c8c64dSAndroid Build Coastguard Worker         BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
369*90c8c64dSAndroid Build Coastguard Worker         // Attempt to connect to the device
370*90c8c64dSAndroid Build Coastguard Worker         mChatService.connect(device, secure);
371*90c8c64dSAndroid Build Coastguard Worker     }
372*90c8c64dSAndroid Build Coastguard Worker 
373*90c8c64dSAndroid Build Coastguard Worker     @Override
onCreateOptionsMenu(Menu menu, MenuInflater inflater)374*90c8c64dSAndroid Build Coastguard Worker     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
375*90c8c64dSAndroid Build Coastguard Worker         inflater.inflate(R.menu.bluetooth_chat, menu);
376*90c8c64dSAndroid Build Coastguard Worker     }
377*90c8c64dSAndroid Build Coastguard Worker 
378*90c8c64dSAndroid Build Coastguard Worker     @Override
onOptionsItemSelected(MenuItem item)379*90c8c64dSAndroid Build Coastguard Worker     public boolean onOptionsItemSelected(MenuItem item) {
380*90c8c64dSAndroid Build Coastguard Worker         switch (item.getItemId()) {
381*90c8c64dSAndroid Build Coastguard Worker             case R.id.secure_connect_scan: {
382*90c8c64dSAndroid Build Coastguard Worker                 // Launch the DeviceListActivity to see devices and do scan
383*90c8c64dSAndroid Build Coastguard Worker                 Intent serverIntent = new Intent(getActivity(), DeviceListActivity.class);
384*90c8c64dSAndroid Build Coastguard Worker                 startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_SECURE);
385*90c8c64dSAndroid Build Coastguard Worker                 return true;
386*90c8c64dSAndroid Build Coastguard Worker             }
387*90c8c64dSAndroid Build Coastguard Worker             case R.id.insecure_connect_scan: {
388*90c8c64dSAndroid Build Coastguard Worker                 // Launch the DeviceListActivity to see devices and do scan
389*90c8c64dSAndroid Build Coastguard Worker                 Intent serverIntent = new Intent(getActivity(), DeviceListActivity.class);
390*90c8c64dSAndroid Build Coastguard Worker                 startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_INSECURE);
391*90c8c64dSAndroid Build Coastguard Worker                 return true;
392*90c8c64dSAndroid Build Coastguard Worker             }
393*90c8c64dSAndroid Build Coastguard Worker             case R.id.discoverable: {
394*90c8c64dSAndroid Build Coastguard Worker                 // Ensure this device is discoverable by others
395*90c8c64dSAndroid Build Coastguard Worker                 ensureDiscoverable();
396*90c8c64dSAndroid Build Coastguard Worker                 return true;
397*90c8c64dSAndroid Build Coastguard Worker             }
398*90c8c64dSAndroid Build Coastguard Worker         }
399*90c8c64dSAndroid Build Coastguard Worker         return false;
400*90c8c64dSAndroid Build Coastguard Worker     }
401*90c8c64dSAndroid Build Coastguard Worker 
402*90c8c64dSAndroid Build Coastguard Worker }
403