You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

新手求助:Android BLE通知数据接收及存储应用开发示例

入门级实现方案:BLE数据接收+CSV/云端存储

以下是贴合你需求的核心实现示例,分三个模块展开:

一、BLE设备数据接收核心代码

1. 先配置权限(AndroidManifest.xml)

<!-- BLE基础权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- Android 12+ 新增权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<!-- 存储权限(用于CSV) -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />

2. 核心业务代码(Kotlin示例)

import android.bluetooth.*
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity

class BLEDataActivity : AppCompatActivity() {
    private val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter()
    private var gatt: BluetoothGatt? = null
    // 替换为你的BLE设备服务UUID和通知特征UUID(设备文档可查)
    private val SERVICE_UUID = "0000ffe0-0000-1000-8000-00805f9b34fb"
    private val CHARACTERISTIC_UUID = "0000ffe1-0000-1000-8000-00805f9b34fb"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // 启动扫描
        startBLEScan()
    }

    // 扫描目标BLE设备
    private fun startBLEScan() {
        val scanCallback = object : ScanCallback() {
            override fun onScanResult(callbackType: Int, result: ScanResult) {
                super.onScanResult(callbackType, result)
                // 匹配你的设备名称或MAC地址
                if (result.device.name == "YourBLEDeviceName") {
                    bluetoothAdapter?.bluetoothLeScanner?.stopScan(this)
                    connectToDevice(result.device)
                }
            }
        }
        bluetoothAdapter?.bluetoothLeScanner?.startScan(scanCallback)
    }

    // 连接设备并监听通知
    private fun connectToDevice(device: BluetoothDevice) {
        gatt = device.connectGatt(this, false, object : BluetoothGattCallback() {
            override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
                if (newState == BluetoothProfile.STATE_CONNECTED) {
                    gatt.discoverServices()
                }
            }

            override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
                val service = gatt.getService(UUID.fromString(SERVICE_UUID))
                val characteristic = service?.getCharacteristic(UUID.fromString(CHARACTERISTIC_UUID))
                // 开启通知
                gatt.setCharacteristicNotification(characteristic, true)
                val descriptor = characteristic?.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"))
                descriptor?.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
                gatt.writeDescriptor(descriptor)
            }

            override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
                // 收到设备通知数据,转成字符串
                val receivedData = String(characteristic.value)
                Log.d("BLE_DATA", "收到数据:$receivedData")
                // 调用存储和上传方法
                saveToCSV(receivedData)
                uploadToCloud(receivedData)
            }
        })
    }

    // 以下是CSV存储和云端上传方法,见下方模块
}

二、CSV文件存储实现

import android.os.Environment
import java.io.File
import java.io.FileWriter
import java.text.SimpleDateFormat
import java.util.*

private fun saveToCSV(data: String) {
    val csvFile = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), "ble_data.csv")
    // 首次创建时写入表头
    if (!csvFile.exists()) {
        FileWriter(csvFile).use { writer ->
            writer.append("时间,数据\n")
        }
    }
    // 写入带时间戳的新数据
    val currentTime = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(Date())
    FileWriter(csvFile, true).use { writer ->
        writer.append("$currentTime,$data\n")
    }
}

三、云端存储简单实现(HTTP POST示例)

1. 添加OkHttp依赖(build.gradle(:app))

dependencies {
    implementation 'com.squareup.okhttp3:okhttp:4.11.0'
}

2. 上传代码

import okhttp3.Call
import okhttp3.Callback
import okhttp3.FormBody
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.*

private val okHttpClient = OkHttpClient()

private fun uploadToCloud(data: String) {
    val requestBody = FormBody.Builder()
        .add("timestamp", SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(Date()))
        .add("ble_data", data)
        .build()

    val request = Request.Builder()
        .url("https://your-server-api.com/save-ble-data") // 替换为你的云端接口地址
        .post(requestBody)
        .build()

    // 异步上传,避免阻塞主线程
    okHttpClient.newCall(request).enqueue(object : Callback {
        override fun onFailure(call: Call, e: IOException) {
            Log.e("UPLOAD_ERROR", "上传失败:${e.message}")
        }

        override fun onResponse(call: Call, response: Response) {
            Log.d("UPLOAD_SUCCESS", "上传结果:${response.code}")
            response.close()
        }
    })
}

内容的提问来源于stack exchange,提问作者Anik Sengupta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 02:45:32