Here are the examples of the java api android.bluetooth.IBluetoothManager taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.
3 Examples
19
Source : PeriodicAdvertisingManager.java
with Apache License 2.0
from lulululbj
with Apache License 2.0
from lulululbj
/**
* This clreplaced provides methods to perform periodic advertising related
* operations. An application can register for periodic advertisements using
* {@link PeriodicAdvertisingManager#registerSync}.
* <p>
* Use {@link BluetoothAdapter#getPeriodicAdvertisingManager()} to get an
* instance of {@link PeriodicAdvertisingManager}.
* <p>
* <b>Note:</b> Most of the methods here require
* {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
*
* @hide
*/
public final clreplaced PeriodicAdvertisingManager {
private static final String TAG = "PeriodicAdvertisingManager";
private static final int SKIP_MIN = 0;
private static final int SKIP_MAX = 499;
private static final int TIMEOUT_MIN = 10;
private static final int TIMEOUT_MAX = 16384;
private static final int SYNC_STARTING = -1;
private final IBluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
/* maps callback, to callback wrapper and sync handle */
Map<PeriodicAdvertisingCallback, IPeriodicAdvertisingCallback> /* callbackWrapper */
mCallbackWrappers;
/**
* Use {@link BluetoothAdapter#getBluetoothLeScanner()} instead.
*
* @param bluetoothManager BluetoothManager that conducts overall Bluetooth Management.
* @hide
*/
public PeriodicAdvertisingManager(IBluetoothManager bluetoothManager) {
mBluetoothManager = bluetoothManager;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mCallbackWrappers = new IdenreplacedyHashMap<>();
}
/**
* Synchronize with periodic advertising pointed to by the {@code scanResult}.
* The {@code scanResult} used must contain a valid advertisingSid. First
* call to registerSync will use the {@code skip} and {@code timeout} provided.
* Subsequent calls from other apps, trying to sync with same set will reuse
* existing sync, thus {@code skip} and {@code timeout} values will not take
* effect. The values in effect will be returned in
* {@link PeriodicAdvertisingCallback#onSyncEstablished}.
*
* @param scanResult Scan result containing advertisingSid.
* @param skip The number of periodic advertising packets that can be skipped after a successful
* receive. Must be between 0 and 499.
* @param timeout Synchronization timeout for the periodic advertising. One unit is 10ms. Must
* be between 10 (100ms) and 16384 (163.84s).
* @param callback Callback used to deliver all operations status.
* @throws IllegalArgumentException if {@code scanResult} is null or {@code skip} is invalid or
* {@code timeout} is invalid or {@code callback} is null.
*/
public void registerSync(ScanResult scanResult, int skip, int timeout, PeriodicAdvertisingCallback callback) {
registerSync(scanResult, skip, timeout, callback, null);
}
/**
* Synchronize with periodic advertising pointed to by the {@code scanResult}.
* The {@code scanResult} used must contain a valid advertisingSid. First
* call to registerSync will use the {@code skip} and {@code timeout} provided.
* Subsequent calls from other apps, trying to sync with same set will reuse
* existing sync, thus {@code skip} and {@code timeout} values will not take
* effect. The values in effect will be returned in
* {@link PeriodicAdvertisingCallback#onSyncEstablished}.
*
* @param scanResult Scan result containing advertisingSid.
* @param skip The number of periodic advertising packets that can be skipped after a successful
* receive. Must be between 0 and 499.
* @param timeout Synchronization timeout for the periodic advertising. One unit is 10ms. Must
* be between 10 (100ms) and 16384 (163.84s).
* @param callback Callback used to deliver all operations status.
* @param handler thread upon which the callbacks will be invoked.
* @throws IllegalArgumentException if {@code scanResult} is null or {@code skip} is invalid or
* {@code timeout} is invalid or {@code callback} is null.
*/
public void registerSync(ScanResult scanResult, int skip, int timeout, PeriodicAdvertisingCallback callback, Handler handler) {
if (callback == null) {
throw new IllegalArgumentException("callback can't be null");
}
if (scanResult == null) {
throw new IllegalArgumentException("scanResult can't be null");
}
if (scanResult.getAdvertisingSid() == ScanResult.SID_NOT_PRESENT) {
throw new IllegalArgumentException("scanResult must contain a valid sid");
}
if (skip < SKIP_MIN || skip > SKIP_MAX) {
throw new IllegalArgumentException("timeout must be between " + TIMEOUT_MIN + " and " + TIMEOUT_MAX);
}
if (timeout < TIMEOUT_MIN || timeout > TIMEOUT_MAX) {
throw new IllegalArgumentException("timeout must be between " + TIMEOUT_MIN + " and " + TIMEOUT_MAX);
}
IBluetoothGatt gatt;
try {
gatt = mBluetoothManager.getBluetoothGatt();
} catch (RemoteException e) {
Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
callback.onSyncEstablished(0, scanResult.getDevice(), scanResult.getAdvertisingSid(), skip, timeout, PeriodicAdvertisingCallback.SYNC_NO_RESOURCES);
return;
}
if (handler == null) {
handler = new Handler(Looper.getMainLooper());
}
IPeriodicAdvertisingCallback wrapped = wrap(callback, handler);
mCallbackWrappers.put(callback, wrapped);
try {
gatt.registerSync(scanResult, skip, timeout, wrapped);
} catch (RemoteException e) {
Log.e(TAG, "Failed to register sync - ", e);
return;
}
}
/**
* Cancel pending attempt to create sync, or terminate existing sync.
*
* @param callback Callback used to deliver all operations status.
* @throws IllegalArgumentException if {@code callback} is null, or not a properly registered
* callback.
*/
public void unregisterSync(PeriodicAdvertisingCallback callback) {
if (callback == null) {
throw new IllegalArgumentException("callback can't be null");
}
IBluetoothGatt gatt;
try {
gatt = mBluetoothManager.getBluetoothGatt();
} catch (RemoteException e) {
Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
return;
}
IPeriodicAdvertisingCallback wrapper = mCallbackWrappers.remove(callback);
if (wrapper == null) {
throw new IllegalArgumentException("callback was not properly registered");
}
try {
gatt.unregisterSync(wrapper);
} catch (RemoteException e) {
Log.e(TAG, "Failed to cancel sync creation - ", e);
return;
}
}
private IPeriodicAdvertisingCallback wrap(PeriodicAdvertisingCallback callback, Handler handler) {
return new IPeriodicAdvertisingCallback.Stub() {
public void onSyncEstablished(int syncHandle, BluetoothDevice device, int advertisingSid, int skip, int timeout, int status) {
handler.post(new Runnable() {
@Override
public void run() {
callback.onSyncEstablished(syncHandle, device, advertisingSid, skip, timeout, status);
if (status != PeriodicAdvertisingCallback.SYNC_SUCCESS) {
// App can still unregister the sync until notified it failed. Remove
// callback
// after app was notifed.
mCallbackWrappers.remove(callback);
}
}
});
}
public void onPeriodicAdvertisingReport(PeriodicAdvertisingReport report) {
handler.post(new Runnable() {
@Override
public void run() {
callback.onPeriodicAdvertisingReport(report);
}
});
}
public void onSyncLost(int syncHandle) {
handler.post(new Runnable() {
@Override
public void run() {
callback.onSyncLost(syncHandle);
// App can still unregister the sync until notified it's lost.
// Remove callback after app was notifed.
mCallbackWrappers.remove(callback);
}
});
}
};
}
}
19
Source : BluetoothLeScanner.java
with Apache License 2.0
from lulululbj
with Apache License 2.0
from lulululbj
/**
* This clreplaced provides methods to perform scan related operations for Bluetooth LE devices. An
* application can scan for a particular type of Bluetooth LE devices using {@link ScanFilter}. It
* can also request different types of callbacks for delivering the result.
* <p>
* Use {@link BluetoothAdapter#getBluetoothLeScanner()} to get an instance of
* {@link BluetoothLeScanner}.
* <p>
* <b>Note:</b> Most of the scan methods here require
* {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
*
* @see ScanFilter
*/
public final clreplaced BluetoothLeScanner {
private static final String TAG = "BluetoothLeScanner";
private static final boolean DBG = true;
private static final boolean VDBG = false;
/**
* Extra containing a list of ScanResults. It can have one or more results if there was no
* error. In case of error, {@link #EXTRA_ERROR_CODE} will contain the error code and this
* extra will not be available.
*/
public static final String EXTRA_LIST_SCAN_RESULT = "android.bluetooth.le.extra.LIST_SCAN_RESULT";
/**
* Optional extra indicating the error code, if any. The error code will be one of the
* SCAN_FAILED_* codes in {@link ScanCallback}.
*/
public static final String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE";
/**
* Optional extra indicating the callback type, which will be one of
* CALLBACK_TYPE_* constants in {@link ScanSettings}.
*
* @see ScanCallback#onScanResult(int, ScanResult)
*/
public static final String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE";
private final IBluetoothManager mBluetoothManager;
private final Handler mHandler;
private BluetoothAdapter mBluetoothAdapter;
private final Map<ScanCallback, BleScanCallbackWrapper> mLeScanClients;
/**
* Use {@link BluetoothAdapter#getBluetoothLeScanner()} instead.
*
* @param bluetoothManager BluetoothManager that conducts overall Bluetooth Management.
* @hide
*/
public BluetoothLeScanner(IBluetoothManager bluetoothManager) {
mBluetoothManager = bluetoothManager;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mHandler = new Handler(Looper.getMainLooper());
mLeScanClients = new HashMap<ScanCallback, BleScanCallbackWrapper>();
}
/**
* Start Bluetooth LE scan with default parameters and no filters. The scan results will be
* delivered through {@code callback}. For unfiltered scans, scanning is stopped on screen
* off to save power. Scanning is resumed when screen is turned on again. To avoid this, use
* {@link #startScan(List, ScanSettings, ScanCallback)} with desired {@link ScanFilter}.
* <p>
* An app must hold
* {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
* in order to get results.
*
* @param callback Callback used to deliver scan results.
* @throws IllegalArgumentException If {@code callback} is null.
*/
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public void startScan(final ScanCallback callback) {
startScan(null, new ScanSettings.Builder().build(), callback);
}
/**
* Start Bluetooth LE scan. The scan results will be delivered through {@code callback}.
* For unfiltered scans, scanning is stopped on screen off to save power. Scanning is
* resumed when screen is turned on again. To avoid this, do filetered scanning by
* using proper {@link ScanFilter}.
* <p>
* An app must hold
* {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
* in order to get results.
*
* @param filters {@link ScanFilter}s for finding exact BLE devices.
* @param settings Settings for the scan.
* @param callback Callback used to deliver scan results.
* @throws IllegalArgumentException If {@code settings} or {@code callback} is null.
*/
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public void startScan(List<ScanFilter> filters, ScanSettings settings, final ScanCallback callback) {
startScan(filters, settings, null, callback, /*callbackIntent=*/
null, null);
}
/**
* Start Bluetooth LE scan using a {@link PendingIntent}. The scan results will be delivered via
* the PendingIntent. Use this method of scanning if your process is not always running and it
* should be started when scan results are available.
* <p>
* An app must hold
* {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
* in order to get results.
* <p>
* When the PendingIntent is delivered, the Intent preplaceded to the receiver or activity
* will contain one or more of the extras {@link #EXTRA_CALLBACK_TYPE},
* {@link #EXTRA_ERROR_CODE} and {@link #EXTRA_LIST_SCAN_RESULT} to indicate the result of
* the scan.
*
* @param filters Optional list of ScanFilters for finding exact BLE devices.
* @param settings Optional settings for the scan.
* @param callbackIntent The PendingIntent to deliver the result to.
* @return Returns 0 for success or an error code from {@link ScanCallback} if the scan request
* could not be sent.
* @see #stopScan(PendingIntent)
*/
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public int startScan(@Nullable List<ScanFilter> filters, @Nullable ScanSettings settings, @NonNull PendingIntent callbackIntent) {
return startScan(filters, settings != null ? settings : new ScanSettings.Builder().build(), null, null, callbackIntent, null);
}
/**
* Start Bluetooth LE scan. Same as {@link #startScan(ScanCallback)} but allows the caller to
* specify on behalf of which application(s) the work is being done.
*
* @param workSource {@link WorkSource} identifying the application(s) for which to blame for
* the scan.
* @param callback Callback used to deliver scan results.
* @hide
*/
@SystemApi
@RequiresPermission(allOf = { Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.UPDATE_DEVICE_STATS })
public void startScanFromSource(final WorkSource workSource, final ScanCallback callback) {
startScanFromSource(null, new ScanSettings.Builder().build(), workSource, callback);
}
/**
* Start Bluetooth LE scan. Same as {@link #startScan(List, ScanSettings, ScanCallback)} but
* allows the caller to specify on behalf of which application(s) the work is being done.
*
* @param filters {@link ScanFilter}s for finding exact BLE devices.
* @param settings Settings for the scan.
* @param workSource {@link WorkSource} identifying the application(s) for which to blame for
* the scan.
* @param callback Callback used to deliver scan results.
* @hide
*/
@SystemApi
@RequiresPermission(allOf = { Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.UPDATE_DEVICE_STATS })
public void startScanFromSource(List<ScanFilter> filters, ScanSettings settings, final WorkSource workSource, final ScanCallback callback) {
startScan(filters, settings, workSource, callback, null, null);
}
private int startScan(List<ScanFilter> filters, ScanSettings settings, final WorkSource workSource, final ScanCallback callback, final PendingIntent callbackIntent, List<List<ResultStorageDescriptor>> resultStorages) {
BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
if (callback == null && callbackIntent == null) {
throw new IllegalArgumentException("callback is null");
}
if (settings == null) {
throw new IllegalArgumentException("settings is null");
}
synchronized (mLeScanClients) {
if (callback != null && mLeScanClients.containsKey(callback)) {
return postCallbackErrorOrReturn(callback, ScanCallback.SCAN_FAILED_ALREADY_STARTED);
}
IBluetoothGatt gatt;
try {
gatt = mBluetoothManager.getBluetoothGatt();
} catch (RemoteException e) {
gatt = null;
}
if (gatt == null) {
return postCallbackErrorOrReturn(callback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR);
}
if (!isSettingsConfigAllowedForScan(settings)) {
return postCallbackErrorOrReturn(callback, ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED);
}
if (!isHardwareResourcesAvailableForScan(settings)) {
return postCallbackErrorOrReturn(callback, ScanCallback.SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES);
}
if (!isSettingsAndFilterComboAllowed(settings, filters)) {
return postCallbackErrorOrReturn(callback, ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED);
}
if (callback != null) {
BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters, settings, workSource, callback, resultStorages);
wrapper.startRegistration();
} else {
try {
gatt.startScanForIntent(callbackIntent, settings, filters, ActivityThread.currentOpPackageName());
} catch (RemoteException e) {
return ScanCallback.SCAN_FAILED_INTERNAL_ERROR;
}
}
}
return ScanCallback.NO_ERROR;
}
/**
* Stops an ongoing Bluetooth LE scan.
*
* @param callback
*/
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public void stopScan(ScanCallback callback) {
BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
synchronized (mLeScanClients) {
BleScanCallbackWrapper wrapper = mLeScanClients.remove(callback);
if (wrapper == null) {
if (DBG)
Log.d(TAG, "could not find callback wrapper");
return;
}
wrapper.stopLeScan();
}
}
/**
* Stops an ongoing Bluetooth LE scan started using a PendingIntent. When creating the
* PendingIntent parameter, please do not use the FLAG_CANCEL_CURRENT flag. Otherwise, the stop
* scan may have no effect.
*
* @param callbackIntent The PendingIntent that was used to start the scan.
* @see #startScan(List, ScanSettings, PendingIntent)
*/
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public void stopScan(PendingIntent callbackIntent) {
BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
IBluetoothGatt gatt;
try {
gatt = mBluetoothManager.getBluetoothGatt();
gatt.stopScanForIntent(callbackIntent, ActivityThread.currentOpPackageName());
} catch (RemoteException e) {
}
}
/**
* Flush pending batch scan results stored in Bluetooth controller. This will return Bluetooth
* LE scan results batched on bluetooth controller. Returns immediately, batch scan results data
* will be delivered through the {@code callback}.
*
* @param callback Callback of the Bluetooth LE Scan, it has to be the same instance as the one
* used to start scan.
*/
public void flushPendingScanResults(ScanCallback callback) {
BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
if (callback == null) {
throw new IllegalArgumentException("callback cannot be null!");
}
synchronized (mLeScanClients) {
BleScanCallbackWrapper wrapper = mLeScanClients.get(callback);
if (wrapper == null) {
return;
}
wrapper.flushPendingBatchResults();
}
}
/**
* Start truncated scan.
*
* @hide
*/
@SystemApi
public void startTruncatedScan(List<TruncatedFilter> truncatedFilters, ScanSettings settings, final ScanCallback callback) {
int filterSize = truncatedFilters.size();
List<ScanFilter> scanFilters = new ArrayList<ScanFilter>(filterSize);
List<List<ResultStorageDescriptor>> scanStorages = new ArrayList<List<ResultStorageDescriptor>>(filterSize);
for (TruncatedFilter filter : truncatedFilters) {
scanFilters.add(filter.getFilter());
scanStorages.add(filter.getStorageDescriptors());
}
startScan(scanFilters, settings, null, callback, null, scanStorages);
}
/**
* Cleans up scan clients. Should be called when bluetooth is down.
*
* @hide
*/
public void cleanup() {
mLeScanClients.clear();
}
/**
* Bluetooth GATT interface callbacks
*/
private clreplaced BleScanCallbackWrapper extends IScannerCallback.Stub {
private static final int REGISTRATION_CALLBACK_TIMEOUT_MILLIS = 2000;
private final ScanCallback mScanCallback;
private final List<ScanFilter> mFilters;
private final WorkSource mWorkSource;
private ScanSettings mSettings;
private IBluetoothGatt mBluetoothGatt;
private List<List<ResultStorageDescriptor>> mResultStorages;
// mLeHandle 0: not registered
// -2: registration failed because app is scanning to frequently
// -1: scan stopped or registration failed
// > 0: registered and scan started
private int mScannerId;
public BleScanCallbackWrapper(IBluetoothGatt bluetoothGatt, List<ScanFilter> filters, ScanSettings settings, WorkSource workSource, ScanCallback scanCallback, List<List<ResultStorageDescriptor>> resultStorages) {
mBluetoothGatt = bluetoothGatt;
mFilters = filters;
mSettings = settings;
mWorkSource = workSource;
mScanCallback = scanCallback;
mScannerId = 0;
mResultStorages = resultStorages;
}
public void startRegistration() {
synchronized (this) {
// Scan stopped.
if (mScannerId == -1 || mScannerId == -2)
return;
try {
mBluetoothGatt.registerScanner(this, mWorkSource);
wait(REGISTRATION_CALLBACK_TIMEOUT_MILLIS);
} catch (InterruptedException | RemoteException e) {
Log.e(TAG, "application registeration exception", e);
postCallbackError(mScanCallback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR);
}
if (mScannerId > 0) {
mLeScanClients.put(mScanCallback, this);
} else {
// Registration timed out or got exception, reset RscannerId to -1 so no
// subsequent operations can proceed.
if (mScannerId == 0)
mScannerId = -1;
// If scanning too frequently, don't report anything to the app.
if (mScannerId == -2)
return;
postCallbackError(mScanCallback, ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED);
}
}
}
public void stopLeScan() {
synchronized (this) {
if (mScannerId <= 0) {
Log.e(TAG, "Error state, mLeHandle: " + mScannerId);
return;
}
try {
mBluetoothGatt.stopScan(mScannerId);
mBluetoothGatt.unregisterScanner(mScannerId);
} catch (RemoteException e) {
Log.e(TAG, "Failed to stop scan and unregister", e);
}
mScannerId = -1;
}
}
void flushPendingBatchResults() {
synchronized (this) {
if (mScannerId <= 0) {
Log.e(TAG, "Error state, mLeHandle: " + mScannerId);
return;
}
try {
mBluetoothGatt.flushPendingBatchResults(mScannerId);
} catch (RemoteException e) {
Log.e(TAG, "Failed to get pending scan results", e);
}
}
}
/**
* Application interface registered - app is ready to go
*/
@Override
public void onScannerRegistered(int status, int scannerId) {
Log.d(TAG, "onScannerRegistered() - status=" + status + " scannerId=" + scannerId + " mScannerId=" + mScannerId);
synchronized (this) {
if (status == BluetoothGatt.GATT_SUCCESS) {
try {
if (mScannerId == -1) {
// Registration succeeds after timeout, unregister client.
mBluetoothGatt.unregisterClient(scannerId);
} else {
mScannerId = scannerId;
mBluetoothGatt.startScan(mScannerId, mSettings, mFilters, mResultStorages, ActivityThread.currentOpPackageName());
}
} catch (RemoteException e) {
Log.e(TAG, "fail to start le scan: " + e);
mScannerId = -1;
}
} else if (status == ScanCallback.SCAN_FAILED_SCANNING_TOO_FREQUENTLY) {
// applicaiton was scanning too frequently
mScannerId = -2;
} else {
// registration failed
mScannerId = -1;
}
notifyAll();
}
}
/**
* Callback reporting an LE scan result.
*
* @hide
*/
@Override
public void onScanResult(final ScanResult scanResult) {
if (VDBG)
Log.d(TAG, "onScanResult() - " + scanResult.toString());
// Check null in case the scan has been stopped
synchronized (this) {
if (mScannerId <= 0)
return;
}
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult);
}
});
}
@Override
public void onBatchScanResults(final List<ScanResult> results) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
mScanCallback.onBatchScanResults(results);
}
});
}
@Override
public void onFoundOrLost(final boolean onFound, final ScanResult scanResult) {
if (VDBG) {
Log.d(TAG, "onFoundOrLost() - onFound = " + onFound + " " + scanResult.toString());
}
// Check null in case the scan has been stopped
synchronized (this) {
if (mScannerId <= 0) {
return;
}
}
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
if (onFound) {
mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_FIRST_MATCH, scanResult);
} else {
mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_MATCH_LOST, scanResult);
}
}
});
}
@Override
public void onScanManagerErrorCallback(final int errorCode) {
if (VDBG) {
Log.d(TAG, "onScanManagerErrorCallback() - errorCode = " + errorCode);
}
synchronized (this) {
if (mScannerId <= 0) {
return;
}
}
postCallbackError(mScanCallback, errorCode);
}
}
private int postCallbackErrorOrReturn(final ScanCallback callback, final int errorCode) {
if (callback == null) {
return errorCode;
} else {
postCallbackError(callback, errorCode);
return ScanCallback.NO_ERROR;
}
}
private void postCallbackError(final ScanCallback callback, final int errorCode) {
mHandler.post(new Runnable() {
@Override
public void run() {
callback.onScanFailed(errorCode);
}
});
}
private boolean isSettingsConfigAllowedForScan(ScanSettings settings) {
if (mBluetoothAdapter.isOffloadedFilteringSupported()) {
return true;
}
final int callbackType = settings.getCallbackType();
// Only support regular scan if no offloaded filter support.
if (callbackType == ScanSettings.CALLBACK_TYPE_ALL_MATCHES && settings.getReportDelayMillis() == 0) {
return true;
}
return false;
}
private boolean isSettingsAndFilterComboAllowed(ScanSettings settings, List<ScanFilter> filterList) {
final int callbackType = settings.getCallbackType();
// If onlost/onfound is requested, a non-empty filter is expected
if ((callbackType & (ScanSettings.CALLBACK_TYPE_FIRST_MATCH | ScanSettings.CALLBACK_TYPE_MATCH_LOST)) != 0) {
if (filterList == null) {
return false;
}
for (ScanFilter filter : filterList) {
if (filter.isAllFieldsEmpty()) {
return false;
}
}
}
return true;
}
private boolean isHardwareResourcesAvailableForScan(ScanSettings settings) {
final int callbackType = settings.getCallbackType();
if ((callbackType & ScanSettings.CALLBACK_TYPE_FIRST_MATCH) != 0 || (callbackType & ScanSettings.CALLBACK_TYPE_MATCH_LOST) != 0) {
// For onlost/onfound, we required hw support be available
return (mBluetoothAdapter.isOffloadedFilteringSupported() && mBluetoothAdapter.isHardwareTrackingFiltersAvailable());
}
return true;
}
}
19
Source : BluetoothLeAdvertiser.java
with Apache License 2.0
from lulululbj
with Apache License 2.0
from lulululbj
/**
* This clreplaced provides a way to perform Bluetooth LE advertise operations, such as starting and
* stopping advertising. An advertiser can broadcast up to 31 bytes of advertisement data
* represented by {@link AdvertiseData}.
* <p>
* To get an instance of {@link BluetoothLeAdvertiser}, call the
* {@link BluetoothAdapter#getBluetoothLeAdvertiser()} method.
* <p>
* <b>Note:</b> Most of the methods here require {@link android.Manifest.permission#BLUETOOTH_ADMIN}
* permission.
*
* @see AdvertiseData
*/
public final clreplaced BluetoothLeAdvertiser {
private static final String TAG = "BluetoothLeAdvertiser";
private static final int MAX_ADVERTISING_DATA_BYTES = 1650;
private static final int MAX_LEGACY_ADVERTISING_DATA_BYTES = 31;
// Each fields need one byte for field length and another byte for field type.
private static final int OVERHEAD_BYTES_PER_FIELD = 2;
// Flags field will be set by system.
private static final int FLAGS_FIELD_BYTES = 3;
private static final int MANUFACTURER_SPECIFIC_DATA_LENGTH = 2;
private final IBluetoothManager mBluetoothManager;
private final Handler mHandler;
private BluetoothAdapter mBluetoothAdapter;
private final Map<AdvertiseCallback, AdvertisingSetCallback> mLegacyAdvertisers = new HashMap<>();
private final Map<AdvertisingSetCallback, IAdvertisingSetCallback> mCallbackWrappers = Collections.synchronizedMap(new HashMap<>());
private final Map<Integer, AdvertisingSet> mAdvertisingSets = Collections.synchronizedMap(new HashMap<>());
/**
* Use BluetoothAdapter.getLeAdvertiser() instead.
*
* @param bluetoothManager BluetoothManager that conducts overall Bluetooth Management
* @hide
*/
public BluetoothLeAdvertiser(IBluetoothManager bluetoothManager) {
mBluetoothManager = bluetoothManager;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mHandler = new Handler(Looper.getMainLooper());
}
/**
* Start Bluetooth LE Advertising. On success, the {@code advertiseData} will be broadcasted.
* Returns immediately, the operation status is delivered through {@code callback}.
* <p>
* Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
*
* @param settings Settings for Bluetooth LE advertising.
* @param advertiseData Advertisement data to be broadcasted.
* @param callback Callback for advertising status.
*/
public void startAdvertising(AdvertiseSettings settings, AdvertiseData advertiseData, final AdvertiseCallback callback) {
startAdvertising(settings, advertiseData, null, callback);
}
/**
* Start Bluetooth LE Advertising. The {@code advertiseData} will be broadcasted if the
* operation succeeds. The {@code scanResponse} is returned when a scanning device sends an
* active scan request. This method returns immediately, the operation status is delivered
* through {@code callback}.
* <p>
* Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
*
* @param settings Settings for Bluetooth LE advertising.
* @param advertiseData Advertisement data to be advertised in advertisement packet.
* @param scanResponse Scan response replacedociated with the advertisement data.
* @param callback Callback for advertising status.
*/
public void startAdvertising(AdvertiseSettings settings, AdvertiseData advertiseData, AdvertiseData scanResponse, final AdvertiseCallback callback) {
synchronized (mLegacyAdvertisers) {
BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
if (callback == null) {
throw new IllegalArgumentException("callback cannot be null");
}
boolean isConnectable = settings.isConnectable();
if (totalBytes(advertiseData, isConnectable) > MAX_LEGACY_ADVERTISING_DATA_BYTES || totalBytes(scanResponse, false) > MAX_LEGACY_ADVERTISING_DATA_BYTES) {
postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE);
return;
}
if (mLegacyAdvertisers.containsKey(callback)) {
postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED);
return;
}
AdvertisingSetParameters.Builder parameters = new AdvertisingSetParameters.Builder();
parameters.setLegacyMode(true);
parameters.setConnectable(isConnectable);
// legacy advertisements we support are always scannable
parameters.setScannable(true);
if (settings.getMode() == AdvertiseSettings.ADVERTISE_MODE_LOW_POWER) {
// 1s
parameters.setInterval(1600);
} else if (settings.getMode() == AdvertiseSettings.ADVERTISE_MODE_BALANCED) {
// 250ms
parameters.setInterval(400);
} else if (settings.getMode() == AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY) {
// 100ms
parameters.setInterval(160);
}
if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_ULTRA_LOW) {
parameters.setTxPowerLevel(-21);
} else if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_LOW) {
parameters.setTxPowerLevel(-15);
} else if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM) {
parameters.setTxPowerLevel(-7);
} else if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_HIGH) {
parameters.setTxPowerLevel(1);
}
int duration = 0;
int timeoutMillis = settings.getTimeout();
if (timeoutMillis > 0) {
duration = (timeoutMillis < 10) ? 1 : timeoutMillis / 10;
}
AdvertisingSetCallback wrapped = wrapOldCallback(callback, settings);
mLegacyAdvertisers.put(callback, wrapped);
startAdvertisingSet(parameters.build(), advertiseData, scanResponse, null, null, duration, 0, wrapped);
}
}
AdvertisingSetCallback wrapOldCallback(AdvertiseCallback callback, AdvertiseSettings settings) {
return new AdvertisingSetCallback() {
@Override
public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int txPower, int status) {
if (status != AdvertisingSetCallback.ADVERTISE_SUCCESS) {
postStartFailure(callback, status);
return;
}
postStartSuccess(callback, settings);
}
/* Legacy advertiser is disabled on timeout */
@Override
public void onAdvertisingEnabled(AdvertisingSet advertisingSet, boolean enabled, int status) {
if (enabled) {
Log.e(TAG, "Legacy advertiser should be only disabled on timeout," + " but was enabled!");
return;
}
stopAdvertising(callback);
}
};
}
/**
* Stop Bluetooth LE advertising. The {@code callback} must be the same one use in
* {@link BluetoothLeAdvertiser#startAdvertising}.
* <p>
* Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
*
* @param callback {@link AdvertiseCallback} identifies the advertising instance to stop.
*/
public void stopAdvertising(final AdvertiseCallback callback) {
synchronized (mLegacyAdvertisers) {
if (callback == null) {
throw new IllegalArgumentException("callback cannot be null");
}
AdvertisingSetCallback wrapper = mLegacyAdvertisers.get(callback);
if (wrapper == null)
return;
stopAdvertisingSet(wrapper);
mLegacyAdvertisers.remove(callback);
}
}
/**
* Creates a new advertising set. If operation succeed, device will start advertising. This
* method returns immediately, the operation status is delivered through
* {@code callback.onAdvertisingSetStarted()}.
* <p>
*
* @param parameters advertising set parameters.
* @param advertiseData Advertisement data to be broadcasted. Size must not exceed {@link
* BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the advertisement is connectable,
* three bytes will be added for flags.
* @param scanResponse Scan response replacedociated with the advertisement data. Size must not
* exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
* @param periodicParameters periodic advertisng parameters. If null, periodic advertising will
* not be started.
* @param periodicData Periodic advertising data. Size must not exceed {@link
* BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
* @param callback Callback for advertising set.
* @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable
* size, or unsupported advertising PHY is selected, or when attempt to use Periodic Advertising
* feature is made when it's not supported by the controller.
*/
public void startAdvertisingSet(AdvertisingSetParameters parameters, AdvertiseData advertiseData, AdvertiseData scanResponse, PeriodicAdvertisingParameters periodicParameters, AdvertiseData periodicData, AdvertisingSetCallback callback) {
startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters, periodicData, 0, 0, callback, new Handler(Looper.getMainLooper()));
}
/**
* Creates a new advertising set. If operation succeed, device will start advertising. This
* method returns immediately, the operation status is delivered through
* {@code callback.onAdvertisingSetStarted()}.
* <p>
*
* @param parameters advertising set parameters.
* @param advertiseData Advertisement data to be broadcasted. Size must not exceed {@link
* BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the advertisement is connectable,
* three bytes will be added for flags.
* @param scanResponse Scan response replacedociated with the advertisement data. Size must not
* exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
* @param periodicParameters periodic advertisng parameters. If null, periodic advertising will
* not be started.
* @param periodicData Periodic advertising data. Size must not exceed {@link
* BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
* @param callback Callback for advertising set.
* @param handler thread upon which the callbacks will be invoked.
* @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable
* size, or unsupported advertising PHY is selected, or when attempt to use Periodic Advertising
* feature is made when it's not supported by the controller.
*/
public void startAdvertisingSet(AdvertisingSetParameters parameters, AdvertiseData advertiseData, AdvertiseData scanResponse, PeriodicAdvertisingParameters periodicParameters, AdvertiseData periodicData, AdvertisingSetCallback callback, Handler handler) {
startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters, periodicData, 0, 0, callback, handler);
}
/**
* Creates a new advertising set. If operation succeed, device will start advertising. This
* method returns immediately, the operation status is delivered through
* {@code callback.onAdvertisingSetStarted()}.
* <p>
*
* @param parameters advertising set parameters.
* @param advertiseData Advertisement data to be broadcasted. Size must not exceed {@link
* BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the advertisement is connectable,
* three bytes will be added for flags.
* @param scanResponse Scan response replacedociated with the advertisement data. Size must not
* exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
* @param periodicParameters periodic advertisng parameters. If null, periodic advertising will
* not be started.
* @param periodicData Periodic advertising data. Size must not exceed {@link
* BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
* @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to 65535
* (655,350 ms). 0 means advertising should continue until stopped.
* @param maxExtendedAdvertisingEvents maximum number of extended advertising events the
* controller shall attempt to send prior to terminating the extended advertising, even if the
* duration has not expired. Valid range is from 1 to 255. 0 means no maximum.
* @param callback Callback for advertising set.
* @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable
* size, or unsupported advertising PHY is selected, or when attempt to use Periodic Advertising
* feature is made when it's not supported by the controller.
*/
public void startAdvertisingSet(AdvertisingSetParameters parameters, AdvertiseData advertiseData, AdvertiseData scanResponse, PeriodicAdvertisingParameters periodicParameters, AdvertiseData periodicData, int duration, int maxExtendedAdvertisingEvents, AdvertisingSetCallback callback) {
startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters, periodicData, duration, maxExtendedAdvertisingEvents, callback, new Handler(Looper.getMainLooper()));
}
/**
* Creates a new advertising set. If operation succeed, device will start advertising. This
* method returns immediately, the operation status is delivered through
* {@code callback.onAdvertisingSetStarted()}.
* <p>
*
* @param parameters Advertising set parameters.
* @param advertiseData Advertisement data to be broadcasted. Size must not exceed {@link
* BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the advertisement is connectable,
* three bytes will be added for flags.
* @param scanResponse Scan response replacedociated with the advertisement data. Size must not
* exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}
* @param periodicParameters Periodic advertisng parameters. If null, periodic advertising will
* not be started.
* @param periodicData Periodic advertising data. Size must not exceed {@link
* BluetoothAdapter#getLeMaximumAdvertisingDataLength}
* @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to 65535
* (655,350 ms). 0 means advertising should continue until stopped.
* @param maxExtendedAdvertisingEvents maximum number of extended advertising events the
* controller shall attempt to send prior to terminating the extended advertising, even if the
* duration has not expired. Valid range is from 1 to 255. 0 means no maximum.
* @param callback Callback for advertising set.
* @param handler Thread upon which the callbacks will be invoked.
* @throws IllegalArgumentException When any of the data parameter exceed the maximum allowable
* size, or unsupported advertising PHY is selected, or when attempt to use Periodic Advertising
* feature is made when it's not supported by the controller, or when
* maxExtendedAdvertisingEvents is used on a controller that doesn't support the LE Extended
* Advertising
*/
public void startAdvertisingSet(AdvertisingSetParameters parameters, AdvertiseData advertiseData, AdvertiseData scanResponse, PeriodicAdvertisingParameters periodicParameters, AdvertiseData periodicData, int duration, int maxExtendedAdvertisingEvents, AdvertisingSetCallback callback, Handler handler) {
BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
if (callback == null) {
throw new IllegalArgumentException("callback cannot be null");
}
boolean isConnectable = parameters.isConnectable();
if (parameters.isLegacy()) {
if (totalBytes(advertiseData, isConnectable) > MAX_LEGACY_ADVERTISING_DATA_BYTES) {
throw new IllegalArgumentException("Legacy advertising data too big");
}
if (totalBytes(scanResponse, false) > MAX_LEGACY_ADVERTISING_DATA_BYTES) {
throw new IllegalArgumentException("Legacy scan response data too big");
}
} else {
boolean supportCodedPhy = mBluetoothAdapter.isLeCodedPhySupported();
boolean support2MPhy = mBluetoothAdapter.isLe2MPhySupported();
int pphy = parameters.getPrimaryPhy();
int sphy = parameters.getSecondaryPhy();
if (pphy == BluetoothDevice.PHY_LE_CODED && !supportCodedPhy) {
throw new IllegalArgumentException("Unsupported primary PHY selected");
}
if ((sphy == BluetoothDevice.PHY_LE_CODED && !supportCodedPhy) || (sphy == BluetoothDevice.PHY_LE_2M && !support2MPhy)) {
throw new IllegalArgumentException("Unsupported secondary PHY selected");
}
int maxData = mBluetoothAdapter.getLeMaximumAdvertisingDataLength();
if (totalBytes(advertiseData, isConnectable) > maxData) {
throw new IllegalArgumentException("Advertising data too big");
}
if (totalBytes(scanResponse, false) > maxData) {
throw new IllegalArgumentException("Scan response data too big");
}
if (totalBytes(periodicData, false) > maxData) {
throw new IllegalArgumentException("Periodic advertising data too big");
}
boolean supportPeriodic = mBluetoothAdapter.isLePeriodicAdvertisingSupported();
if (periodicParameters != null && !supportPeriodic) {
throw new IllegalArgumentException("Controller does not support LE Periodic Advertising");
}
}
if (maxExtendedAdvertisingEvents < 0 || maxExtendedAdvertisingEvents > 255) {
throw new IllegalArgumentException("maxExtendedAdvertisingEvents out of range: " + maxExtendedAdvertisingEvents);
}
if (maxExtendedAdvertisingEvents != 0 && !mBluetoothAdapter.isLePeriodicAdvertisingSupported()) {
throw new IllegalArgumentException("Can't use maxExtendedAdvertisingEvents with controller that don't support " + "LE Extended Advertising");
}
if (duration < 0 || duration > 65535) {
throw new IllegalArgumentException("duration out of range: " + duration);
}
IBluetoothGatt gatt;
try {
gatt = mBluetoothManager.getBluetoothGatt();
} catch (RemoteException e) {
Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
postStartSetFailure(handler, callback, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
return;
}
IAdvertisingSetCallback wrapped = wrap(callback, handler);
if (mCallbackWrappers.putIfAbsent(callback, wrapped) != null) {
throw new IllegalArgumentException("callback instance already replacedociated with advertising");
}
try {
gatt.startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters, periodicData, duration, maxExtendedAdvertisingEvents, wrapped);
} catch (RemoteException e) {
Log.e(TAG, "Failed to start advertising set - ", e);
postStartSetFailure(handler, callback, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
return;
}
}
/**
* Used to dispose of a {@link AdvertisingSet} object, obtained with {@link
* BluetoothLeAdvertiser#startAdvertisingSet}.
*/
public void stopAdvertisingSet(AdvertisingSetCallback callback) {
if (callback == null) {
throw new IllegalArgumentException("callback cannot be null");
}
IAdvertisingSetCallback wrapped = mCallbackWrappers.remove(callback);
if (wrapped == null) {
return;
}
IBluetoothGatt gatt;
try {
gatt = mBluetoothManager.getBluetoothGatt();
gatt.stopAdvertisingSet(wrapped);
} catch (RemoteException e) {
Log.e(TAG, "Failed to stop advertising - ", e);
}
}
/**
* Cleans up advertisers. Should be called when bluetooth is down.
*
* @hide
*/
public void cleanup() {
mLegacyAdvertisers.clear();
mCallbackWrappers.clear();
mAdvertisingSets.clear();
}
// Compute the size of advertisement data or scan resp
private int totalBytes(AdvertiseData data, boolean isFlagsIncluded) {
if (data == null)
return 0;
// Flags field is omitted if the advertising is not connectable.
int size = (isFlagsIncluded) ? FLAGS_FIELD_BYTES : 0;
if (data.getServiceUuids() != null) {
int num16BitUuids = 0;
int num32BitUuids = 0;
int num128BitUuids = 0;
for (ParcelUuid uuid : data.getServiceUuids()) {
if (BluetoothUuid.is16BitUuid(uuid)) {
++num16BitUuids;
} else if (BluetoothUuid.is32BitUuid(uuid)) {
++num32BitUuids;
} else {
++num128BitUuids;
}
}
// 16 bit service uuids are grouped into one field when doing advertising.
if (num16BitUuids != 0) {
size += OVERHEAD_BYTES_PER_FIELD + num16BitUuids * BluetoothUuid.UUID_BYTES_16_BIT;
}
// 32 bit service uuids are grouped into one field when doing advertising.
if (num32BitUuids != 0) {
size += OVERHEAD_BYTES_PER_FIELD + num32BitUuids * BluetoothUuid.UUID_BYTES_32_BIT;
}
// 128 bit service uuids are grouped into one field when doing advertising.
if (num128BitUuids != 0) {
size += OVERHEAD_BYTES_PER_FIELD + num128BitUuids * BluetoothUuid.UUID_BYTES_128_BIT;
}
}
for (ParcelUuid uuid : data.getServiceData().keySet()) {
int uuidLen = BluetoothUuid.uuidToBytes(uuid).length;
size += OVERHEAD_BYTES_PER_FIELD + uuidLen + byteLength(data.getServiceData().get(uuid));
}
for (int i = 0; i < data.getManufacturerSpecificData().size(); ++i) {
size += OVERHEAD_BYTES_PER_FIELD + MANUFACTURER_SPECIFIC_DATA_LENGTH + byteLength(data.getManufacturerSpecificData().valueAt(i));
}
if (data.getIncludeTxPowerLevel()) {
// tx power level value is one byte.
size += OVERHEAD_BYTES_PER_FIELD + 1;
}
if (data.getIncludeDeviceName() && mBluetoothAdapter.getName() != null) {
size += OVERHEAD_BYTES_PER_FIELD + mBluetoothAdapter.getName().length();
}
return size;
}
private int byteLength(byte[] array) {
return array == null ? 0 : array.length;
}
IAdvertisingSetCallback wrap(AdvertisingSetCallback callback, Handler handler) {
return new IAdvertisingSetCallback.Stub() {
@Override
public void onAdvertisingSetStarted(int advertiserId, int txPower, int status) {
handler.post(new Runnable() {
@Override
public void run() {
if (status != AdvertisingSetCallback.ADVERTISE_SUCCESS) {
callback.onAdvertisingSetStarted(null, 0, status);
mCallbackWrappers.remove(callback);
return;
}
AdvertisingSet advertisingSet = new AdvertisingSet(advertiserId, mBluetoothManager);
mAdvertisingSets.put(advertiserId, advertisingSet);
callback.onAdvertisingSetStarted(advertisingSet, txPower, status);
}
});
}
@Override
public void onOwnAddressRead(int advertiserId, int addressType, String address) {
handler.post(new Runnable() {
@Override
public void run() {
AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
callback.onOwnAddressRead(advertisingSet, addressType, address);
}
});
}
@Override
public void onAdvertisingSetStopped(int advertiserId) {
handler.post(new Runnable() {
@Override
public void run() {
AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
callback.onAdvertisingSetStopped(advertisingSet);
mAdvertisingSets.remove(advertiserId);
mCallbackWrappers.remove(callback);
}
});
}
@Override
public void onAdvertisingEnabled(int advertiserId, boolean enabled, int status) {
handler.post(new Runnable() {
@Override
public void run() {
AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
callback.onAdvertisingEnabled(advertisingSet, enabled, status);
}
});
}
@Override
public void onAdvertisingDataSet(int advertiserId, int status) {
handler.post(new Runnable() {
@Override
public void run() {
AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
callback.onAdvertisingDataSet(advertisingSet, status);
}
});
}
@Override
public void onScanResponseDataSet(int advertiserId, int status) {
handler.post(new Runnable() {
@Override
public void run() {
AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
callback.onScanResponseDataSet(advertisingSet, status);
}
});
}
@Override
public void onAdvertisingParametersUpdated(int advertiserId, int txPower, int status) {
handler.post(new Runnable() {
@Override
public void run() {
AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
callback.onAdvertisingParametersUpdated(advertisingSet, txPower, status);
}
});
}
@Override
public void onPeriodicAdvertisingParametersUpdated(int advertiserId, int status) {
handler.post(new Runnable() {
@Override
public void run() {
AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
callback.onPeriodicAdvertisingParametersUpdated(advertisingSet, status);
}
});
}
@Override
public void onPeriodicAdvertisingDataSet(int advertiserId, int status) {
handler.post(new Runnable() {
@Override
public void run() {
AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
callback.onPeriodicAdvertisingDataSet(advertisingSet, status);
}
});
}
@Override
public void onPeriodicAdvertisingEnabled(int advertiserId, boolean enable, int status) {
handler.post(new Runnable() {
@Override
public void run() {
AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
callback.onPeriodicAdvertisingEnabled(advertisingSet, enable, status);
}
});
}
};
}
private void postStartSetFailure(Handler handler, final AdvertisingSetCallback callback, final int error) {
handler.post(new Runnable() {
@Override
public void run() {
callback.onAdvertisingSetStarted(null, 0, error);
}
});
}
private void postStartFailure(final AdvertiseCallback callback, final int error) {
mHandler.post(new Runnable() {
@Override
public void run() {
callback.onStartFailure(error);
}
});
}
private void postStartSuccess(final AdvertiseCallback callback, final AdvertiseSettings settings) {
mHandler.post(new Runnable() {
@Override
public void run() {
callback.onStartSuccess(settings);
}
});
}
}