1 /* 2 * Copyright (C) 2014 Akexorcist 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 app.akexorcist.bluetotohspp.library; 18 19 import java.util.ArrayList; 20 import java.util.Set; 21 22 import android.annotation.SuppressLint; 23 import android.bluetooth.BluetoothAdapter; 24 import android.bluetooth.BluetoothDevice; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.os.Handler; 28 import android.os.Message; 29 import android.util.Log; 30 import android.widget.Toast; 31 32 @SuppressLint("NewApi") 33 public class BluetoothSPP { 34 // Listener for Bluetooth Status & Connection 35 private BluetoothStateListener mBluetoothStateListener = null; 36 private OnDataReceivedListener mDataReceivedListener = null; 37 private BluetoothConnectionListener mBluetoothConnectionListener = null; 38 private AutoConnectionListener mAutoConnectionListener = null; 39 40 // Context from activity which call this class 41 private Context mContext; 42 43 // Local Bluetooth adapter 44 private BluetoothAdapter mBluetoothAdapter = null; 45 46 // Member object for the chat services 47 private BluetoothService mChatService = null; 48 49 // Name and Address of the connected device 50 private String mDeviceName = null; 51 private String mDeviceAddress = null; 52 53 private boolean isAutoConnecting = false; 54 private boolean isAutoConnectionEnabled = false; 55 private boolean isConnected = false; 56 private boolean isConnecting = false; 57 private boolean isServiceRunning = false; 58 59 private String keyword = ""; 60 private boolean isAndroid = BluetoothState.DEVICE_ANDROID; 61 private String autoAddress = ""; 62 63 private BluetoothConnectionListener bcl; 64 private int c = 0; 65 BluetoothSPP(Context context)66 public BluetoothSPP(Context context) { 67 Log.i("DEBUGGER_TAG", "BluetoothSPP ctor"); 68 69 mContext = context; 70 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 71 } 72 73 public interface BluetoothStateListener { onServiceStateChanged(int state)74 public void onServiceStateChanged(int state); 75 } 76 77 public interface OnDataReceivedListener { onDataReceived(byte[] data, String message)78 public void onDataReceived(byte[] data, String message); 79 } 80 81 public interface BluetoothConnectionListener { onDeviceConnected(String name, String address)82 public void onDeviceConnected(String name, String address); onDeviceDisconnected()83 public void onDeviceDisconnected(); onDeviceConnectionFailed()84 public void onDeviceConnectionFailed(); 85 } 86 87 public interface AutoConnectionListener { onAutoConnectionStarted()88 public void onAutoConnectionStarted(); onNewConnection(String name, String address)89 public void onNewConnection(String name, String address); 90 } 91 isBluetoothAvailable()92 public boolean isBluetoothAvailable() { 93 try { 94 if (mBluetoothAdapter == null || mBluetoothAdapter.getAddress().equals(null)) 95 return false; 96 } catch (NullPointerException e) { 97 return false; 98 } 99 return true; 100 } 101 isBluetoothEnabled()102 public boolean isBluetoothEnabled() { 103 return mBluetoothAdapter.isEnabled(); 104 } 105 isServiceAvailable()106 public boolean isServiceAvailable() { 107 return mChatService != null; 108 } 109 isAutoConnecting()110 public boolean isAutoConnecting() { 111 return isAutoConnecting; 112 } 113 startDiscovery()114 public boolean startDiscovery() { 115 return mBluetoothAdapter.startDiscovery(); 116 } 117 isDiscovery()118 public boolean isDiscovery() { 119 return mBluetoothAdapter.isDiscovering(); 120 } 121 cancelDiscovery()122 public boolean cancelDiscovery() { 123 return mBluetoothAdapter.cancelDiscovery(); 124 } 125 setupService()126 public void setupService() { 127 mChatService = new BluetoothService(mContext, mHandler); 128 } 129 getBluetoothAdapter()130 public BluetoothAdapter getBluetoothAdapter() { 131 return mBluetoothAdapter; 132 } 133 getServiceState()134 public int getServiceState() { 135 if(mChatService != null) 136 return mChatService.getState(); 137 else 138 return -1; 139 } 140 startService(boolean isAndroid)141 public void startService(boolean isAndroid) { 142 if (mChatService != null) { 143 if (mChatService.getState() == BluetoothState.STATE_NONE) { 144 Log.i("DEBUGGER_TAG", "SPPstartService"); 145 isServiceRunning = true; 146 mChatService.start(isAndroid); 147 BluetoothSPP.this.isAndroid = isAndroid; 148 } 149 } 150 } 151 stopService()152 public void stopService() { 153 if (mChatService != null) { 154 isServiceRunning = false; 155 mChatService.stop(); 156 } 157 new Handler().postDelayed(new Runnable() { 158 public void run() { 159 if (mChatService != null) { 160 isServiceRunning = false; 161 mChatService.stop(); 162 } 163 } 164 }, 500); 165 } 166 setDeviceTarget(boolean isAndroid)167 public void setDeviceTarget(boolean isAndroid) { 168 stopService(); 169 startService(isAndroid); 170 BluetoothSPP.this.isAndroid = isAndroid; 171 } 172 173 @SuppressLint("HandlerLeak") 174 private final Handler mHandler = new Handler() { 175 public void handleMessage(Message msg) { 176 177 switch (msg.what) { 178 case BluetoothState.MESSAGE_WRITE: 179 break; 180 case BluetoothState.MESSAGE_READ: 181 Log.i("DEBUGGER_TAG", "MESSAGE_READ"); 182 byte[] readBuf = (byte[]) msg.obj; 183 String readMessage = new String(readBuf); 184 if(readBuf != null && readBuf.length > 0) { 185 Log.i("DEBUGGER_TAG", readMessage); 186 if(mDataReceivedListener != null) 187 mDataReceivedListener.onDataReceived(readBuf, readMessage); 188 } 189 break; 190 case BluetoothState.MESSAGE_DEVICE_NAME: 191 Log.i("DEBUGGER_TAG", "MESSAGE_DEVICE_NAME"); 192 193 mDeviceName = msg.getData().getString(BluetoothState.DEVICE_NAME); 194 mDeviceAddress = msg.getData().getString(BluetoothState.DEVICE_ADDRESS); 195 if(mBluetoothConnectionListener != null) 196 mBluetoothConnectionListener.onDeviceConnected(mDeviceName, mDeviceAddress); 197 isConnected = true; 198 break; 199 case BluetoothState.MESSAGE_TOAST: 200 Log.i("DEBUGGER_TAG", "MESSAGE_TOAST"); 201 Toast.makeText(mContext, msg.getData().getString(BluetoothState.TOAST) 202 , Toast.LENGTH_SHORT).show(); 203 break; 204 case BluetoothState.MESSAGE_STATE_CHANGE: 205 Log.i("DEBUGGER_TAG", "MESSAGE_STATE_CHANGE"); 206 if(mBluetoothStateListener != null) 207 mBluetoothStateListener.onServiceStateChanged(msg.arg1); 208 209 if(msg.arg1 == BluetoothState.STATE_NONE) 210 Log.i("DEBUGGER_TAG", "State:STATE_NONE"); 211 else if(msg.arg1 == BluetoothState.STATE_LISTEN) 212 Log.i("DEBUGGER_TAG", "State:STATE_LISTEN"); 213 else if(msg.arg1 == BluetoothState.STATE_CONNECTING) 214 Log.i("DEBUGGER_TAG", "State:STATE_CONNECTING"); 215 else if(msg.arg1 == BluetoothState.STATE_CONNECTED) 216 Log.i("DEBUGGER_TAG", "State:STATE_CONNECTED"); 217 218 if(isConnected && msg.arg1 != BluetoothState.STATE_NONE) { 219 Log.i("DEBUGGER_TAG", "State:NONE, maybe stop requested?"); 220 isAutoConnectionEnabled = false; 221 } 222 223 224 225 if(isConnected && msg.arg1 != BluetoothState.STATE_CONNECTED) { 226 if(mBluetoothConnectionListener != null) 227 mBluetoothConnectionListener.onDeviceDisconnected(); 228 if(isAutoConnectionEnabled) { 229 isAutoConnectionEnabled = false; 230 autoConnect(keyword); 231 } 232 Log.i("DEBUGGER_TAG", "Disconnected"); 233 isConnected = false; 234 mDeviceName = null; 235 mDeviceAddress = null; 236 } 237 238 if(!isConnecting && msg.arg1 == BluetoothState.STATE_CONNECTING) { 239 isConnecting = true; 240 Log.i("DEBUGGER_TAG", "isConnecting"); 241 242 } else if(isConnecting) { 243 244 if(msg.arg1 == BluetoothState.STATE_CONNECTING) { 245 Log.i("DEBUGGER_TAG", "stillConnecting"); 246 } 247 248 else if(msg.arg1 != BluetoothState.STATE_CONNECTED) { 249 if(mBluetoothConnectionListener != null) 250 mBluetoothConnectionListener.onDeviceConnectionFailed(); 251 Log.i("DEBUGGER_TAG", "Connection failed"); 252 isConnecting = false; 253 } 254 else{ 255 Log.i("DEBUGGER_TAG", "Connected"); 256 isConnecting = false; 257 } 258 259 } 260 break; 261 } 262 } 263 }; 264 resetAutoConnect()265 public void resetAutoConnect() { 266 isAutoConnectionEnabled = false; 267 } 268 connect(Intent data)269 public void connect(Intent data) { 270 String address = data.getExtras().getString(BluetoothState.EXTRA_DEVICE_ADDRESS); 271 BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); 272 mChatService.connect(device); 273 } 274 connect(String address)275 public void connect(String address) { 276 Log.i("DEBUGGER_TAG", "connectB " + address); 277 BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); 278 mChatService.connect(device); 279 } 280 disconnect()281 public void disconnect() { 282 if(mChatService != null) { 283 isServiceRunning = false; 284 mChatService.stop(); 285 if(mChatService.getState() == BluetoothState.STATE_NONE) { 286 isServiceRunning = true; 287 mChatService.start(BluetoothSPP.this.isAndroid); 288 } 289 } 290 } 291 setBluetoothStateListener(BluetoothStateListener listener)292 public void setBluetoothStateListener (BluetoothStateListener listener) { 293 mBluetoothStateListener = listener; 294 } 295 setOnDataReceivedListener(OnDataReceivedListener listener)296 public void setOnDataReceivedListener (OnDataReceivedListener listener) { 297 mDataReceivedListener = listener; 298 } 299 setBluetoothConnectionListener(BluetoothConnectionListener listener)300 public void setBluetoothConnectionListener (BluetoothConnectionListener listener) { 301 mBluetoothConnectionListener = listener; 302 } 303 setAutoConnectionListener(AutoConnectionListener listener)304 public void setAutoConnectionListener(AutoConnectionListener listener) { 305 mAutoConnectionListener = listener; 306 } 307 enable()308 public void enable() { 309 mBluetoothAdapter.enable(); 310 } 311 send(byte[] data, boolean CRLF)312 public void send(byte[] data, boolean CRLF) { 313 if(mChatService.getState() == BluetoothState.STATE_CONNECTED) { 314 if(CRLF) { 315 byte[] data2 = new byte[data.length + 2]; 316 for(int i = 0 ; i < data.length ; i++) 317 data2[i] = data[i]; 318 data2[data2.length - 2] = 0x0A; 319 data2[data2.length - 1] = 0x0D; 320 mChatService.write(data2); 321 } else { 322 mChatService.write(data); 323 } 324 } 325 } 326 send(String data, boolean CRLF)327 public void send(String data, boolean CRLF) { 328 if(mChatService.getState() == BluetoothState.STATE_CONNECTED) { 329 if(CRLF) 330 data += "\r\n"; 331 mChatService.write(data.getBytes()); 332 } 333 } 334 getConnectedDeviceName()335 public String getConnectedDeviceName() { 336 return mDeviceName; 337 } 338 getConnectedDeviceAddress()339 public String getConnectedDeviceAddress() { 340 return mDeviceAddress; 341 } 342 getPairedDeviceName()343 public String[] getPairedDeviceName() { 344 int c = 0; 345 Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices(); 346 String[] name_list = new String[devices.size()]; 347 for(BluetoothDevice device : devices) { 348 Log.i("DEBUGGER_TAG", "autoconn name" + device.getName()); 349 name_list[c] = device.getName(); 350 c++; 351 } 352 return name_list; 353 } 354 getPairedDeviceAddress()355 public String[] getPairedDeviceAddress() { 356 int c = 0; 357 Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices(); 358 String[] address_list = new String[devices.size()]; 359 for(BluetoothDevice device : devices) { 360 Log.i("DEBUGGER_TAG", "autoconn address" + device.getAddress()); 361 address_list[c] = device.getAddress(); 362 c++; 363 } 364 return address_list; 365 } 366 367 autoConnect(String keywordName)368 public void autoConnect(String keywordName) { 369 Log.i("DEBUGGER_TAG", "autoconnA"); 370 if(!isAutoConnectionEnabled) { 371 Log.i("DEBUGGER_TAG", "autoconnB"); 372 keyword = keywordName; 373 isAutoConnectionEnabled = true; 374 isAutoConnecting = true; 375 if(mAutoConnectionListener != null) 376 mAutoConnectionListener.onAutoConnectionStarted(); 377 final ArrayList<String> arr_filter_address = new ArrayList<String>(); 378 final ArrayList<String> arr_filter_name = new ArrayList<String>(); 379 String[] arr_name = getPairedDeviceName(); 380 String[] arr_address = getPairedDeviceAddress(); 381 for(int i = 0 ; i < arr_name.length ; i++) { 382 if(arr_name[i].contains(keywordName)) { 383 Log.i("DEBUGGER_TAG", "autoconn filter" + arr_address[i]); 384 arr_filter_address.add(arr_address[i]); 385 arr_filter_name.add(arr_name[i]); 386 } 387 } 388 389 bcl = new BluetoothConnectionListener() { 390 public void onDeviceConnected(String name, String address) { 391 bcl = null; 392 isAutoConnecting = false; 393 } 394 395 public void onDeviceDisconnected() { } 396 public void onDeviceConnectionFailed() { 397 Log.e("CHeck", "Failed"); 398 if(isServiceRunning) { 399 if(isAutoConnectionEnabled) { 400 c++; 401 if(c >= arr_filter_address.size()) 402 c = 0; 403 connect(arr_filter_address.get(c)); 404 Log.e("CHeck", "Connect"); 405 if(mAutoConnectionListener != null) 406 mAutoConnectionListener.onNewConnection(arr_filter_name.get(c) 407 , arr_filter_address.get(c)); 408 } else { 409 bcl = null; 410 isAutoConnecting = false; 411 } 412 } 413 } 414 }; 415 416 setBluetoothConnectionListener(bcl); 417 c = 0; 418 if(mAutoConnectionListener != null) 419 mAutoConnectionListener.onNewConnection(arr_name[c], arr_address[c]); 420 if(arr_filter_address.size() > 0){ 421 Log.i("DEBUGGER_TAG", "autoconn" + arr_filter_address.get(c)); 422 connect(arr_filter_address.get(c)); 423 } 424 else 425 Toast.makeText(mContext, "Device name mismatch", Toast.LENGTH_SHORT).show(); 426 } 427 } 428 autoConnectAddress(String address)429 public void autoConnectAddress(String address) { 430 Log.i("DEBUGGER_TAG", "autoconnA"); 431 if(!isAutoConnectionEnabled) { 432 Log.i("DEBUGGER_TAG", "autoconnB"); 433 autoAddress = address; 434 isAutoConnectionEnabled = true; 435 isAutoConnecting = true; 436 if(mAutoConnectionListener != null) 437 mAutoConnectionListener.onAutoConnectionStarted(); 438 439 bcl = new BluetoothConnectionListener() { 440 public void onDeviceConnected(String name, String address) { 441 bcl = null; 442 isAutoConnecting = false; 443 } 444 445 public void onDeviceDisconnected() { } 446 public void onDeviceConnectionFailed() { 447 Log.e("CHeck", "Failed"); 448 if(isServiceRunning) { 449 if(isAutoConnectionEnabled) { 450 connect(autoAddress); 451 Log.e("CHeck", "Connect"); 452 if(mAutoConnectionListener != null) 453 mAutoConnectionListener.onNewConnection(autoAddress, autoAddress); 454 } else { 455 bcl = null; 456 isAutoConnecting = false; 457 } 458 } 459 } 460 }; 461 462 setBluetoothConnectionListener(bcl); 463 464 if(mAutoConnectionListener != null) 465 mAutoConnectionListener.onNewConnection(autoAddress, autoAddress); 466 connect(address); 467 468 } 469 } 470 471 } 472