Flir One Edge Pro 无法连接个人 Android 应用
结论
Operation Canceled (code=125) 是 SDK 在异步连接流程被取消后返回的通用错误,无法直接据此判断“相机无法访问”。随后出现的 ErrorCode{code=5, message='Camera is not connected'} 是连接失败后的结果,并非最初的错误原因。
从目前的现象看,问题很可能出在 BLE 发现完成之后,具体可能涉及 Android 的 Wi-Fi 切换、网络选择或路由绑定。Pixel 7 运行 Android 16,需要查阅对应 SDK 版本的兼容性说明,确认当前 Flir Mobile SDK 是否完整支持该系统。官方 FLIR ONE app 可以连接,也无法说明公开版 Mobile SDK 采用了相同的版本和连接实现。
建议先用同一个 APK 在受支持的较低 Android 版本上复测。如果 Android 14 或 Android 15 可以连接,而 Android 16 每次都失败,就应从 SDK 与 Android 16 的兼容性入手:升级 Flir Mobile SDK,或向 Teledyne FLIR 索取支持 Android 16 的 SDK 版本。
为什么 BLE 能发现,相机却仍然连不上
DiscoveryFactory.scan() 和 camera.connect() 分属不同的连接阶段。
扫描阶段主要通过 BLE 获取相机的 Identity、SSID、IP 地址和固件信息。执行 camera.connect() 后,还要完成以下操作:
- 通过 BLE 与相机协商连接。
- 请求 Android 加入相机创建的本地 Wi-Fi。
- 等待 Android 返回可用的
Network。 - 将 SDK 的通信流量路由到该网络。
- 建立 SDK 使用的相机协议连接。
拿到完整的 Identity,只能确认 BLE discovery 正常。后续的 Wi-Fi 切换、网络绑定和相机协议连接仍有可能失败。
手动加入 FLIRONE_xxxxx 后,可以通过浏览器访问 192.168.87.1,说明本地 Wi-Fi 和 HTTP 路由可达,但 SDK 所需的端口、网络绑定和握手流程未必已经完成。
先确认是否为 Android 16 兼容性问题
可以通过控制变量复测:
- 使用同一个 APK、同一台相机和同一版本固件。
- 在 Android 14 或 Android 15 设备上执行相同的连接流程。
- 暂时不要修改连接代码,以免引入其他变量。
如果较低版本可以连接,而 Android 16 仍在约 10 秒后返回 code=125,问题范围基本可以缩小到 Android 16 的 Wi-Fi 接入或路由机制与当前 SDK 不兼容。继续增加权限通常解决不了这类问题,此时应确认:
- 当前 Flir Mobile SDK 的准确版本。
- 该版本声明支持的 Android API 范围。
- 是否有更新的 SDK 可用。
- FLIR 是否提供 Android 16 兼容补丁或更新后的示例工程。
联系 FLIR 支持时,至少应提供 SDK 版本、Android build number、完整 Atlas 日志、相机固件版本和最小复现工程。仅提供 code=125 不够,因为这个错误码无法说明连接在哪一步被取消。
排除应用自身取消连接
连接操作应串行执行。重复扫描、重复调用 connect()、页面销毁或主动执行 disconnect(),都可能触发相同的取消错误。
下面的 Kotlin 示例提供了基本的状态保护。回调方法名称需要根据实际使用的 SDK 版本调整:
private val camera = Camera()
private var connecting = false
private var connected = false
fun connectCamera(identity: Identity) {
if (connecting || connected) {
return
}
connecting = true
camera.connect(
identity,
connectionStatusListener,
ConnectParameters()
)
}
private val connectionStatusListener = object : ConnectionStatusListener {
override fun onConnectionStatusChanged(
status: ConnectionStatus,
errorCode: ErrorCode?
) {
when (status) {
ConnectionStatus.CONNECTED -> {
connecting = false
connected = true
}
ConnectionStatus.DISCONNECTED -> {
connecting = false
connected = false
Log.e("FLIR", "Disconnected: $errorCode")
}
else -> {
Log.d("FLIR", "Connection status: $status, error: $errorCode")
}
}
}
}
同时检查以下问题:
- 不要只在局部变量中保存
Camera、Identity和 listener。 - 不要在
Activity.onStop()或Fragment.onDestroyView()中无条件断开正在建立的连接。 - coroutine、RxJava subscription 或其他异步任务被取消时,不要连带调用
disconnect()。 - 发现目标相机后应停止重复扫描,但不要调用会释放整个 SDK 或无线接口的清理方法。
- 每次只连接一个
Identity。 - 避免因 Compose 重组或重复点击按钮而多次执行
camera.connect()。
不同 SDK 版本的 listener 接口和枚举值可能不同,应以当前版本的 API 为准。
检查 Android 是否保留了相机 Wi-Fi
FLIR 相机提供的 Wi-Fi 通常无法访问互联网。Android 可能将该网络判定为“无互联网”,随后继续使用移动网络,或者自动断开相机网络。
测试时可以暂时这样操作:
- 关闭 VPN。
- 关闭会自动切换网络的自适应连接功能。
- 开启飞行模式,然后单独打开 Bluetooth 和 Wi-Fi。
- 连接时留意系统是否出现“此网络无法访问互联网”之类的确认提示。
- 选择继续使用
FLIRONE_xxxxx,不要让系统切回其他已保存的 Wi-Fi。 - 删除旧的
FLIRONE_xxxxx网络记录,然后重新连接。
这些操作主要用于定位问题,未必适合作为正式应用的长期方案。如果关闭移动网络后才能连接,故障更可能出在网络选择或路由绑定阶段,而非 BLE discovery。
手动连接后的路由诊断
手动加入相机 Wi-Fi 后,可以检查 Android 是否创建了位于 192.168.87.0/24 网段的 Wi-Fi Network:
fun findFlirNetwork(context: Context): Network? {
val cm = context.getSystemService(ConnectivityManager::class.java)
return cm.allNetworks.firstOrNull { network ->
val capabilities = cm.getNetworkCapabilities(network)
val linkProperties = cm.getLinkProperties(network)
capabilities?.hasTransport(
NetworkCapabilities.TRANSPORT_WIFI
) == true &&
linkProperties?.linkAddresses?.any { linkAddress ->
linkAddress.address.hostAddress
?.startsWith("192.168.87.") == true
} == true
}
}
如果已经找到该 Network,但 SDK 仍通过默认移动网络发送流量,可以临时将进程绑定到该网络进行诊断:
val connectivityManager =
getSystemService(ConnectivityManager::class.java)
val flirNetwork = findFlirNetwork(this)
if (flirNetwork != null) {
connectivityManager.bindProcessToNetwork(flirNetwork)
}
断开相机后,应恢复默认路由:
connectivityManager.bindProcessToNetwork(null)
这种做法只适合诊断或临时规避。Flir Mobile SDK 可能会自行管理 Network,进程级绑定也会影响应用内的其他网络请求。没有 FLIR 文档确认时,不要将其作为正式的连接方案。
权限配置仍需核对
即使已经授予运行时权限,也要确认这些权限已在 manifest 中声明,并且与应用的 targetSdkVersion 匹配:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
如果权限已经授予,BLE discovery 也能正常完成,权限缺失通常不是首要排查方向。不过,第三方 SDK 仍可能检查位置权限或系统位置服务状态,因此测试时也应打开系统 Location。
在 Application.onCreate() 中执行 ThermalSdkAndroid.init(this) 是合理的,但 discovery 成功不足以证明连接模块已正确初始化。还要确认应用没有重复初始化,并查看初始化过程中是否出现异常日志。
收集真正的失败位置
连接时可以同时抓取 SDK、Wi-Fi 和 Android 网络服务日志:
adb logcat -v threadtime | grep -iE 'flir|atlas|wifi|connectivityservice|networkmonitor|bluetooth'
连接失败后,再保存以下状态:
adb shell dumpsys connectivity
adb shell dumpsys wifi
重点检查:
- Android 是否收到加入
FLIRONE_xxxxx的请求。 - Wi-Fi 是否已完成关联并取得
192.168.87.x地址。 - 系统是否因该网络无法访问互联网而将其撤销。
- SDK 是否在 Wi-Fi 可用前主动结束连接。
- 应用生命周期内是否调用了
disconnect(),或发生了任务取消。 - 相机网络是否存在,而默认路由仍指向移动网络。
如果日志显示 Android 从未尝试加入相机 Wi-Fi,问题更可能出在 SDK 的 Wi-Fi transition 实现。如果设备已经加入网络并取得地址,之后连接才被取消,就需要继续检查网络绑定和 SDK 协议握手。
缺少完整 Atlas 日志、准确的 SDK 版本和官方兼容性说明时,仅凭 code=125 无法确定唯一原因。根据现有信息,Android 16 与当前 Flir Mobile SDK 的无线连接流程不兼容最符合这些现象。使用较低 Android 版本进行对照测试,可以最快确认这一判断。
备注:内容仅供参考。
