All Projects β†’ LeandroSQ β†’ android-ble-made-easy

LeandroSQ / android-ble-made-easy

Licence: MIT License
An Android Library for handling Bluetooth Low Energy on Android Easy

Programming Languages

kotlin
9241 projects

Projects that are alternatives of or similar to android-ble-made-easy

Bluetooth-ble-beamer-and-scanner-for-tracing-corona-virus-infected-individual
Bluetooth ble beacon beamer and scanner for tracing corona virus infected person similar to Trace Together app
Stars: ✭ 26 (-23.53%)
Mutual labels:  bluetooth, ble, bluetooth-low-energy
H.E.L.P.
Home Environment Locating People 🍍
Stars: ✭ 19 (-44.12%)
Mutual labels:  bluetooth, ble, bluetooth-low-energy
bluetooth-terminal
ES6 class for serial communication with your own Bluetooth Low Energy (Smart) devices
Stars: ✭ 43 (+26.47%)
Mutual labels:  bluetooth, ble, bluetooth-low-energy
Reactivebeacons
Android library scanning BLE beacons nearby with RxJava
Stars: ✭ 171 (+402.94%)
Mutual labels:  bluetooth, ble, bluetooth-low-energy
theheraldproject.github.io
Herald - Proximity Detection Protocol and research documentation, including the Fair Efficacy Formula
Stars: ✭ 17 (-50%)
Mutual labels:  bluetooth, ble, bluetooth-low-energy
Continuity
Apple Continuity Protocol Reverse Engineering and Dissector
Stars: ✭ 180 (+429.41%)
Mutual labels:  bluetooth, ble, bluetooth-low-energy
awesome-bluetooth-security
List of Bluetooth BR/EDR/LE security resources
Stars: ✭ 220 (+547.06%)
Mutual labels:  bluetooth, ble, bluetooth-low-energy
Easyble
Android BLE framework
Stars: ✭ 155 (+355.88%)
Mutual labels:  bluetooth, ble, bluetooth-low-energy
SmartSpin2k
Transform your spin bike into a Smart Trainer!
Stars: ✭ 88 (+158.82%)
Mutual labels:  bluetooth, ble, bluetooth-low-energy
daydream-node
Quick Node.js module to connect to the Daydream controller and receive all the data
Stars: ✭ 17 (-50%)
Mutual labels:  bluetooth, ble, bluetooth-low-energy
bluetooth-manager
Java Bluetooth Manager. A library/framework for managing bluetooth adapters, bluetooth devices, GATT services and characteristics
Stars: ✭ 75 (+120.59%)
Mutual labels:  bluetooth, ble, bluetooth-low-energy
BLELib
This library contains many of the features you need to interact with BLE peripherals
Stars: ✭ 21 (-38.24%)
Mutual labels:  bluetooth, ble, bluetooth-low-energy
H Ble
Android Bleη±»εΊ“οΌŒεŸΊδΊŽε›žθ°ƒοΌŒζš΄ιœ²ζœη΄’γ€θΏžζŽ₯、发送、ζŽ₯ζ”Άγ€ζ–­εΌ€θΏžζŽ₯η­‰ζŽ₯ε£οΌŒζ— ιœ€ε…³εΏƒη»†θŠ‚ζ“δ½œε³ε―θΏ›θ‘ŒBleι€šδΏ‘γ€‚
Stars: ✭ 171 (+402.94%)
Mutual labels:  bluetooth, ble, bluetooth-low-energy
Bluetooth
Cross-platform Bluetooth API for Go and TinyGo.
Stars: ✭ 246 (+623.53%)
Mutual labels:  bluetooth, ble, bluetooth-low-energy
Node Ble
Bluetooth Low Energy (BLE) library written with pure Node.js (no bindings) - baked by Bluez via DBus
Stars: ✭ 159 (+367.65%)
Mutual labels:  bluetooth, ble, bluetooth-low-energy
py-bluetooth-utils
Python module containing bluetooth utility functions, in particular for easy BLE scanning and advertising
Stars: ✭ 60 (+76.47%)
Mutual labels:  bluetooth, ble, bluetooth-low-energy
Web Bluetooth Terminal
Progressive Web Application for serial communication with your own Bluetooth Low Energy (Smart) devices
Stars: ✭ 130 (+282.35%)
Mutual labels:  bluetooth, ble, bluetooth-low-energy
Ble.net
Cross-platform Bluetooth Low Energy (BLE) library for Android, iOS, and UWP
Stars: ✭ 137 (+302.94%)
Mutual labels:  bluetooth, ble, bluetooth-low-energy
ble
Bluetooth Low Energy for Linux / macOS
Stars: ✭ 264 (+676.47%)
Mutual labels:  bluetooth, ble, bluetooth-low-energy
ESP32BleAdvertise
Simple library for BLE advertise using ESP32 in Arduino
Stars: ✭ 39 (+14.71%)
Mutual labels:  bluetooth, ble, bluetooth-low-energy

Android BLE Made Easy

An easy to use, kotlin friendly BLE library for Android.

API

Installing

  • Step 1. Add the JitPack repository to your project gradle file
allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}
  • Step 1.1 Only if you have the file settings.gradle at your project root folder

    • Add the JitPack repository to your project settings.gradle file
    dependencyResolutionManagement {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }
    • Add the JitPack repository to your project gradle file
    buildscript {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }
  • Step 2. Add the implementation dependency to your app gradle file

dependencies {
    ...

    implementation 'com.github.LeandroSQ:android-ble-made-easy:1.5.2'

    ...
}
  • Step 3. Gradle sync

  • Step 4. Add these permissions to your manifest.xml file

<uses-permission
    android:name="android.permission.BLUETOOTH"
    android:maxSdkVersion="30" />
<uses-permission
    android:name="android.permission.BLUETOOTH_ADMIN"
    android:maxSdkVersion="30" />

<!-- These 2 bellow, only if you are targeting Android 12+ -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"
    tools:targetApi="s" />
<uses-permission
    android:name="android.permission.BLUETOOTH_SCAN"
    android:usesPermissionFlags="neverForLocation"
    tools:targetApi="s" />

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

<!-- These 2 bellow, only if you are targeting Android 10+ -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
<uses-feature android:name="android.hardware.bluetooth" android:required="true"/>

And you are ready to go!


Core features

Lifecycle

The library accepts being used both in an Activity and a Fragment!

val ble = BLE(activity = this)
// or
val ble = BLE(fragment = this)

Automatic handle permissions

The library requests the permissions for you.

Asynchronous:

ble.verifyPermissionsAsync(
    rationaleRequestCallback = { next ->
        // Include your code to show an Alert or UI explaining why the permissions are required
        // Calling the function bellow if the user agrees to give the permissions
        next()
    },
    callback = { granted ->
        if (granted) {
            // Continue your code....
        } else {
            // Include your code to show an Alert or UI indicating that the permissions are required
        }
    }
)

Coroutines:

GlobalScope.launch {
    val granted = ble.verifyPermissions(
        rationaleRequestCallback = { next ->
            // Include your code to show an Alert or UI explaining why the permissions are required
            // Calling the function bellow if the user agrees to give the permissions
            next()
        }
    )

    if (granted) {
        // Continue your code....
    } else {
        // Include your code to show an Alert or UI indicating that the permissions are required
    }
}

Automatic turn on the Bluetooth adapter

The library requests the Bluetooth hardware to be activated whenever it is off.

Asynchronous:

ble.verifyBluetoothAdapterStateAsync { active ->
    if (active) {
        // Continue your code...
    } else {
        // Include your code to show an Alert or UI indicating that the Bluetooth adapter is required to be on in order to your project work
    }
}

Coroutines:

GlobalScope.launch {
    if (ble.verifyBluetoothAdapterState()) {
        // Continue your code...
    } else {
        // Include your code to show an Alert or UI indicating that the Bluetooth adapter is required to be on in order to your project work
    }
}

Automatic turn on Location services

The library requests Location services to be activated whenever it is off.

Asynchronous:

ble.verifyLocationStateAsync{ active ->
    if (active) {
        // Continue your code...
    } else {
        // Include your code to show an Alert or UI indicating that Location is required to be on in order to your project work
    }
}

Coroutines:

GlobalScope.launch {
    if (ble.verifyLocationState()) {
        // Continue your code...
    } else {
        // Include your code to show an Alert or UI indicating that Location is required to be on in order to your project work
    }
}

Asynchronous and Coroutines

You can both use the library with callbacks and with coroutines suspended functions The callback functions having the 'async' suffix. And requiring a HOF callback as a parameter .

Handling the bluetooth connections with graceful connection shutdown, in another words, waits for current running operations (Read and Write) to be finished before closing the connection

JetPack Contracts Ready!

The library uses the new JetPack contracts API to automatically handle permissions and adapter activation for you.

Compatible with older API levels

Theoretically compatible all the way down to API 18, but made targeting API 21+.

Well documented!

All the functions and variables you're gonna be using are very well documented with KotlinDOC. So you can get autocompletion information on Android Studio. But if you want to take a look without installing it... You can take a look on the dokka generated documentation

.github/workflows/wiki.yml

Both low level bytes and String conversion

The library gives you the option to receive and send raw Bytes if you want. But also you can let it encode and decode your strings automatically.

Automatically handles the pain of Known issues

Take for instance Issue 183108 where Lollipop devices will not work properly without a workaround to handle the connection.

Or the well-known BLE 133 error! The nightmare of everyone that already worked with BLE on Android, this library has a compilation of techniques being used to get around it

Usage

After instantiating the BLE class...

Fast scan for a specific device

If you already know the device you wanna connect to, you could use this:

Asynchronous:

ble.scanForAsync(
    // You only need to supply one of these, no need for all of them!
    macAddress = "00:00:00:00",
    name = "ESP32",
    service = "00000000-0000-0000-0000-000000000000",
    onFinish = { connection ->
        if (connection != null) {
            // And you can continue with your code
            it.write("00000000-0000-0000-0000-000000000000", "Testing")
        } else {
            // Show an Alert or UI with your preferred error message about the device not being available
        }
    },
       onError = { errorCode ->
         // Show an Alert or UI with your preferred error message about the error
    }
)

// It is important to keep in mind that every single one of the provided arguments of the function shown above, are optionals! Therefore, you can skip the ones that you don't need.

Coroutines:

GlobalScope.launch {
    // You can specify filters for your device, being them 'macAddress', 'service' and 'name'
    val connection = ble.scanFor(
        // You only need to supply one of these, no need for all of them!
        macAddress = "00:00:00:00",
        name = "ESP32",
        service = "00000000-0000-0000-0000-000000000000"
    )

    // And it will automatically connect to your device, no need to boilerplate
    if (connection != null) {
        // And you can continue with your code
        it.write("00000000-0000-0000-0000-000000000000", "Testing")
    } else {
        // Show an Alert or UI with your preferred error message about the device not being available
    }
}

Scanning BLE devices

Asynchronous:

ble.scanAsync(
    duration = 10000,
    onDiscover = { device ->
        // Update your UI with the newest found device, in real time
    },
    onFinish = { devices ->
        // Continue with your code handling all the devices found
    },
    onError = { errorCode ->
        // Show an Alert or UI with your preferred error message
    }
)

Coroutines:

GlobalScope.launch {
    try {
        // Continue with your code handling all the devices found
        val devices = ble.scan(duration = 10000)
    } catch (e: Exception) {
        // Show an Alert or UI with your preferred error message
    } catch (e: ScanFailureException) {
        // Show an Alert or UI with your preferred error message
    }
}

Or you could use the scan method without any timeout, only stopping it manually

ble.scanAsync(
    duration = 0, // Disables the timeout
    onDiscover = { device ->
        // Update your UI with the newest found device, in real time
    },
    onFinish = { devices ->
        // Continue with your code handling all the devices found
    },
    onError = { errorCode ->
        // Show an Alert or UI with your preferred error message
    }
)

// Stops your scan manually
ble.stopScan()

Manually connecting to a discovered device

After a successful scan, you'll have your Bluetooth device, now it is time to connect with it!

ble.connect(device)?.let { connection ->
    // Continue with your code
    val value = connection.read("00000000-0000-0000-0000-000000000000")
    connection.write("00000000-0000-0000-0000-000000000000", "0")
    connection.close()
}

Observing changes

There are two ways to observe changes, the first is using the native BLE NOTIFY, which is the preferred option.

// If you want to make use of the NOTIFY functionality
ble.connect(device)?.let { connection ->

    // For watching bytes
    connection.observe(characteristic = "00000000-0000-0000-0000-000000000000") { value: ByteArray ->
        // This will run everytime the characteristic changes it's value
    }

    // For watching strings
    connection.observeString(characteristic = "00000000-0000-0000-0000-000000000000", charset = Charsets.UTF_8) { value: String ->
        // This will run everytime the characteristic changes it's value
    }
}

The second way is to manually read the characteristic in a fixed interval and compare with the last value. Which uses more battery, isn't as effective and should only be used when the characteristic doesn't provide the NOTIFY property. Fortunately the library handles both ways in a similar API.

// If you want to use NOTIFY when available and fallback to the legacy way when it isn't
ble.connect(device)?.let { connection ->
    connection.observe(
        characteristic = "00000000-0000-0000-0000-000000000000",
        owner = viewLifeCycleOwner, // The Lifecycle Owner to attach to
        interval = 1000L // The interval in ms (in this example 1 second)
    ) { value: ByteArray ->
        // This will run everytime the characteristic changes it's value
    }
}

Made With <3 by Leandro Quevedo

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].