Skip to content

Onboarding enables the Dictus keyboard but never selects it — users think it is active and the mic does nothing (v1.1.0) #111

Description

@Pivii

Note: this body was rewritten once the root cause was established. The original analysis was wrong and the thread below records how it was corrected — worth reading if you want the reasoning, not needed if you just want the fix.

Summary

Two users report that tapping the mic in the Dictus keyboard does nothing. One gave up on the app and went back to dictating in-app and copy-pasting by hand. One is on GrapheneOS and provided a log export.

Root cause: v1.1.0 onboarding enables the Dictus keyboard but never selects it, then tells the user setup is complete. On Android those are two different actions. The keyboard the users were tapping was never ours — ours was never activated.

Already fixed on develop by #41, which is not released.

The defect in v1.1.0

AppNavHost.kt, onboarding step 3 (OnboardingKeyboardSetupScreen):

LaunchedEffect(currentStep) {
    if (currentStep == 3) {
        val imm = context.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
        val isEnabled = imm.enabledInputMethodList.any { it.packageName == context.packageName }
        viewModel.setImeActivated(isEnabled)     // "activated" only ever means "enabled"
    }
}
...
3 -> OnboardingKeyboardSetupScreen(
    imeActivated = imeActivated,
    onOpenSettings = {
        context.startActivity(Intent(Settings.ACTION_INPUT_METHOD_SETTINGS))  // the enable list
    },
    onNext = { viewModel.advanceStep() },
)

It checks enabledInputMethodList and nothing else. It never reads DEFAULT_INPUT_METHOD. showInputMethodPicker() does not appear anywhere in the app module on v1.1.0 — the only call site is inside DictusImeService itself (:304), unreachable unless the Dictus keyboard is already active.

Every line of the user's log matches

Observation Explanation
enabled=true, selected=false on all 8 launches over 8 days he ticked the checkbox; nothing ever selected Dictus
no DictusImeService created, ever the IME was never the active input method, so the system never created the service
no handleMicTap called, ever — on v1.1.0 that line is logged unconditionally on entry no tap ever reached our IME
two successful recordings on 2026-08-21 at 11:23 onboarding step 6's in-app test recording — the app path works fine
raw transcript text in the log pre-#40 build, consistent with v1.1.0
log starts 2026-08-21, no gaps v1.1.0 has no purge in TimberSetup; complete history since install

Still broken on develop

#41 fixes the activation gap. These do not, and are what will make the next field report just as hard to diagnose:

  1. A failed mic tap produces no UI and no log. gatedMicTap (ime/.../DictusImeService.kt:640) returns silently when RECORD_AUDIO is missing (log only, and an InputMethodService cannot request runtime permissions), and runGateCommand does dictationController?.startRecording() — a null controller is swallowed with no trace. grep over the whole ime/ module returns zero Toast and zero error surface.

    Verified on an emulator: a successful keyboard mic tap writes two lines, both from DictationService, and none from the IME. A broken keyboard and an unused keyboard produce identical logs.

  2. selected cannot be trusted. Settings.Secure.getString(DEFAULT_INPUT_METHOD) returning null is fed to isImeComponentForPackage and yields false, indistinguishable from "another IME is selected", with nothing logged either way (MainActivity.kt:220-228). The SecurityException branch is handled; a silent null is not.

  3. Logging gaps that made this take an emulator control run to settle: Debug log export is too thin to diagnose field reports: null tags, no device context, silent mic-tap path #112.

Actions

  1. Cut a release from develop — 46 commits ahead of v1.1.0, including fix(onboarding): require selecting Dictus IME #41. Every user still on v1.1.0 is in this state.
  2. Surface mic-tap failures in the keyboard UI (item 1 above).
  3. Debug log export is too thin to diagnose field reports: null tags, no device context, silent mic-tap path #112 — make the keyboard log its mic path.
  4. Distinguish "cannot read DEFAULT_INPUT_METHOD" from "not selected".

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions