startLeScan avec UUIDs 128 bits ne fonctionne pas sur l'implémentation Android blable natif

j'ai du mal à utiliser startLeScan( new UUID[]{ MY_DESIRED_128_BIT_SERVICE_UUID }, callback) sur la nouvelle API BLE introduite de Android 4.3 sur mon Nexus 4.

le rappel ne se fait pas appeler. Je peux encore voir les paquets entrants dans le journal:

08-02 15:48:57.985: I/bt-hci(1051): btu_ble_process_adv_pkt
08-02 15:48:58.636: I/bt-hci(1051): BLE HCI(id=62) event = 0x02)

si je n'utilise pas le paramètre pour filtrer les UUIDs, il fonctionne. Nous utilisons un spécifique au fabricant 128bit UUID pour l'appareil de notre société.

Maintenant, notre appareil offre plus de services que je fournis dans le tableau. Mais ça ne devrait pas être le problème.

est-ce que quelqu'un fait face au même problème? Toutes les solutions?

Modifier

il y a plusieurs problèmes liés à la numérisation, cette question n'en aborde qu'un: si vous avez aussi un problème avec la numérisation, lisez ce commentaire d'abord. Gardez également à l'esprit, que mon appareil impose un UUID 16bit et un UUID 128bit. La plupart d'entre vous utilisent des UUID à 16 bits fournis par le standard BLE comme la fréquence cardiaque ou la vitesse et la Cadence.

33
demandé sur Community 2013-08-02 18:17:23

11 réponses

le code de @Navin est bon, mais il inclut un bug de débordement du code original de 16 bits Android. (Si l'un ou l'autre octet est plus grand que 127 alors il devient un entier négatif.)

Voici une implémentation qui corrige le bug et ajoute un support de 128 bits:

private List<UUID> parseUuids(byte[] advertisedData) {
     List<UUID> uuids = new ArrayList<UUID>();

     ByteBuffer buffer = ByteBuffer.wrap(advertisedData).order(ByteOrder.LITTLE_ENDIAN);
     while (buffer.remaining() > 2) {
         byte length = buffer.get();
         if (length == 0) break;

         byte type = buffer.get();
         switch (type) {
             case 0x02: // Partial list of 16-bit UUIDs
             case 0x03: // Complete list of 16-bit UUIDs
                 while (length >= 2) {
                     uuids.add(UUID.fromString(String.format(
                             "%08x-0000-1000-8000-00805f9b34fb", buffer.getShort())));
                     length -= 2;
                 }
                 break;

             case 0x06: // Partial list of 128-bit UUIDs
             case 0x07: // Complete list of 128-bit UUIDs
                 while (length >= 16) {
                     long lsb = buffer.getLong();
                     long msb = buffer.getLong();
                     uuids.add(new UUID(msb, lsb));
                     length -= 16;
                 }
                 break;

             default:
                 buffer.position(buffer.position() + length - 1);
                 break;
         }
     }

     return uuids;
 }
38
répondu Harold Cooper 2014-07-03 12:18:00

essayez ceci pour récupérer/filtrer l'appareil à partir des UUIDs de 128 bits annoncés:

private List<UUID> parseUUIDs(final byte[] advertisedData) {
    List<UUID> uuids = new ArrayList<UUID>();

    int offset = 0;
    while (offset < (advertisedData.length - 2)) {
        int len = advertisedData[offset++];
        if (len == 0)
            break;

        int type = advertisedData[offset++];
        switch (type) {
        case 0x02: // Partial list of 16-bit UUIDs
        case 0x03: // Complete list of 16-bit UUIDs
            while (len > 1) {
                int uuid16 = advertisedData[offset++];
                uuid16 += (advertisedData[offset++] << 8);
                len -= 2;
                uuids.add(UUID.fromString(String.format(
                        "%08x-0000-1000-8000-00805f9b34fb", uuid16)));
            }
            break;
        case 0x06:// Partial list of 128-bit UUIDs
        case 0x07:// Complete list of 128-bit UUIDs
            // Loop through the advertised 128-bit UUID's.
            while (len >= 16) {
                try {
                    // Wrap the advertised bits and order them.
                    ByteBuffer buffer = ByteBuffer.wrap(advertisedData,
                            offset++, 16).order(ByteOrder.LITTLE_ENDIAN);
                    long mostSignificantBit = buffer.getLong();
                    long leastSignificantBit = buffer.getLong();
                    uuids.add(new UUID(leastSignificantBit,
                            mostSignificantBit));
                } catch (IndexOutOfBoundsException e) {
                    // Defensive programming.
                    Log.e(LOG_TAG, e.toString());
                    continue;
                } finally {
                    // Move the offset to read the next uuid.
                    offset += 15;
                    len -= 16;
                }
            }
            break;
        default:
            offset += (len - 1);
            break;
        }
    }

    return uuids;
}
21
répondu Navin Ilavarasan 2014-02-24 11:30:07

C'est un bogue signalé au moins dans Android 4.3 JWR66Y:

  • le filtrage fonctionne, si je fournis mon UUID 16bit
  • Le filtrage
  • ne renvoie aucun résultat d'analyse, si je fournis mon UUID 128bit ou si je fournis les deux UUID

mon réglage: mon appareil offre 2 UUIDs sur la publicité ( 1 16bit et 1 128bit ) et 4 UUIDs sur la découverte de service (1 128bit et 3 16bit).

même si elle est corrigée, je mets tout le monde en garde contre l'utilisation de l'option filter fournie par Android. Pour rétrocompatibilité et puisqu'il est cassé sur Samsung Galaxy S3 avec Android 4.3

10
répondu OneWorld 2017-05-23 12:18:33

bien que 4.3 ne semble pas supporter le filtrage par UUIDs 128 bits, ces UUIDs sont probablement présents dans le octet[] scanRecord retourné par le LeScanCallback.

il y a probablement une bonne façon de traiter ces données, mais si vous obtenez les mêmes données à chaque fois, vous pouvez filtrer les résultats manuellement en trouvant les offsets des UUIDs que vous recherchez. Vous pouvez le faire en imprimant les données de numérisation dans un journal (sous forme de chaîne hexadécimale) et en recherchant les Uuides qui vous intéressent. in (ils suivront probablement un 0x06 ou un 0x07 et seront inversés). Une fois que vous avez trouvé l'offset, il ne devrait pas être trop difficile de configurer un filtre de base.

voici un exemple simple qui filtre par un UUID unique (utilise Apache Commons Lang pour les tableaux et la méthode bytes-to-hex trouvée ici , mais vous pouvez substituer votre propre code si nécessaire)

public static boolean hasMyService(byte[] scanRecord) {

    // UUID we want to filter by (without hyphens)
    final String myServiceID = "0000000000001000800000805F9B34FB";

    // The offset in the scan record. In my case the offset was 13; it will probably be different for you
    final int serviceOffset = 13; 

    try{

        // Get a 16-byte array of what may or may not be the service we're filtering for
        byte[] service = ArrayUtils.subarray(scanRecord, serviceOffset, serviceOffset + 16);

        // The bytes are probably in reverse order, so we need to fix that
        ArrayUtils.reverse(service);

        // Get the hex string
        String discoveredServiceID = bytesToHex(service);

        // Compare against our service
        return myServiceID.equals(discoveredServiceID);

    } catch (Exception e){
        return false;
    }

}
5
répondu sa.shadow 2017-05-23 12:02:54

êtes-vous certain que le périphérique inscrit le service spécifié UUID dans les données de publicité ou de réponse de balayage?

1
répondu oyhovd 2013-08-07 16:48:03

la meilleure méthode pour lister les UUIDs de Service du résultat de scan est de copier exactement la parseFromBytes méthode de ScanRecord.java qui est situé à l'intérieur de l'android .Bluetooth.le paquet (assurez-vous que vous avez le dernier SDK Android), changer le retour à une liste de ParcelUuid depuis que c'est la seule chose qui nous intéresse

    private static final int DATA_TYPE_FLAGS = 0x01;
    private static final int DATA_TYPE_SERVICE_UUIDS_16_BIT_PARTIAL = 0x02;
    private static final int DATA_TYPE_SERVICE_UUIDS_16_BIT_COMPLETE = 0x03;
    private static final int DATA_TYPE_SERVICE_UUIDS_32_BIT_PARTIAL = 0x04;
    private static final int DATA_TYPE_SERVICE_UUIDS_32_BIT_COMPLETE = 0x05;
    private static final int DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL = 0x06;
    private static final int DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE = 0x07;
    private static final int DATA_TYPE_LOCAL_NAME_SHORT = 0x08;
    private static final int DATA_TYPE_LOCAL_NAME_COMPLETE = 0x09;
    private static final int DATA_TYPE_TX_POWER_LEVEL = 0x0A;
    private static final int DATA_TYPE_SERVICE_DATA = 0x16;
    private static final int DATA_TYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF;

    public static List<ParcelUuid> parseFromBytes(byte[] scanRecord) {
        if (scanRecord == null) {
            return null;
        }

        int currentPos = 0;
        int advertiseFlag = -1;
        List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>();
        String localName = null;
        int txPowerLevel = Integer.MIN_VALUE;

        SparseArray<byte[]> manufacturerData = new SparseArray<byte[]>();
        Map<ParcelUuid, byte[]> serviceData = new HashMap<ParcelUuid, byte[]>();

        try {
            while (currentPos < scanRecord.length) {
                // length is unsigned int.
                int length = scanRecord[currentPos++] & 0xFF;
                if (length == 0) {
                    break;
                }
                // Note the length includes the length of the field type itself.
                int dataLength = length - 1;
                // fieldType is unsigned int.
                int fieldType = scanRecord[currentPos++] & 0xFF;
                switch (fieldType) {
                    case DATA_TYPE_FLAGS:
                        advertiseFlag = scanRecord[currentPos] & 0xFF;
                        break;
                    case DATA_TYPE_SERVICE_UUIDS_16_BIT_PARTIAL:
                    case DATA_TYPE_SERVICE_UUIDS_16_BIT_COMPLETE:
                        parseServiceUuid(scanRecord, currentPos,
                                dataLength, 2, serviceUuids);
                        break;
                    case DATA_TYPE_SERVICE_UUIDS_32_BIT_PARTIAL:
                    case DATA_TYPE_SERVICE_UUIDS_32_BIT_COMPLETE:
                        parseServiceUuid(scanRecord, currentPos, dataLength,
                                BluetoothUuid.UUID_BYTES_32_BIT, serviceUuids);
                        break;
                    case DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL:
                    case DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE:
                        parseServiceUuid(scanRecord, currentPos, dataLength,
                                BluetoothUuid.UUID_BYTES_128_BIT, serviceUuids);
                        break;
                    case DATA_TYPE_LOCAL_NAME_SHORT:
                    case DATA_TYPE_LOCAL_NAME_COMPLETE:
                        localName = new String(
                                extractBytes(scanRecord, currentPos, dataLength));
                        break;
                    case DATA_TYPE_TX_POWER_LEVEL:
                        txPowerLevel = scanRecord[currentPos];
                        break;
                    case DATA_TYPE_SERVICE_DATA:
                        // The first two bytes of the service data are service data UUID in little
                        // endian. The rest bytes are service data.
                        int serviceUuidLength = BluetoothUuid.UUID_BYTES_16_BIT;
                        byte[] serviceDataUuidBytes = extractBytes(scanRecord, currentPos,
                                serviceUuidLength);
                        ParcelUuid serviceDataUuid = BluetoothUuid.parseUuidFrom(
                                serviceDataUuidBytes);
                        byte[] serviceDataArray = extractBytes(scanRecord,
                                currentPos + serviceUuidLength, dataLength - serviceUuidLength);
                        serviceData.put(serviceDataUuid, serviceDataArray);
                        break;
                    case DATA_TYPE_MANUFACTURER_SPECIFIC_DATA:
                        // The first two bytes of the manufacturer specific data are
                        // manufacturer ids in little endian.
                        int manufacturerId = ((scanRecord[currentPos + 1] & 0xFF) << 8) +
                                (scanRecord[currentPos] & 0xFF);
                        byte[] manufacturerDataBytes = extractBytes(scanRecord, currentPos + 2,
                                dataLength - 2);
                        manufacturerData.put(manufacturerId, manufacturerDataBytes);
                        break;
                    default:
                        // Just ignore, we don't handle such data type.
                        break;
                }
                currentPos += dataLength;
            }

            if (serviceUuids.isEmpty()) {
                serviceUuids = null;
            }

//            Log.i("SERVICE UUIDS", parcelUuidToString(serviceUuids));
        } catch (Exception e) {
            Log.e(TAG, "unable to parse scan record: " + Arrays.toString(scanRecord));
            // As the record is invalid, ignore all the parsed results for this packet
            // and return an empty record with raw scanRecord bytes in results
        }

        return serviceUuids;
    }

vous devez importer BluetoothUuid.java dans le même package ainsi:

import java.util.UUID;
import android.os.ParcelUuid;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
import java.util.HashSet;
/**
 * Static helper methods and constants to decode the ParcelUuid of remote devices.
 *  @hide
 */
public final class BluetoothUuid {
    /* See Bluetooth Assigned Numbers document - SDP section, to get the values of UUIDs
     * for the various services.
     *
     * The following 128 bit values are calculated as:
     *  uuid * 2^96 + BASE_UUID
     */
    public static final ParcelUuid AudioSink =
            ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB");
    public static final ParcelUuid AudioSource =
            ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB");
    public static final ParcelUuid AdvAudioDist =
            ParcelUuid.fromString("0000110D-0000-1000-8000-00805F9B34FB");
    public static final ParcelUuid HSP =
            ParcelUuid.fromString("00001108-0000-1000-8000-00805F9B34FB");
    public static final ParcelUuid HSP_AG =
            ParcelUuid.fromString("00001112-0000-1000-8000-00805F9B34FB");
    public static final ParcelUuid Handsfree =
            ParcelUuid.fromString("0000111E-0000-1000-8000-00805F9B34FB");
    public static final ParcelUuid Handsfree_AG =
            ParcelUuid.fromString("0000111F-0000-1000-8000-00805F9B34FB");
    public static final ParcelUuid AvrcpController =
            ParcelUuid.fromString("0000110E-0000-1000-8000-00805F9B34FB");
    public static final ParcelUuid AvrcpTarget =
            ParcelUuid.fromString("0000110C-0000-1000-8000-00805F9B34FB");
    public static final ParcelUuid ObexObjectPush =
            ParcelUuid.fromString("00001105-0000-1000-8000-00805f9b34fb");
    public static final ParcelUuid Hid =
            ParcelUuid.fromString("00001124-0000-1000-8000-00805f9b34fb");
    public static final ParcelUuid Hogp =
            ParcelUuid.fromString("00001812-0000-1000-8000-00805f9b34fb");
    public static final ParcelUuid PANU =
            ParcelUuid.fromString("00001115-0000-1000-8000-00805F9B34FB");
    public static final ParcelUuid NAP =
            ParcelUuid.fromString("00001116-0000-1000-8000-00805F9B34FB");
    public static final ParcelUuid BNEP =
            ParcelUuid.fromString("0000000f-0000-1000-8000-00805F9B34FB");
    public static final ParcelUuid PBAP_PCE =
            ParcelUuid.fromString("0000112e-0000-1000-8000-00805F9B34FB");
    public static final ParcelUuid PBAP_PSE =
            ParcelUuid.fromString("0000112f-0000-1000-8000-00805F9B34FB");
    public static final ParcelUuid MAP =
            ParcelUuid.fromString("00001134-0000-1000-8000-00805F9B34FB");
    public static final ParcelUuid MNS =
            ParcelUuid.fromString("00001133-0000-1000-8000-00805F9B34FB");
    public static final ParcelUuid MAS =
            ParcelUuid.fromString("00001132-0000-1000-8000-00805F9B34FB");
    public static final ParcelUuid SAP =
            ParcelUuid.fromString("0000112D-0000-1000-8000-00805F9B34FB");

    public static final ParcelUuid BASE_UUID =
            ParcelUuid.fromString("00000000-0000-1000-8000-00805F9B34FB");
    /** Length of bytes for 16 bit UUID */
    public static final int UUID_BYTES_16_BIT = 2;
    /** Length of bytes for 32 bit UUID */
    public static final int UUID_BYTES_32_BIT = 4;
    /** Length of bytes for 128 bit UUID */
    public static final int UUID_BYTES_128_BIT = 16;
    public static final ParcelUuid[] RESERVED_UUIDS = {
            AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget,
            ObexObjectPush, PANU, NAP, MAP, MNS, MAS, SAP};
    public static boolean isAudioSource(ParcelUuid uuid) {
        return uuid.equals(AudioSource);
    }
    public static boolean isAudioSink(ParcelUuid uuid) {
        return uuid.equals(AudioSink);
    }
    public static boolean isAdvAudioDist(ParcelUuid uuid) {
        return uuid.equals(AdvAudioDist);
    }
    public static boolean isHandsfree(ParcelUuid uuid) {
        return uuid.equals(Handsfree);
    }
    public static boolean isHeadset(ParcelUuid uuid) {
        return uuid.equals(HSP);
    }
    public static boolean isAvrcpController(ParcelUuid uuid) {
        return uuid.equals(AvrcpController);
    }
    public static boolean isAvrcpTarget(ParcelUuid uuid) {
        return uuid.equals(AvrcpTarget);
    }
    public static boolean isInputDevice(ParcelUuid uuid) {
        return uuid.equals(Hid);
    }
    public static boolean isPanu(ParcelUuid uuid) {
        return uuid.equals(PANU);
    }
    public static boolean isNap(ParcelUuid uuid) {
        return uuid.equals(NAP);
    }
    public static boolean isBnep(ParcelUuid uuid) {
        return uuid.equals(BNEP);
    }
    public static boolean isMap(ParcelUuid uuid) {
        return uuid.equals(MAP);
    }
    public static boolean isMns(ParcelUuid uuid) {
        return uuid.equals(MNS);
    }
    public static boolean isMas(ParcelUuid uuid) {
        return uuid.equals(MAS);
    }
    public static boolean isSap(ParcelUuid uuid) {
        return uuid.equals(SAP);
    }
    /**
     * Returns true if ParcelUuid is present in uuidArray
     *
     * @param uuidArray - Array of ParcelUuids
     * @param uuid
     */
    public static boolean isUuidPresent(ParcelUuid[] uuidArray, ParcelUuid uuid) {
        if ((uuidArray == null || uuidArray.length == 0) && uuid == null)
            return true;
        if (uuidArray == null)
            return false;
        for (ParcelUuid element: uuidArray) {
            if (element.equals(uuid)) return true;
        }
        return false;
    }
    /**
     * Returns true if there any common ParcelUuids in uuidA and uuidB.
     *
     * @param uuidA - List of ParcelUuids
     * @param uuidB - List of ParcelUuids
     *
     */
    public static boolean containsAnyUuid(ParcelUuid[] uuidA, ParcelUuid[] uuidB) {
        if (uuidA == null && uuidB == null) return true;
        if (uuidA == null) {
            return uuidB.length == 0 ? true : false;
        }
        if (uuidB == null) {
            return uuidA.length == 0 ? true : false;
        }
        HashSet<ParcelUuid> uuidSet = new HashSet<ParcelUuid> (Arrays.asList(uuidA));
        for (ParcelUuid uuid: uuidB) {
            if (uuidSet.contains(uuid)) return true;
        }
        return false;
    }
    /**
     * Returns true if all the ParcelUuids in ParcelUuidB are present in
     * ParcelUuidA
     *
     * @param uuidA - Array of ParcelUuidsA
     * @param uuidB - Array of ParcelUuidsB
     *
     */
    public static boolean containsAllUuids(ParcelUuid[] uuidA, ParcelUuid[] uuidB) {
        if (uuidA == null && uuidB == null) return true;
        if (uuidA == null) {
            return uuidB.length == 0 ? true : false;
        }
        if (uuidB == null) return true;
        HashSet<ParcelUuid> uuidSet = new HashSet<ParcelUuid> (Arrays.asList(uuidA));
        for (ParcelUuid uuid: uuidB) {
            if (!uuidSet.contains(uuid)) return false;
        }
        return true;
    }
    /**
     * Extract the Service Identifier or the actual uuid from the Parcel Uuid.
     * For example, if 0000110B-0000-1000-8000-00805F9B34FB is the parcel Uuid,
     * this function will return 110B
     * @param parcelUuid
     * @return the service identifier.
     */
    public static int getServiceIdentifierFromParcelUuid(ParcelUuid parcelUuid) {
        UUID uuid = parcelUuid.getUuid();
        long value = (uuid.getMostSignificantBits() & 0x0000FFFF00000000L) >>> 32;
        return (int)value;
    }
    /**
     * Parse UUID from bytes. The {@code uuidBytes} can represent a 16-bit, 32-bit or 128-bit UUID,
     * but the returned UUID is always in 128-bit format.
     * Note UUID is little endian in Bluetooth.
     *
     * @param uuidBytes Byte representation of uuid.
     * @return {@link ParcelUuid} parsed from bytes.
     * @throws IllegalArgumentException If the {@code uuidBytes} cannot be parsed.
     */
    public static ParcelUuid parseUuidFrom(byte[] uuidBytes) {
        if (uuidBytes == null) {
            throw new IllegalArgumentException("uuidBytes cannot be null");
        }
        int length = uuidBytes.length;
        if (length != UUID_BYTES_16_BIT && length != UUID_BYTES_32_BIT &&
                length != UUID_BYTES_128_BIT) {
            throw new IllegalArgumentException("uuidBytes length invalid - " + length);
        }
        // Construct a 128 bit UUID.
        if (length == UUID_BYTES_128_BIT) {
            ByteBuffer buf = ByteBuffer.wrap(uuidBytes).order(ByteOrder.LITTLE_ENDIAN);
            long msb = buf.getLong(8);
            long lsb = buf.getLong(0);
            return new ParcelUuid(new UUID(msb, lsb));
        }
        // For 16 bit and 32 bit UUID we need to convert them to 128 bit value.
        // 128_bit_value = uuid * 2^96 + BASE_UUID
        long shortUuid;
        if (length == UUID_BYTES_16_BIT) {
            shortUuid = uuidBytes[0] & 0xFF;
            shortUuid += (uuidBytes[1] & 0xFF) << 8;
        } else {
            shortUuid = uuidBytes[0] & 0xFF ;
            shortUuid += (uuidBytes[1] & 0xFF) << 8;
            shortUuid += (uuidBytes[2] & 0xFF) << 16;
            shortUuid += (uuidBytes[3] & 0xFF) << 24;
        }
        long msb = BASE_UUID.getUuid().getMostSignificantBits() + (shortUuid << 32);
        long lsb = BASE_UUID.getUuid().getLeastSignificantBits();
        return new ParcelUuid(new UUID(msb, lsb));
    }
    /**
     * Parse UUID to bytes. The returned value is shortest representation, a 16-bit, 32-bit or 128-bit UUID,
     * Note returned value is little endian (Bluetooth).
     *
     * @param uuid uuid to parse.
     * @return shortest representation of {@code uuid} as bytes.
     * @throws IllegalArgumentException If the {@code uuid} is null.
     */
    public static byte[] uuidToBytes(ParcelUuid uuid) {
        if (uuid == null) {
            throw new IllegalArgumentException("uuid cannot be null");
        }
        if (is16BitUuid(uuid)) {
            byte[] uuidBytes = new byte[UUID_BYTES_16_BIT];
            int uuidVal = getServiceIdentifierFromParcelUuid(uuid);
            uuidBytes[0] = (byte)(uuidVal & 0xFF);
            uuidBytes[1] = (byte)((uuidVal & 0xFF00) >> 8);
            return uuidBytes;
        }
        if (is32BitUuid(uuid)) {
            byte[] uuidBytes = new byte[UUID_BYTES_32_BIT];
            int uuidVal = getServiceIdentifierFromParcelUuid(uuid);
            uuidBytes[0] = (byte)(uuidVal & 0xFF);
            uuidBytes[1] = (byte)((uuidVal & 0xFF00) >> 8);
            uuidBytes[2] = (byte)((uuidVal & 0xFF0000) >> 16);
            uuidBytes[3] = (byte)((uuidVal & 0xFF000000) >> 24);
            return uuidBytes;
        }
        // Construct a 128 bit UUID.
        long msb = uuid.getUuid().getMostSignificantBits();
        long lsb = uuid.getUuid().getLeastSignificantBits();
        byte[] uuidBytes = new byte[UUID_BYTES_128_BIT];
        ByteBuffer buf = ByteBuffer.wrap(uuidBytes).order(ByteOrder.LITTLE_ENDIAN);
        buf.putLong(8, msb);
        buf.putLong(0, lsb);
        return uuidBytes;
    }
    /**
     * Check whether the given parcelUuid can be converted to 16 bit bluetooth uuid.
     *
     * @param parcelUuid
     * @return true if the parcelUuid can be converted to 16 bit uuid, false otherwise.
     */
    public static boolean is16BitUuid(ParcelUuid parcelUuid) {
        UUID uuid = parcelUuid.getUuid();
        if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) {
            return false;
        }
        return ((uuid.getMostSignificantBits() & 0xFFFF0000FFFFFFFFL) == 0x1000L);
    }
    /**
     * Check whether the given parcelUuid can be converted to 32 bit bluetooth uuid.
     *
     * @param parcelUuid
     * @return true if the parcelUuid can be converted to 32 bit uuid, false otherwise.
     */
    public static boolean is32BitUuid(ParcelUuid parcelUuid) {
        UUID uuid = parcelUuid.getUuid();
        if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) {
            return false;
        }
        if (is16BitUuid(parcelUuid)) {
            return false;
        }
        return ((uuid.getMostSignificantBits() & 0xFFFFFFFFL) == 0x1000L);
    }

D'après mes tests, les résultats donnent exactement ce que je veux.

1
répondu Zany K 2017-03-11 06:38:25

vous devez ajouter service UUID dans les données de l'annonce comme le lien

puis vous pouvez réessayer startLeScan (UUID[],callback).

j'avais réussi par cette méthode à découvrir thermomètre dispositif avec UUID spécifique [0x1809]

ça marche pour moi.

0
répondu Samuel C. 2013-08-15 05:29:04

mon expérience est que j'ai dû fournir chaque service qu'un appareil que je veux connecter présente, pas seulement celui qui me préoccupe. J'ai fini par faire des recherches de service après scan pour contourner ça.

0
répondu Douglas Jones 2013-08-19 21:59:40

128 bits UUID le scan a fonctionné sur Samsung S5, exécutant Android 4.4.2; mais oui, il échoue sur Nexus 4, 7. Testé sur 4.4.2, 4.4.3, 4.4.4.

0
répondu Khulja Sim Sim 2014-06-25 01:59:48

J'ai trouvé un bug dans Android source 5.x, mais pas présent en 6.x.

il y a une fonction dans ce fichier: http://androidxref.com/5.1.1_r6/xref/external/bluetooth/bluedroid/bta/dm/bta_dm_api.c#1560 utilisé pour passer un data_mask 32 bits à la pile de réponse Bluetooth le advertising and scan. Mais la structure "tBTA_DM_API_SET_ADV_CONFIG;" gère la valeur de 16 bits !!! Ainsi, changer UINT16 en UINT32 dor data_mask, recompiler Android et cela fonctionnera. Rif http://androidxref.com/5.1.1_r6/xref/external/bluetooth/bluedroid/bta/dm/bta_dm_int.h#594

0
répondu gpaga 2015-10-09 14:19:48

j'ai rencontré le même problème avec le SensorTag de TI en utilisant ma N7 2013 avec Android 4.3.

ce que j'ai trouvé à faire est de démarrer le LeScan, attendre une seconde, l'arrêter et puis le redémarrer.

        if(!mBluetoothAdapter.startLeScan(mBleScanCallback)){
            L.e("could not start scan action");
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {}
        mBluetoothAdapter.stopLeScan(mBleScanCallback);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {}
        mBluetoothAdapter.startLeScan(mBleScanCallback);

J'ai aussi remarqué que parfois la connexion n'est pas établie (cela pourrait ou non être lié à l'implémentation du firmware ou à la fermeture correcte de la connexion). De la même façon, il semble que d'essayer de se reconnecter pour le gatt semble faire l'affaire.

avoir à utiliser ces solutions de rechange est vraiment décevant...

-2
répondu nexuscomputing 2013-09-16 15:26:45