added code to close the netlink socket.
[contrib/iotivity.git] / java / examples-android / simplebase / src / main / java / org / iotivity / base / examples / BluetoothFragment.java
1 /*
2  * ******************************************************************
3  *
4  * Copyright 2016 Samsung Electronics All Rights Reserved.
5  *
6  * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21  */
22
23 package org.iotivity.base.examples;
24
25 import android.app.Activity;
26 import android.app.Fragment;
27 import android.bluetooth.BluetoothAdapter;
28 import android.bluetooth.BluetoothDevice;
29 import android.bluetooth.BluetoothGatt;
30 import android.bluetooth.BluetoothManager;
31 import android.bluetooth.le.BluetoothLeScanner;
32 import android.bluetooth.le.ScanCallback;
33 import android.bluetooth.le.ScanFilter;
34 import android.bluetooth.le.ScanResult;
35 import android.bluetooth.le.ScanSettings;
36 import android.content.Context;
37 import android.content.Intent;
38 import android.content.pm.PackageManager;
39 import android.os.Build;
40 import android.os.Bundle;
41 import android.os.Handler;
42 import android.os.ParcelUuid;
43 import android.util.Log;
44 import android.view.LayoutInflater;
45 import android.view.View;
46 import android.view.ViewGroup;
47 import android.widget.AdapterView;
48 import android.widget.ArrayAdapter;
49 import android.widget.Button;
50 import android.widget.ListView;
51
52 import org.iotivity.base.ModeType;
53 import org.iotivity.base.OcConnectivityType;
54 import org.iotivity.base.OcException;
55 import org.iotivity.base.OcPlatform;
56 import org.iotivity.base.OcResource;
57 import org.iotivity.base.PlatformConfig;
58 import org.iotivity.base.QualityOfService;
59 import org.iotivity.base.ServiceType;
60 import org.iotivity.ca.CaBtPairingInterface;
61 import org.iotivity.ca.CaInterface;
62
63 import java.util.ArrayList;
64 import java.util.EnumSet;
65 import java.util.List;
66
67 /**
68  * This class is for testing of Bluetooth util.
69  */
70 public class BluetoothFragment extends Fragment implements
71         CaInterface.OnBtDeviceFoundListener,
72         CaInterface.OnConnectionManagerStateListener {
73
74     private static final String      TAG                  = "OCF_SIMPLE_BLUETOOTH";
75     private static final String      CA_GATT_SERVICE_UUID = "ADE3D529-C784-4F63-A987-EB69F70EE816";
76
77     private Activity                   mActivity;
78     private Context                    mContext;
79     private BluetoothAdapter           mBluetoothAdapter;
80     private static final int           REQUEST_ENABLE_BT  = 1;
81     private static final long          SCAN_PERIOD        = 10000;
82     private BluetoothLeScanner         mLEScanner;
83     private ScanSettings               mScanSettings;
84     private List<ScanFilter>           mScanFilters;
85     private BluetoothGatt              mGatt;
86     private ArrayList<String>          mItems;
87     private ArrayList<BluetoothDevice> mBluetoothDevices;
88     private ArrayAdapter<String>       mAdapters;
89
90     private boolean                    mIsScanning;
91     private boolean                    mIsBTSelected;
92
93     private Button                     mBtButton;
94     private Button                     mLeButton;
95
96     @Override
97     public View onCreateView(LayoutInflater inflater, ViewGroup container,
98                              Bundle savedInstanceState) {
99         View rootView = inflater.inflate(R.layout.fragment_bluetooth, container, false);
100         mBtButton = (Button) rootView.findViewById(R.id.btn_bt);
101         mBtButton.setOnClickListener(scanButtonListener(true));
102
103         mLeButton = (Button) rootView.findViewById(R.id.btn_le);
104         mLeButton.setOnClickListener(scanButtonListener(false));
105
106         ListView listView = (ListView) rootView.findViewById(R.id.list_view);
107         mItems = new ArrayList<String>();
108         mAdapters = new ArrayAdapter<String>(mActivity, android.R.layout.simple_list_item_1, mItems);
109         listView.setAdapter(mAdapters);
110         listView.setOnItemClickListener(itemClickListener);
111         listView.setOnItemLongClickListener(itemLongClickListener);
112
113         return rootView;
114     }
115
116     @Override
117     public void onCreate(Bundle savedInstanceState) {
118         super.onCreate(savedInstanceState);
119         mActivity = getActivity();
120         mContext = mActivity.getBaseContext();
121
122         mBluetoothDevices = new ArrayList<BluetoothDevice>();
123
124         if (!mActivity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
125             Common.showToast(mContext, "BLE Not Supported");
126         }
127         final BluetoothManager bluetoothManager = (BluetoothManager) mActivity
128                                                   .getSystemService(Context.BLUETOOTH_SERVICE);
129         mBluetoothAdapter = bluetoothManager.getAdapter();
130
131         PlatformConfig cfg = new PlatformConfig(mActivity, mContext,
132                                                 ServiceType.IN_PROC,
133                                                 ModeType.CLIENT,
134                                                 Common.IP_ADDRESS,
135                                                 Common.IP_PORT,
136                                                 QualityOfService.LOW);
137
138         OcPlatform.Configure(cfg);
139         CaInterface.startBtPairingService(mContext, this);
140         CaInterface.startManagerService(mContext, this);
141     }
142
143     @Override
144     public void onResume() {
145         super.onResume();
146         if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
147             Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
148             startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
149         } else {
150             if (Build.VERSION.SDK_INT >= 21) {
151                 mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
152                 if (mScanSettings == null) {
153                     mScanSettings = new ScanSettings.Builder()
154                                                .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
155                                                .build();
156                 }
157
158                 if (mScanFilters == null) {
159                     mScanFilters = new ArrayList<ScanFilter>();
160                     ScanFilter scanFilter = new ScanFilter.Builder()
161                             .setServiceUuid(ParcelUuid.fromString(CA_GATT_SERVICE_UUID)).build();
162                     mScanFilters.add(scanFilter);
163                 }
164             }
165         }
166     }
167
168     @Override
169     public void onPause() {
170         super.onPause();
171         if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {
172             scanLeDevice(false);
173         }
174     }
175
176     @Override
177     public void onDestroy() {
178         super.onDestroy();
179         CaInterface.stopBtPairingService();
180         CaInterface.stopManagerService();
181         CaBtPairingInterface.destroyEdrInterface();
182         if (mGatt != null) {
183             mGatt.close();
184             mGatt = null;
185         }
186     }
187
188     @Override
189     public void onActivityResult(int requestCode, int resultCode, Intent data) {
190         if (requestCode == REQUEST_ENABLE_BT) {
191             if (resultCode == Activity.RESULT_CANCELED) {
192                 mActivity.finish();
193                 return;
194             }
195         }
196         super.onActivityResult(requestCode, resultCode, data);
197     }
198
199     View.OnClickListener scanButtonListener(final boolean isBT) {
200         return new View.OnClickListener() {
201             @Override
202             public void onClick(View view) {
203                 if (!mIsScanning) {
204                     mItems.clear();
205                     mBluetoothDevices.clear();
206                     mAdapters.notifyDataSetChanged();
207                     mIsBTSelected = isBT;
208                 }
209
210                 if (isBT) {
211                     if (mIsScanning) {
212                         // BT Stop
213                         try {
214                             CaInterface.stopScan();
215                         } catch (OcException e) {
216                             e.printStackTrace();
217                         }
218                         mBtButton.setText(R.string.bt_scan);
219                         mLeButton.setVisibility(View.VISIBLE);
220                     } else {
221                         // BT Scan
222                         try {
223                             CaInterface.startScan();
224                         } catch (OcException e) {
225                             e.printStackTrace();
226                         }
227                         mBtButton.setText(R.string.stop_scan);
228                         mLeButton.setVisibility(View.GONE);
229                     }
230                 } else {
231                     if (mIsScanning) {
232                         // LE Stop
233                         mLeButton.setText(R.string.le_scan);
234                         mBtButton.setVisibility(View.VISIBLE);
235                     } else {
236                         // LE Scan
237                         mLeButton.setText(R.string.stop_scan);
238                         mBtButton.setVisibility(View.GONE);
239                     }
240                     scanLeDevice(!mIsScanning);
241                 }
242                 mIsScanning = !mIsScanning;
243             }
244         };
245     }
246
247     @Override
248     public synchronized void onBtDeviceFound(BluetoothDevice device) throws OcException {
249         Log.i(TAG, "onBtDeviceFound address : " + device.getAddress());
250
251         addItemToList(device);
252     }
253
254     private AdapterView.OnItemClickListener itemClickListener = new AdapterView
255                                                                 .OnItemClickListener() {
256         public void onItemClick(AdapterView<?> adapterView, View clickedView, int pos, long id) {
257             StringBuilder sb = new StringBuilder();
258
259             if (mIsBTSelected) {
260                 sb.append("Pairing with : ");
261                 try {
262                     CaInterface.createBond(mBluetoothDevices.get(pos));
263                 } catch (OcException e) {
264                     e.printStackTrace();
265                 }
266             } else {
267                 sb.append("Set Connect with : ");
268                 try {
269                     final String address = mBluetoothDevices.get(pos).getAddress();
270                     CaInterface.setAutoConnectionDevice(address);
271                     OcPlatform.OnResourceFoundListener resourceFoundListener =
272                             new OcPlatform.OnResourceFoundListener() {
273                         @Override
274                         public void onResourceFound(OcResource ocResource) {
275                             Log.i(TAG, "onResourceFound : " + ocResource.getUri());
276                         }
277                     };
278                     OcPlatform.findResource("", address + OcPlatform.WELL_KNOWN_QUERY,
279                                             EnumSet.of(OcConnectivityType.CT_ADAPTER_GATT_BTLE),
280                                             resourceFoundListener, QualityOfService.LOW);
281                 } catch (OcException e) {
282                     e.printStackTrace();
283                 }
284             }
285             Common.showToast(mContext, sb.append(mItems.get(pos)).toString());
286         }
287     };
288
289     private AdapterView.OnItemLongClickListener itemLongClickListener = new AdapterView
290                                                                         .OnItemLongClickListener() {
291         @Override
292         public boolean onItemLongClick(AdapterView<?> adapterView, View view, int pos, long id) {
293             StringBuilder sb = new StringBuilder();
294
295             if (!mIsBTSelected) {
296                 sb.append("Unset Connect with : ");
297                 try {
298                     CaInterface.unsetAutoConnectionDevice(mBluetoothDevices.get(pos).getAddress());
299                 } catch (OcException e) {
300                     e.printStackTrace();
301                 }
302             }
303             Common.showToast(mContext, sb.append(mItems.get(pos)).toString());
304
305             return true;
306         }
307     };
308
309     private void scanLeDevice(final boolean enable) {
310         if (enable) {
311             new Handler().postDelayed(new Runnable() {
312                 @Override
313                 public void run() {
314                     mLEScanner.stopScan(mScanCallback);
315                 }
316             }, SCAN_PERIOD);
317
318             mLEScanner.startScan(mScanFilters, mScanSettings, mScanCallback);
319         } else {
320             mLEScanner.stopScan(mScanCallback);
321         }
322     }
323
324     private ScanCallback mScanCallback = new ScanCallback() {
325         @Override
326         public void onScanResult(int callbackType, ScanResult result) {
327             Log.i(TAG, "onScanResult : " + result.toString());
328
329             addItemToList(result.getDevice());
330         }
331
332         @Override
333         public void onScanFailed(int errorCode) {
334             Log.e(TAG, "Scan Failed, Error Code : " + errorCode);
335         }
336     };
337
338     private void addItemToList(BluetoothDevice btDevice) {
339         StringBuilder sb = new StringBuilder(btDevice.toString());
340         sb.append(" (");
341         if (btDevice.getName() != null) {
342             sb.append(btDevice.getName().toString());
343         } else {
344             sb.append("NULL");
345         }
346         sb.append(")");
347
348         if (mItems.contains(sb.toString())) {
349             // Duplicate
350         } else {
351             // add item
352             mItems.add(sb.toString());
353             mBluetoothDevices.add(btDevice);
354             mAdapters.notifyDataSetChanged();
355         }
356     }
357
358     @Override
359     public void onAdapterStateChanged(OcConnectivityType type, boolean enabled) {
360         final String msg = getString(R.string.action_onadapterstatechanged) + enabled;
361         Log.i(TAG, msg);
362         mActivity.runOnUiThread(new Runnable() {
363             @Override
364             public void run() {
365                 Common.showToast(mContext, msg);
366             }
367         });
368     }
369
370     @Override
371     public void onConnectionStateChanged(OcConnectivityType type,
372                                          String address, boolean connected) {
373         Log.i(TAG, "onConnectionStateChanged address: " + address);
374         final String msg = getString(R.string.action_onconnectionstatechanged) + connected;
375         Log.i(TAG, msg);
376         mActivity.runOnUiThread(new Runnable() {
377             @Override
378             public void run() {
379                 Common.showToast(mContext, msg);
380             }
381         });
382     }
383 }