@Override
  public void touch() {
    if (this.callback == null) return;

    try {
      this.advertiser.stopAdvertising(callback);
    } catch (Exception ex) {
    }

    this.callback = new BleAdvCallback(this, queue);

    ManufacturerData data = listener.onAdvertisementDataRequested();
    if (data == null) stopAdvertise();

    advertise(data);
  }
  @Override
  public void startAdvertise(long durationMs) {
    if (Build.VERSION.SDK_INT < 21) {
      queue.dispatch(
          new Runnable() {
            @Override
            public void run() {
              listener.onAdvertiseStopped(BleAdvertiser.this, true);
            }
          });
      return;
    }

    if (this.callback != null) return;

    if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
      Logger.error("Bluetooth LE is not supported on this device.");
      queue.dispatch(
          new Runnable() {
            @Override
            public void run() {
              listener.onAdvertiseStopped(BleAdvertiser.this, true);
            }
          });
      return;
    }

    final BluetoothManager bluetoothManager =
        (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
    this.adapter = bluetoothManager.getAdapter();

    if (this.adapter == null) {
      Logger.error("Bluetooth is not supported on this device.");
      queue.dispatch(
          new Runnable() {
            @Override
            public void run() {
              listener.onAdvertiseStopped(BleAdvertiser.this, true);
            }
          });
      return;
    }

    this.manager = bluetoothManager;

    if (!adapter.isMultipleAdvertisementSupported()) {
      Logger.warn("ble peripheral mode is not supported on this device.");

      queue.dispatch(
          new Runnable() {
            @Override
            public void run() {
              listener.onAdvertiseStopped(BleAdvertiser.this, true);
            }
          });
      return;
    }

    this.advertiser = adapter.getBluetoothLeAdvertiser();
    if (advertiser == null) {
      Logger.error("ble peripheral failed to get BluetoothLeAdvertiser instance");
      queue.dispatch(
          new Runnable() {
            @Override
            public void run() {
              listener.onAdvertiseStopped(BleAdvertiser.this, true);
            }
          });
      return;
    }

    this.callback = new BleAdvCallback(this, queue);

    queue.dispatch(
        new Runnable() {
          @Override
          public void run() {
            // Logger.debug("ble advertise started");
            listener.onAdvertiseStarted(BleAdvertiser.this);
          }
        });

    stopCommand =
        queue.dispatchAfter(
            durationMs,
            new Runnable() {
              @Override
              public void run() {
                stopAdvertise();
              }
            });

    ManufacturerData data = listener.onAdvertisementDataRequested();
    if (data == null) stopAdvertise();

    advertise(data);
  } // startAdvertise()