Ble:将广告数据从Android发送到iOS [英] Ble: Send advertise data to iOS from Android

查看:217
本文介绍了Ble:将广告数据从Android发送到iOS的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须通过ble将一些广告数据发送到iOS中央应用程序.在Android外围设备方面,当我创建广告时,我会这样做:

I have to send some advertise data via ble to an iOS central app. On Android peripheral side, when i create advertise i do:

    var byteArrayData = dataToSend.toByteArray(Charsets.UTF_8)

    var data = AdvertiseData.Builder().apply {
        addServiceData(
            ParcelUuid(MY_SERVICE_UUID),
            byteArrayData
        )
    }
    bleAdvertiser.startAdvertising(mySettings.build(), data.build(), myAdvertiseCallback)

,但似乎iOS无法读取自定义服务数据.

but it seems that iOS is not able to read custom service data.

因此,有一种方法可以通过BLE向iOS发送一些小数据(少量字节)(并在Android为中心而iOS为外围设备时也接收数据)?

So, there's a way to sent some small data (few bytes) via BLE to iOS (and receive also data when Android is central and iOS is pheripheral)?

如果可能的话,我会避免在中央外围设备之间建立连接.

I would avoid, if is possible, to open a connection between central an peripheral.

推荐答案

iOS对广告数据的限制非常严格.无论是发送还是接收它,您都只能控制它的一小部分.它的大部分由iOS本身控制,并且在中央管理者的情况下,甚至都不会转发到该应用.

iOS is very restrictive regarding advertisement data. Both when sending and receiving it, you can only control a small subset of it. Most of it is controlled by iOS itself and — in case of the central manager role — not even forwarded to the app.

广告数据检索键是例外,适用于< centralManager(_:didDiscover:advertisementData:rssi的em> advertisementData 参数:) .

The exceptions are the Advertisement Data Retrieval Keys, applicable for the advertisementData parameter of centralManager(_:didDiscover:advertisementData:rssi:).

答案中提到了一个更具体的示例.

A more specific example is mentioned in this answer.

更新

即使其中之一是用于服务数据,我也不认为数据会转发到应用程序.但是我可能是错的.我想您是在问这个问题,因为未设置键CBAdvertisementDataServiceDataKey.

Even though one of the keys is for service data, I don't think the data is forwarded to the app. But I might be wrong. I guess you are asking this question because the key CBAdvertisementDataServiceDataKey is not set.

更新2

我创建了一个最小的Android和iOS示例,并使它可以正常工作.我认为您的Android代码中没有明显的问题.因此,您需要与您的iOS同事交谈...

I've created a minimal Android and iOS example and got it working without any problem. I don't see no obvious problem in your Android code. So you will need to talk to your iOS colleague...

服务数据为"ABC"(或十六进制的61 62 63),而16位UUID为FF01. iOS日志输出为:

The service data is "ABC" (or 61 62 63 in hex) and the 16-bit UUID is FF01. The iOS log output is:

2019-09-05 16:39:18.987142+0200 BleScanner[18568:3982403] [Scanner] Advertisement data: FF01: <616263>

Android-MainActivity.kt

package bleadvertiser

import android.bluetooth.BluetoothManager
import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

class MainActivity : AppCompatActivity() {

    private var peripheral: Peripheral? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    override fun onStart() {
        super.onStart()
        val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
        peripheral = Peripheral(bluetoothManager.adapter)
        peripheral?.startAdvertising()
    }
}

Android-Peripheral.kt

package bleadvertiser

import android.bluetooth.BluetoothAdapter
import android.bluetooth.le.AdvertiseCallback
import android.bluetooth.le.AdvertiseData
import android.bluetooth.le.AdvertiseSettings
import android.os.ParcelUuid
import android.util.Log
import java.util.*

private const val TAG = "Peripheral"

class Peripheral(private val bluetoothAdapter: BluetoothAdapter) {

    fun startAdvertising() {
        val advertiseSettings = AdvertiseSettings.Builder().build()
        val serviceData = "abc".toByteArray(Charsets.UTF_8)
        val advertiseData = AdvertiseData.Builder()
            .addServiceData(ParcelUuid(SERVICE_UUID), serviceData)
            .build()
        val advertiser = bluetoothAdapter.bluetoothLeAdvertiser
        advertiser.startAdvertising(advertiseSettings, advertiseData, advertiseCallback)
    }

    private val advertiseCallback = object: AdvertiseCallback() {
        override fun onStartFailure(errorCode: Int) {
            Log.w(TAG, String.format("Advertisement failure (code %d)", errorCode))
        }
        override fun onStartSuccess(settingsInEffect: AdvertiseSettings?) {
            Log.i(TAG, "Advertisement started")
        }
    }

    companion object {
        val SERVICE_UUID: UUID = UUID.fromString("0000ff01-0000-1000-8000-00805F9B34FB")
    }
}

iOS-ViewController.swift

import UIKit

class ViewController: UIViewController {

    var bleScanner: BleScanner?

    override func viewDidLoad() {
        super.viewDidLoad()
        bleScanner = BleScanner()
    }
}

iOS-BleScanner.swift

import Foundation
import CoreBluetooth
import os.log

class BleScanner : NSObject {

    static let serviceUUID = CBUUID(string: "FF01")
    static let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "Scanner")

    private var centralManager: CBCentralManager!
    private var scanningTimer: Timer?

    override init() {
        super.init()
        centralManager = CBCentralManager(delegate: self, queue: nil)
    }

    func startScanning() {
        scanningTimer = Timer.scheduledTimer(withTimeInterval: TimeInterval(20), repeats: false, block: { (_) in
            self.stopScanning()
        })
        centralManager.scanForPeripherals(withServices: [ BleScanner.serviceUUID ], options: nil)
    }

    func stopScanning() {
        centralManager.stopScan()
    }
}

extension BleScanner : CBCentralManagerDelegate {

    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        if centralManager.state == .poweredOn {
            startScanning()
        }
    }

    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        for (key, value) in advertisementData {
            if key == CBAdvertisementDataServiceDataKey {
                let serviceData = value as! [CBUUID : NSData]
                for (uuid, data) in serviceData {
                    os_log("Advertisement data: %{public}s: %{public}s", log: BleScanner.log, type: .info, uuid.uuidString, data.debugDescription)
                }
            }
        }
    }
}

这篇关于Ble:将广告数据从Android发送到iOS的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆