diff options
Diffstat (limited to 'app/src/main/java/io/trygvis/android/bt/DefaultBtService.java')
-rw-r--r-- | app/src/main/java/io/trygvis/android/bt/DefaultBtService.java | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/app/src/main/java/io/trygvis/android/bt/DefaultBtService.java b/app/src/main/java/io/trygvis/android/bt/DefaultBtService.java new file mode 100644 index 0000000..8638544 --- /dev/null +++ b/app/src/main/java/io/trygvis/android/bt/DefaultBtService.java @@ -0,0 +1,192 @@ +package io.trygvis.android.bt; + +import android.app.Service; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothManager; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Handler; +import android.os.IBinder; +import android.util.Log; +import android.widget.Toast; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import io.trygvis.soilmoisture.R; + +public class DefaultBtService<A> extends Service implements BtService<A> { + private final static String TAG = DefaultBtService.class.getSimpleName(); + + private final IBinder binder = new LocalBinder<>(this); + + private Handler handler = new Handler(); + + // ----------------------------------------------------------------------- + // State + // ----------------------------------------------------------------------- + + private BtServiceListener<A> serviceListener = new AbstractBtServiceListener<A>() { + @Override + public void onNewDevice(BtDevice<A> device) { + } + }; + + private Supplier<A> tagConstructor; + + private BluetoothManager bluetoothManager; + + private BluetoothAdapter bluetoothAdapter; + + private final List<BtDevice<A>> devices = new ArrayList<>(); + + private boolean scanning = false; + + // ----------------------------------------------------------------------- + // BtService Implementation + // ----------------------------------------------------------------------- + + @Override + public boolean initialize(BtServiceListener<A> serviceListener, Supplier<A> dataSupplier) { + if (bluetoothManager != null) { + Log.e(TAG, "Already initialized"); + return false; + } + + this.tagConstructor = dataSupplier; + + if (serviceListener != null) { + this.serviceListener = serviceListener; + } + + // Use this check to determine whether BLE is supported on the device. Then you can + // selectively disable BLE-related features. + if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { + Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show(); + return false; + } + + // Initializes a Bluetooth adapter. For API level 18 and above, get a reference to + // BluetoothAdapter through BluetoothManager. + bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); + + if (bluetoothManager == null) { + Log.e(TAG, "Unable to initialize BluetoothManager."); + return false; + } + + bluetoothAdapter = bluetoothManager.getAdapter(); + if (bluetoothAdapter == null) { + Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show(); + bluetoothManager = null; + return false; + } + + Log.e(TAG, "Bluetooth initialized"); + return true; + } + + @Override + public void clearCache() { + } + + @Override + public boolean isScanning() { + return scanning; + } + + @Override + public boolean startScanning(long timeoutMs) { + if (timeoutMs > 0) { + handler.postDelayed(this::stopScanning, timeoutMs); + } + + if (bluetoothAdapter.startLeScan(leScanCallback)) { + scanning = true; + serviceListener.onScanStarted(); + return true; + } + + return false; + } + + @Override + public void stopScanning() { + // This doesn't mind being called twice. + bluetoothAdapter.stopLeScan(leScanCallback); + + scanning = false; + + serviceListener.onScanStopped(); + } + +// @Override + public BtDevice<A> getDevice(String mac) { + BtDevice<A> device = findDevice(mac); + + if (device != null) { + return device; + } + + BluetoothDevice bluetoothDevice = bluetoothAdapter.getRemoteDevice(mac); + return register(bluetoothDevice, null, null); + } + + @Override + public List<BtDevice<A>> getDevices() { + return Collections.unmodifiableList(devices); + } + + // ----------------------------------------------------------------------- + // Scanning + // ----------------------------------------------------------------------- + + private BluetoothAdapter.LeScanCallback leScanCallback = (device, rssi, scanRecord) -> { +// Log.i(TAG, "onLeScan()"); + + BtScanResult scanResult = new BtScanResult(scanRecord); + + register(device, rssi, scanResult); + }; + + // ----------------------------------------------------------------------- + // Service Implementation + // ----------------------------------------------------------------------- + + @Override + public IBinder onBind(Intent intent) { + return binder; + } + + // ----------------------------------------------------------------------- + // Stuff + // ----------------------------------------------------------------------- + + private BtDevice<A> register(BluetoothDevice bluetoothDevice, Integer rssi, BtScanResult scanResult) { + BtDevice<A> btDevice = findDevice(bluetoothDevice.getAddress()); + + if (btDevice != null) { + return btDevice; + } + + Log.i(TAG, "New device: " + bluetoothDevice.getAddress()); + btDevice = new BtDevice<>(this, bluetoothDevice, tagConstructor.get(), rssi, scanResult); + devices.add(btDevice); + + serviceListener.onNewDevice(btDevice); + + return btDevice; + } + + private BtDevice<A> findDevice(String mac) { + for (BtDevice<A> d : devices) { + if (d.getAddress().equals(mac)) { + return d; + } + } + return null; + } +} |