1 /* 2 * Copyright (C) 2016 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * 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, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 17 package com.googlecode.android_scripting.facade.bluetooth; 18 19 import java.util.HashMap; 20 import java.util.List; 21 import java.util.concurrent.Callable; 22 23 import android.app.Service; 24 import android.bluetooth.BluetoothAdapter; 25 import android.bluetooth.le.AdvertiseCallback; 26 import android.bluetooth.le.AdvertiseData; 27 import android.bluetooth.le.AdvertiseData.Builder; 28 import android.bluetooth.le.AdvertiseSettings; 29 import android.bluetooth.le.BluetoothLeAdvertiser; 30 import android.os.Bundle; 31 import android.os.ParcelUuid; 32 33 import com.googlecode.android_scripting.Log; 34 import com.googlecode.android_scripting.MainThread; 35 import com.googlecode.android_scripting.facade.EventFacade; 36 import com.googlecode.android_scripting.facade.FacadeManager; 37 import com.googlecode.android_scripting.jsonrpc.RpcReceiver; 38 import com.googlecode.android_scripting.rpc.Rpc; 39 import com.googlecode.android_scripting.rpc.RpcParameter; 40 import com.googlecode.android_scripting.ConvertUtils; 41 42 /** 43 * BluetoothLe Advertise functions. 44 */ 45 46 public class BluetoothLeAdvertiseFacade extends RpcReceiver { 47 48 private final EventFacade mEventFacade; 49 private BluetoothAdapter mBluetoothAdapter; 50 private static int BleAdvertiseCallbackCount; 51 private static int BleAdvertiseSettingsCount; 52 private static int BleAdvertiseDataCount; 53 private final HashMap<Integer, myAdvertiseCallback> mAdvertiseCallbackList; 54 private final BluetoothLeAdvertiser mAdvertise; 55 private final Service mService; 56 private Builder mAdvertiseDataBuilder; 57 private android.bluetooth.le.AdvertiseSettings.Builder mAdvertiseSettingsBuilder; 58 private final HashMap<Integer, AdvertiseData> mAdvertiseDataList; 59 private final HashMap<Integer, AdvertiseSettings> mAdvertiseSettingsList; 60 BluetoothLeAdvertiseFacade(FacadeManager manager)61 public BluetoothLeAdvertiseFacade(FacadeManager manager) { 62 super(manager); 63 mService = manager.getService(); 64 mBluetoothAdapter = MainThread.run(mService, 65 new Callable<BluetoothAdapter>() { 66 @Override 67 public BluetoothAdapter call() throws Exception { 68 return BluetoothAdapter.getDefaultAdapter(); 69 } 70 }); 71 mEventFacade = manager.getReceiver(EventFacade.class); 72 mAdvertiseCallbackList = new HashMap<Integer, myAdvertiseCallback>(); 73 mAdvertise = mBluetoothAdapter.getBluetoothLeAdvertiser(); 74 mAdvertiseDataList = new HashMap<Integer, AdvertiseData>(); 75 mAdvertiseSettingsList = new HashMap<Integer, AdvertiseSettings>(); 76 mAdvertiseDataBuilder = new Builder(); 77 mAdvertiseSettingsBuilder = new android.bluetooth.le.AdvertiseSettings.Builder(); 78 } 79 80 /** 81 * Constructs a myAdvertiseCallback obj and returns its index 82 * 83 * @return myAdvertiseCallback.index 84 */ 85 @Rpc(description = "Generate a new myAdvertisement Object") bleGenBleAdvertiseCallback()86 public Integer bleGenBleAdvertiseCallback() { 87 BleAdvertiseCallbackCount += 1; 88 int index = BleAdvertiseCallbackCount; 89 myAdvertiseCallback mCallback = new myAdvertiseCallback(index); 90 mAdvertiseCallbackList.put(mCallback.index, 91 mCallback); 92 return mCallback.index; 93 } 94 95 /** 96 * Constructs a AdvertiseData obj and returns its index 97 * 98 * @return index 99 */ 100 @Rpc(description = "Constructs a new Builder obj for AdvertiseData and returns its index") bleBuildAdvertiseData()101 public Integer bleBuildAdvertiseData() { 102 BleAdvertiseDataCount += 1; 103 int index = BleAdvertiseDataCount; 104 mAdvertiseDataList.put(index, 105 mAdvertiseDataBuilder.build()); 106 mAdvertiseDataBuilder = new Builder(); 107 return index; 108 } 109 110 /** 111 * Constructs a Advertise Settings obj and returns its index 112 * 113 * @return index 114 */ 115 @Rpc(description = "Constructs a new Builder obj for AdvertiseData and returns its index") bleBuildAdvertiseSettings()116 public Integer bleBuildAdvertiseSettings() { 117 BleAdvertiseSettingsCount += 1; 118 int index = BleAdvertiseSettingsCount; 119 mAdvertiseSettingsList.put(index, 120 mAdvertiseSettingsBuilder.build()); 121 mAdvertiseSettingsBuilder = new android.bluetooth.le.AdvertiseSettings.Builder(); 122 return index; 123 } 124 125 /** 126 * Stops a ble advertisement 127 * 128 * @param index the id of the advertisement to stop advertising on 129 * @throws Exception 130 */ 131 @Rpc(description = "Stops an ongoing ble advertisement") bleStopBleAdvertising( @pcParametername = "index") Integer index)132 public void bleStopBleAdvertising( 133 @RpcParameter(name = "index") 134 Integer index) throws Exception { 135 if (mAdvertiseCallbackList.get(index) != null) { 136 Log.d("bluetooth_le mAdvertise " + index); 137 mAdvertise.stopAdvertising(mAdvertiseCallbackList 138 .get(index)); 139 } else { 140 throw new Exception("Invalid index input:" + Integer.toString(index)); 141 } 142 } 143 144 /** 145 * Starts ble advertising 146 * 147 * @param callbackIndex The advertisementCallback index 148 * @param dataIndex the AdvertiseData index 149 * @param settingsIndex the advertisementsettings index 150 * @throws Exception 151 */ 152 @Rpc(description = "Starts ble advertisement") bleStartBleAdvertising( @pcParametername = "callbackIndex") Integer callbackIndex, @RpcParameter(name = "dataIndex") Integer dataIndex, @RpcParameter(name = "settingsIndex") Integer settingsIndex )153 public void bleStartBleAdvertising( 154 @RpcParameter(name = "callbackIndex") 155 Integer callbackIndex, 156 @RpcParameter(name = "dataIndex") 157 Integer dataIndex, 158 @RpcParameter(name = "settingsIndex") 159 Integer settingsIndex 160 ) throws Exception { 161 AdvertiseData mData = new AdvertiseData.Builder().build(); 162 AdvertiseSettings mSettings = new AdvertiseSettings.Builder().build(); 163 if (mAdvertiseDataList.get(dataIndex) != null) { 164 mData = mAdvertiseDataList.get(dataIndex); 165 } else { 166 throw new Exception("Invalid dataIndex input:" + Integer.toString(dataIndex)); 167 } 168 if (mAdvertiseSettingsList.get(settingsIndex) != null) { 169 mSettings = mAdvertiseSettingsList.get(settingsIndex); 170 } else { 171 throw new Exception("Invalid settingsIndex input:" + Integer.toString(settingsIndex)); 172 } 173 if (mAdvertiseCallbackList.get(callbackIndex) != null) { 174 Log.d("bluetooth_le starting a background advertisement on callback index: " 175 + Integer.toString(callbackIndex)); 176 mAdvertise 177 .startAdvertising(mSettings, mData, mAdvertiseCallbackList.get(callbackIndex)); 178 } else { 179 throw new Exception("Invalid callbackIndex input" + Integer.toString(callbackIndex)); 180 } 181 } 182 183 /** 184 * Starts ble advertising with a scanResponse. ScanResponses are created in the same way 185 * AdvertiseData is created since they share the same object type. 186 * 187 * @param callbackIndex The advertisementCallback index 188 * @param dataIndex the AdvertiseData index 189 * @param settingsIndex the advertisementsettings index 190 * @param scanResponseIndex the scanResponse index 191 * @throws Exception 192 */ 193 @Rpc(description = "Starts ble advertisement") bleStartBleAdvertisingWithScanResponse( @pcParametername = "callbackIndex") Integer callbackIndex, @RpcParameter(name = "dataIndex") Integer dataIndex, @RpcParameter(name = "settingsIndex") Integer settingsIndex, @RpcParameter(name = "scanResponseIndex") Integer scanResponseIndex )194 public void bleStartBleAdvertisingWithScanResponse( 195 @RpcParameter(name = "callbackIndex") 196 Integer callbackIndex, 197 @RpcParameter(name = "dataIndex") 198 Integer dataIndex, 199 @RpcParameter(name = "settingsIndex") 200 Integer settingsIndex, 201 @RpcParameter(name = "scanResponseIndex") 202 Integer scanResponseIndex 203 ) throws Exception { 204 AdvertiseData mData = new AdvertiseData.Builder().build(); 205 AdvertiseSettings mSettings = new AdvertiseSettings.Builder().build(); 206 AdvertiseData mScanResponse = new AdvertiseData.Builder().build(); 207 208 if (mAdvertiseDataList.get(dataIndex) != null) { 209 mData = mAdvertiseDataList.get(dataIndex); 210 } else { 211 throw new Exception("Invalid dataIndex input:" + Integer.toString(dataIndex)); 212 } 213 if (mAdvertiseSettingsList.get(settingsIndex) != null) { 214 mSettings = mAdvertiseSettingsList.get(settingsIndex); 215 } else { 216 throw new Exception("Invalid settingsIndex input:" + Integer.toString(settingsIndex)); 217 } 218 if (mAdvertiseDataList.get(scanResponseIndex) != null) { 219 mScanResponse = mAdvertiseDataList.get(scanResponseIndex); 220 } else { 221 throw new Exception("Invalid scanResponseIndex input:" 222 + Integer.toString(settingsIndex)); 223 } 224 if (mAdvertiseCallbackList.get(callbackIndex) != null) { 225 Log.d("bluetooth_le starting a background advertise on callback index: " 226 + Integer.toString(callbackIndex)); 227 mAdvertise 228 .startAdvertising(mSettings, mData, mScanResponse, 229 mAdvertiseCallbackList.get(callbackIndex)); 230 } else { 231 throw new Exception("Invalid callbackIndex input" + Integer.toString(callbackIndex)); 232 } 233 } 234 235 /** 236 * Get ble advertisement settings mode 237 * 238 * @param index the advertise settings object to use 239 * @return the mode of the advertise settings object 240 * @throws Exception 241 */ 242 @Rpc(description = "Get ble advertisement settings mode") bleGetAdvertiseSettingsMode( @pcParametername = "index") Integer index)243 public int bleGetAdvertiseSettingsMode( 244 @RpcParameter(name = "index") 245 Integer index) throws Exception { 246 if (mAdvertiseSettingsList.get(index) != null) { 247 AdvertiseSettings mSettings = mAdvertiseSettingsList.get(index); 248 return mSettings.getMode(); 249 } else { 250 throw new Exception("Invalid index input:" + Integer.toString(index)); 251 } 252 } 253 254 /** 255 * Get ble advertisement settings tx power level 256 * 257 * @param index the advertise settings object to use 258 * @return the tx power level of the advertise settings object 259 * @throws Exception 260 */ 261 @Rpc(description = "Get ble advertisement settings tx power level") bleGetAdvertiseSettingsTxPowerLevel( @pcParametername = "index") Integer index)262 public int bleGetAdvertiseSettingsTxPowerLevel( 263 @RpcParameter(name = "index") 264 Integer index) throws Exception { 265 if (mAdvertiseSettingsList.get(index) != null) { 266 AdvertiseSettings mSettings = mAdvertiseSettingsList.get(index); 267 return mSettings.getTxPowerLevel(); 268 } else { 269 throw new Exception("Invalid index input:" + Integer.toString(index)); 270 } 271 } 272 273 /** 274 * Get ble advertisement settings isConnectable value 275 * 276 * @param index the advertise settings object to use 277 * @return the boolean value whether the advertisement will indicate 278 * connectable. 279 * @throws Exception 280 */ 281 @Rpc(description = "Get ble advertisement settings isConnectable value") bleGetAdvertiseSettingsIsConnectable( @pcParametername = "index") Integer index)282 public boolean bleGetAdvertiseSettingsIsConnectable( 283 @RpcParameter(name = "index") 284 Integer index) throws Exception { 285 if (mAdvertiseSettingsList.get(index) != null) { 286 AdvertiseSettings mSettings = mAdvertiseSettingsList.get(index); 287 return mSettings.isConnectable(); 288 } else { 289 throw new Exception("Invalid index input:" + Integer.toString(index)); 290 } 291 } 292 293 /** 294 * Get ble advertisement data include tx power level 295 * 296 * @param index the advertise data object to use 297 * @return True if include tx power level, false otherwise 298 * @throws Exception 299 */ 300 @Rpc(description = "Get ble advertisement data include tx power level") bleGetAdvertiseDataIncludeTxPowerLevel( @pcParametername = "index") Integer index)301 public Boolean bleGetAdvertiseDataIncludeTxPowerLevel( 302 @RpcParameter(name = "index") 303 Integer index) throws Exception { 304 if (mAdvertiseDataList.get(index) != null) { 305 AdvertiseData mData = mAdvertiseDataList.get(index); 306 return mData.getIncludeTxPowerLevel(); 307 } else { 308 throw new Exception("Invalid index input:" + Integer.toString(index)); 309 } 310 } 311 312 /** 313 * Get ble advertisement data manufacturer specific data 314 * 315 * @param index the advertise data object to use 316 * @param manufacturerId the id that corresponds to the manufacturer specific data. 317 * @return the corresponding manufacturer specific data to the manufacturer id. 318 * @throws Exception 319 */ 320 @Rpc(description = "Get ble advertisement data manufacturer specific data") bleGetAdvertiseDataManufacturerSpecificData( @pcParametername = "index") Integer index, @RpcParameter(name = "manufacturerId") Integer manufacturerId)321 public String bleGetAdvertiseDataManufacturerSpecificData( 322 @RpcParameter(name = "index") 323 Integer index, 324 @RpcParameter(name = "manufacturerId") 325 Integer manufacturerId) throws Exception { 326 if (mAdvertiseDataList.get(index) != null) { 327 AdvertiseData mData = mAdvertiseDataList.get(index); 328 if (mData.getManufacturerSpecificData() != null) { 329 return ConvertUtils.convertByteArrayToString(mData.getManufacturerSpecificData().get(manufacturerId)); 330 } else { 331 throw new Exception("Invalid manufacturerId input:" + Integer.toString(manufacturerId)); 332 } 333 } else { 334 throw new Exception("Invalid index input:" + Integer.toString(index)); 335 336 } 337 } 338 339 /** 340 * Get ble advertisement data include device name 341 * 342 * @param index the advertise data object to use 343 * @return the advertisement data's include device name 344 * @throws Exception 345 */ 346 @Rpc(description = "Get ble advertisement include device name") bleGetAdvertiseDataIncludeDeviceName( @pcParametername = "index") Integer index)347 public Boolean bleGetAdvertiseDataIncludeDeviceName( 348 @RpcParameter(name = "index") 349 Integer index) throws Exception { 350 if (mAdvertiseDataList.get(index) != null) { 351 AdvertiseData mData = mAdvertiseDataList.get(index); 352 return mData.getIncludeDeviceName(); 353 } else { 354 throw new Exception("Invalid index input:" + Integer.toString(index)); 355 } 356 } 357 358 /** 359 * Get ble advertisement Service Data 360 * 361 * @param index the advertise data object to use 362 * @param serviceUuid the uuid corresponding to the service data. 363 * @return the advertisement data's service data 364 * @throws Exception 365 */ 366 @Rpc(description = "Get ble advertisement Service Data") bleGetAdvertiseDataServiceData( @pcParametername = "index") Integer index, @RpcParameter(name = "serviceUuid") String serviceUuid)367 public String bleGetAdvertiseDataServiceData( 368 @RpcParameter(name = "index") 369 Integer index, 370 @RpcParameter(name = "serviceUuid") 371 String serviceUuid) throws Exception { 372 ParcelUuid uuidKey = ParcelUuid.fromString(serviceUuid); 373 if (mAdvertiseDataList.get(index) != null) { 374 AdvertiseData mData = mAdvertiseDataList.get(index); 375 if (mData.getServiceData().containsKey(uuidKey)) { 376 return ConvertUtils.convertByteArrayToString(mData.getServiceData().get(uuidKey)); 377 } else { 378 throw new Exception("Invalid serviceUuid input:" + serviceUuid); 379 } 380 } else { 381 throw new Exception("Invalid index input:" + Integer.toString(index)); 382 } 383 } 384 385 /** 386 * Get ble advertisement Service Uuids 387 * 388 * @param index the advertise data object to use 389 * @return the advertisement data's Service Uuids 390 * @throws Exception 391 */ 392 @Rpc(description = "Get ble advertisement Service Uuids") bleGetAdvertiseDataServiceUuids( @pcParametername = "index") Integer index)393 public List<ParcelUuid> bleGetAdvertiseDataServiceUuids( 394 @RpcParameter(name = "index") 395 Integer index) throws Exception { 396 if (mAdvertiseDataList.get(index) != null) { 397 AdvertiseData mData = mAdvertiseDataList.get(index); 398 return mData.getServiceUuids(); 399 } else { 400 throw new Exception("Invalid index input:" + Integer.toString(index)); 401 } 402 } 403 404 /** 405 * Set ble advertisement data service uuids 406 * 407 * @param uuidList 408 * @throws Exception 409 */ 410 @Rpc(description = "Set ble advertisement data service uuids") bleSetAdvertiseDataSetServiceUuids( @pcParametername = "uuidList") String[] uuidList )411 public void bleSetAdvertiseDataSetServiceUuids( 412 @RpcParameter(name = "uuidList") 413 String[] uuidList 414 ) { 415 for (String uuid : uuidList) { 416 mAdvertiseDataBuilder.addServiceUuid(ParcelUuid.fromString(uuid)); 417 } 418 } 419 420 /** 421 * Set ble advertise data service uuids 422 * 423 * @param serviceDataUuid 424 * @param serviceData 425 * @throws Exception 426 */ 427 @Rpc(description = "Set ble advertise data service uuids") bleAddAdvertiseDataServiceData( @pcParametername = "serviceDataUuid") String serviceDataUuid, @RpcParameter(name = "serviceData") String serviceData )428 public void bleAddAdvertiseDataServiceData( 429 @RpcParameter(name = "serviceDataUuid") 430 String serviceDataUuid, 431 @RpcParameter(name = "serviceData") 432 String serviceData 433 ) { 434 mAdvertiseDataBuilder.addServiceData( 435 ParcelUuid.fromString(serviceDataUuid), 436 ConvertUtils.convertStringToByteArray(serviceData)); 437 } 438 439 /** 440 * Set ble advertise data manufacturer id 441 * 442 * @param manufacturerId the manufacturer id to set 443 * @param manufacturerSpecificData the manufacturer specific data to set 444 * @throws Exception 445 */ 446 @Rpc(description = "Set ble advertise data manufacturerId") bleAddAdvertiseDataManufacturerId( @pcParametername = "manufacturerId") Integer manufacturerId, @RpcParameter(name = "manufacturerSpecificData") String manufacturerSpecificData )447 public void bleAddAdvertiseDataManufacturerId( 448 @RpcParameter(name = "manufacturerId") 449 Integer manufacturerId, 450 @RpcParameter(name = "manufacturerSpecificData") 451 String manufacturerSpecificData 452 ) { 453 mAdvertiseDataBuilder.addManufacturerData(manufacturerId, 454 ConvertUtils.convertStringToByteArray(manufacturerSpecificData)); 455 } 456 457 /** 458 * Set ble advertise settings advertise mode 459 * 460 * @param advertiseMode 461 * @throws Exception 462 */ 463 @Rpc(description = "Set ble advertise settings advertise mode") bleSetAdvertiseSettingsAdvertiseMode( @pcParametername = "advertiseMode") Integer advertiseMode )464 public void bleSetAdvertiseSettingsAdvertiseMode( 465 @RpcParameter(name = "advertiseMode") 466 Integer advertiseMode 467 ) { 468 mAdvertiseSettingsBuilder.setAdvertiseMode(advertiseMode); 469 } 470 471 /** 472 * Set ble advertise settings tx power level 473 * 474 * @param txPowerLevel the tx power level to set 475 * @throws Exception 476 */ 477 @Rpc(description = "Set ble advertise settings tx power level") bleSetAdvertiseSettingsTxPowerLevel( @pcParametername = "txPowerLevel") Integer txPowerLevel )478 public void bleSetAdvertiseSettingsTxPowerLevel( 479 @RpcParameter(name = "txPowerLevel") 480 Integer txPowerLevel 481 ) { 482 mAdvertiseSettingsBuilder.setTxPowerLevel(txPowerLevel); 483 } 484 485 /** 486 * Set ble advertise settings the isConnectable value 487 * 488 * @param type the isConnectable value 489 * @throws Exception 490 */ 491 @Rpc(description = "Set ble advertise settings isConnectable value") bleSetAdvertiseSettingsIsConnectable( @pcParametername = "value") Boolean value )492 public void bleSetAdvertiseSettingsIsConnectable( 493 @RpcParameter(name = "value") 494 Boolean value 495 ) { 496 mAdvertiseSettingsBuilder.setConnectable(value); 497 } 498 499 /** 500 * Set ble advertisement data include tx power level 501 * 502 * @param includeTxPowerLevel boolean whether to include the tx power level or not in the 503 * advertisement 504 */ 505 @Rpc(description = "Set ble advertisement data include tx power level") bleSetAdvertiseDataIncludeTxPowerLevel( @pcParametername = "includeTxPowerLevel") Boolean includeTxPowerLevel )506 public void bleSetAdvertiseDataIncludeTxPowerLevel( 507 @RpcParameter(name = "includeTxPowerLevel") 508 Boolean includeTxPowerLevel 509 ) { 510 mAdvertiseDataBuilder.setIncludeTxPowerLevel(includeTxPowerLevel); 511 } 512 513 /** 514 * Set ble advertisement settings set timeout 515 * 516 * @param timeoutSeconds Limit advertising to a given amount of time. 517 */ 518 @Rpc(description = "Set ble advertisement data include tx power level") bleSetAdvertiseSettingsTimeout( @pcParametername = "timeoutSeconds") Integer timeoutSeconds )519 public void bleSetAdvertiseSettingsTimeout( 520 @RpcParameter(name = "timeoutSeconds") 521 Integer timeoutSeconds 522 ) { 523 mAdvertiseSettingsBuilder.setTimeout(timeoutSeconds); 524 } 525 526 /** 527 * Set ble advertisement data include device name 528 * 529 * @param includeDeviceName boolean whether to include device name or not in the 530 * advertisement 531 */ 532 @Rpc(description = "Set ble advertisement data include device name") bleSetAdvertiseDataIncludeDeviceName( @pcParametername = "includeDeviceName") Boolean includeDeviceName )533 public void bleSetAdvertiseDataIncludeDeviceName( 534 @RpcParameter(name = "includeDeviceName") 535 Boolean includeDeviceName 536 ) { 537 mAdvertiseDataBuilder.setIncludeDeviceName(includeDeviceName); 538 } 539 540 private class myAdvertiseCallback extends AdvertiseCallback { 541 public Integer index; 542 private final Bundle mResults; 543 String mEventType; 544 myAdvertiseCallback(int idx)545 public myAdvertiseCallback(int idx) { 546 index = idx; 547 mEventType = "BleAdvertise"; 548 mResults = new Bundle(); 549 } 550 551 @Override onStartSuccess(AdvertiseSettings settingsInEffect)552 public void onStartSuccess(AdvertiseSettings settingsInEffect) { 553 Log.d("bluetooth_le_advertisement onSuccess " + mEventType + " " 554 + index); 555 mResults.putString("Type", "onSuccess"); 556 mResults.putParcelable("SettingsInEffect", settingsInEffect); 557 mEventFacade.postEvent(mEventType + index + "onSuccess", mResults.clone()); 558 mResults.clear(); 559 } 560 561 @Override onStartFailure(int errorCode)562 public void onStartFailure(int errorCode) { 563 String errorString = "UNKNOWN_ERROR_CODE"; 564 if (errorCode == AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED) { 565 errorString = "ADVERTISE_FAILED_ALREADY_STARTED"; 566 } else if (errorCode == AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE) { 567 errorString = "ADVERTISE_FAILED_DATA_TOO_LARGE"; 568 } else if (errorCode == AdvertiseCallback.ADVERTISE_FAILED_FEATURE_UNSUPPORTED) { 569 errorString = "ADVERTISE_FAILED_FEATURE_UNSUPPORTED"; 570 } else if (errorCode == AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR) { 571 errorString = "ADVERTISE_FAILED_INTERNAL_ERROR"; 572 } else if (errorCode == AdvertiseCallback.ADVERTISE_FAILED_TOO_MANY_ADVERTISERS) { 573 errorString = "ADVERTISE_FAILED_TOO_MANY_ADVERTISERS"; 574 } 575 Log.d("bluetooth_le_advertisement onFailure " + mEventType + " " 576 + index + " error " + errorString); 577 mResults.putString("Type", "onFailure"); 578 mResults.putInt("ErrorCode", errorCode); 579 mResults.putString("Error", errorString); 580 mEventFacade.postEvent(mEventType + index + "onFailure", 581 mResults.clone()); 582 mResults.clear(); 583 } 584 } 585 586 @Override shutdown()587 public void shutdown() { 588 if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) { 589 for (myAdvertiseCallback mAdvertise : mAdvertiseCallbackList 590 .values()) { 591 if (mAdvertise != null) { 592 try{ 593 mBluetoothAdapter.getBluetoothLeAdvertiser() 594 .stopAdvertising(mAdvertise); 595 } catch (NullPointerException e) { 596 Log.e("Failed to stop ble advertising.", e); 597 } 598 } 599 } 600 } 601 mAdvertiseCallbackList.clear(); 602 mAdvertiseSettingsList.clear(); 603 mAdvertiseDataList.clear(); 604 } 605 } 606