Stop the Fly App hanging forever on DJI registration

The DJI SDK can drop a registration attempt without ever calling
onRegister (it logged "Exception when executing encrypt/decrypt
functions" and nothing more), which left the app on "Registering…" with
no way out but a restart. The bridge now gives up after 60 s and reports
a failure that names the likely causes; a late answer from the SDK still
replaces it.

The failure was also only visible in the settings sheet, which the home
screen's Connect aircraft flow never opens, so failures now show a
snackbar too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
tajniak81andClaude Opus 5.5 committed 2026-10-21 17:39:39 +02:00
1 parent 636da1ac2c
commit 56d43ddb1e
2 files changed
+28

No files matched your search

@@ -49,6 +49,14 @@ class DjiSdkBridge(
*/
private const val IDENTITY_RETRY_MS = 2_000L
private const val IDENTITY_MAX_ATTEMPTS = 30
/**
* The SDK can swallow a registration failure without ever calling
* [DJISDKManager.SDKManagerCallback.onRegister] — e.g. it logs "Exception when
* executing encrypt/decrypt functions" when DJI's server rejects the App Key —
* leaving the app on "Registering…" forever. Give up after this long.
*/
private const val REGISTRATION_TIMEOUT_MS = 60_000L
}
private val mainHandler = Handler(Looper.getMainLooper())
@@ -57,6 +65,19 @@ class DjiSdkBridge(
private var eventSink: EventChannel.EventSink? = null
private val registrationTimeout = Runnable {
emit(
mapOf(
"type" to "registration",
"state" to "failed",
"error" to "DJI did not answer the registration within " +
"${REGISTRATION_TIMEOUT_MS / 1000} s. Check the internet connection, " +
"and that the DJI App Key is activated for package " +
"${appContext.packageName}.",
)
)
}
/**
* The *flight controller's* serial number — not the aircraft's.
*
@@ -181,12 +202,16 @@ class DjiSdkBridge(
private fun registerApp() {
emit(mapOf("type" to "registration", "state" to "registering"))
mainHandler.removeCallbacks(registrationTimeout)
mainHandler.postDelayed(registrationTimeout, REGISTRATION_TIMEOUT_MS)
DJISDKManager.getInstance().registerApp(
appContext,
object : DJISDKManager.SDKManagerCallback {
override fun onRegister(error: DJIError?) {
// A late answer still wins: it replaces a timed-out "failed".
mainHandler.removeCallbacks(registrationTimeout)
if (error == DJISDKError.REGISTRATION_SUCCESS) {
emit(mapOf("type" to "registration", "state" to "success"))
DJISDKManager.getInstance().startConnectionToProduct()
+3
View File
@@ -173,6 +173,9 @@ class _HomePageState extends State<HomePage> {
case 'failed':
_model.registration = RegistrationState.failed;
_model.registrationError = event['error'] as String?;
// The error otherwise only shows in the settings sheet, which the
// home "Connect aircraft" flow never opens.
_snack('Registration failed: ${_model.registrationError ?? 'unknown error'}');
break;
}
_model.bump();