基于BLE传输Android至iOS图片字节后,iOS端Swift图片还原方法咨询
Since your Android code sends JPEG-compressed byte chunks over BLE, here's a straightforward way to reassemble and convert those bytes into a usable image in Swift:
1. Accumulate Incoming Byte Chunks
First, you need to collect all the BLE data chunks into a single Data object. You’ll need to track when the full image data has been received—two common approaches work here: using a total length marker or leveraging the JPEG file’s natural end sequence.
Setup Class-Level Variables
// Track accumulated image data and expected total bytes (if using length marker) private var accumulatedImageData = Data() private var expectedTotalBytes: Int?
2. Handle BLE Characteristic Updates
In your CBPeripheralDelegate method that receives characteristic updates, process each chunk:
Option 1: Use a Total Length Marker (Recommended)
If your Android code sends the total byte count of the image first (as a 4-byte Int32), use this approach:
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { guard let incomingData = characteristic.value else { return } // First chunk: extract total expected bytes (adjust based on your Android protocol) if expectedTotalBytes == nil { let lengthBytes = incomingData.prefix(4) expectedTotalBytes = lengthBytes.withUnsafeBytes { $0.load(as: Int32.self) } // Add remaining bytes of this chunk to accumulated data accumulatedImageData.append(incomingData.suffix(from: 4)) } else { // Add full chunk to accumulated data accumulatedImageData.append(incomingData) } // Check if we've received all bytes if let totalBytes = expectedTotalBytes, accumulatedImageData.count == totalBytes { convertDataToImage() // Reset for next transmission accumulatedImageData = Data() expectedTotalBytes = nil } }
Option 2: Use JPEG’s Natural End Marker
Since you’re compressing to JPEG on Android, the file ends with 0xFFD9. You can use this sequence to detect the final chunk:
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { guard let incomingData = characteristic.value else { return } let jpegEndMarker = Data([0xFF, 0xD9]) if incomingData.hasSuffix(jpegEndMarker) { // Add all bytes except the end marker accumulatedImageData.append(incomingData.dropLast(jpegEndMarker.count)) convertDataToImage() // Reset for next transmission accumulatedImageData = Data() } else { accumulatedImageData.append(incomingData) } }
3. Convert Accumulated Data to UIImage
Create a helper function to turn the collected bytes into an image:
private func convertDataToImage() { guard let image = UIImage(data: accumulatedImageData) else { print("Failed to create image—check if all chunks were received or if JPEG compression is valid") return } // Update UI on main thread (since BLE callbacks run in background) DispatchQueue.main.async { // Use your image here, e.g., self.imageView.image = image } }
Key Tips for Success
- MTU Size: Ensure your Android code splits the JPEG bytes into chunks that fit within your BLE connection’s MTU limit (default is 20 bytes, but can be increased).
- Validate JPEG on Android: Before sending, confirm the byte array from
baos.toByteArray()is a valid JPEG (write it to a file and check it opens correctly). - Error Handling: Add checks for missing chunks or corrupted data to avoid crashes.
内容的提问来源于stack exchange,提问作者phoebus

