Here's a thing that happens to me about forty times a day and I've never once stopped to think about why. I type something, I want to change one word, and suddenly my hands are doing a little dance across a screen that doesn't want to help me.
That's the friction Daniel's been chewing on, and he's gone further down the rabbit hole than most people would.
Daniel wrote in this week. He's been rebuilding his Android voice-typing setup, and he's landed on a Parakeet backend that he says beats Futo's Whisper implementation cold. He runs a dedicated voice IME alongside a regular typing keyboard, which gives him the best results, but the transition between the two is clunky. If you're editing and dictating multiple times in one email, opening the keyboard selector every single time becomes a real imposition, not a minor annoyance.
And he's not wrong about that. I want to sit on that phrase for a second, "multiple times in one email," because I think people who don't dictate underestimate how often the mode-switching happens. You dictate a sentence, you notice the transcription got a name wrong, you switch to the typing keyboard to fix it, you switch back to keep dictating, you realize the next sentence needs a number formatted a specific way, you switch again. That's four switches in ninety seconds. It's not a two-or-three-tap problem in the abstract. It's a two-or-three-tap problem multiplied by the fact that you're already mid-thought, and every tap is a chance to lose the thread of what you were saying.
Right, and that's the part that's hard to convey to someone who just types. The cost isn't the taps. The cost is the interruption to the sentence you were composing in your head.
It's a context-switch tax, and it's levied at the worst possible moment.
He's figured out that if you enumerate the active IMEs on a device you can identify each one deterministically, and he suspects there's a simple command to switch between them. He thinks Tasker or MicroDroid could map a button or a press sequence to jump to the regular keyboard, another to jump to the voice keyboard, maybe even a toggle between the two. His sticking points: finding the correct Android intent, which he says isn't always obvious, and defining context so shortcuts don't fire in the wrong window state. And the bigger question underneath all of it, which is what we're actually here to talk about: how do developers discover which intents and deep links the OS actually offers, so they can build the right mappings in whatever automation platform they prefer?
So the short version is Daniel wants to know how to find a door in Android that doesn't exist, and what to do instead.
That's a bleak way to put it, but let's find out if you're right.
Start with the landscape, because it matters. Android treats keyboards and speech-to-text as two completely separate services. You can set a default IME and a default voice input provider independently of each other. But only one IME is active at any given moment. That's the architectural fact that creates Daniel's problem in the first place.
So the voice keyboard and the typing keyboard are never both live.
Never. One at a time. The system IME picker, that little globe or keyboard icon, is the default way to switch. Tap it, get a list, pick one. Two or three taps, depending on how many you have installed. Once is nothing. Ten times in a single email is a different story.
And I assume the picker itself isn't smart about ordering. It's not like it puts your two most-used keyboards at the top.
It does not. It's roughly alphabetical by display name, or by install order in some OEM builds. Which means if your voice keyboard is called something that starts with a Z, you're scrolling every time. It's a small thing, but it compounds the friction. The system has no concept of "the two keyboards this person actually uses."
And the performance claim. Is Daniel imagining the Parakeet advantage, or is it real?
It's real, and it's corroborated. NVIDIA's Parakeet, specifically the tdt-0.6b-v2 and v3 variants, has topped the Open ASR Leaderboard. It's faster and lighter than Whisper for English. A developer named Ayoub Abedrabbo forked the FUTO Voice Input app last June to use a Parakeet backend, and his own words were that it's much faster for English than the included Open Whisper implementation.
So Daniel isn't an outlier. He's early to something that's already spreading.
There's a dedicated Parakeet keyboard on Android, notune's android_transcribe_app. Someone verified via adb that it runs fully local and called it flawless. And there's active pressure on FUTO itself, multiple GitHub issues asking them to swap whisper.cpp for sherpa-onnx specifically so they can run Parakeet. The argument in those threads is that ONNX allows faster ASR, lower resource use, and more model choice.
What's Whisper's counterargument? There has to be one, or FUTO would have switched already.
Multilingual breadth. Whisper handles a huge range of languages. Parakeet's edge is strongest for English. FUTO only exposes languages with more than a thousand training hours, so their calculus is different from Daniel's. If you're an English speaker doing English dictation, Parakeet wins. If you need forty languages, you probably stay where you are.
Fair. So the performance fork is real, the trade-off is real, and Daniel has picked his side. Now the hard part.
Now the hard part. Each keyboard on Android is a separate input method. The InputMethodManager is the service that manages them. It gives you getEnabledInputMethodList for the ones the user has turned on, getInputMethodList for everything installed, and getCurrentInputMethodInfo, which was added at API level thirty-four, for whatever's active right now.
And each one has a stable identifier.
InputMethodInfo objects. The ID format is packageName slash className. So something like com dot example dot voiceime slash dot VoiceImeService. That's the deterministic key Daniel's talking about. It doesn't change between reboots, it doesn't depend on display order. If you've enumerated it once, you know exactly which one you're pointing at.
There's a caveat there, isn't there? Something about visibility.
Android eleven and up, API thirty and above. Those enumeration methods return filtered results by package visibility rules, with one exception: the currently connected IME is always visible. If you're building an automation helper that needs the full list, the app has to declare a queries element for android dot view dot inputmethod dot InputMethod, the SERVICE_INTERFACE. Otherwise you get a partial list and you don't know what's missing.
Which is exactly the kind of thing that makes an automation work on your phone and fail on someone else's.
Same Android version, same app, different results, because one device has the queries declaration and the other doesn't. It's a nasty one to debug because nothing errors. You just get fewer keyboards than you expected.
So Daniel can enumerate. He can identify each IME deterministically. Now he wants to send a simple command to switch. And this is where the wall is, isn't it.
This is where the wall is. The Android documentation is explicit. A client application can ask that the system let the user pick a new IME, but cannot programmatically switch to one itself. That's a direct quote. And then it adds: an IME, on the other hand, is allowed to programmatically switch the system to another IME, since it already has full control of user input.
So the permission is asymmetric. A keyboard can switch you to another keyboard. An ordinary app can't.
And the reason is stated right there in the docs. It avoids malicious applications from switching the user to their own IME. Think about what a keyboard sees. Every keystroke, every password, every message. If any app with a Play Store listing could flip your active keyboard to one it controls, you'd have a keylogger installed by lunchtime and no idea.
So the restriction isn't bureaucratic friction. It's load-bearing.
It's one of the better-designed security boundaries in the OS, honestly. And I say that as someone who complains about most things.
Which means Daniel's instinct to find an intent is right in spirit but wrong in mechanism. There is no public switch-to-IME-X intent. You can call showInputMethodPicker, and all that does is show the picker. It doesn't select anything.
There are intents that get you to settings. android dot settings dot INPUT_METHOD_SETTINGS opens the keyboard settings screen. Individual IMEs expose their own settings activities through manifest metadata. Those are useful for configuration. None of them switch the active keyboard.
So what actually does?
The active IME is stored in the Settings dot Secure table under the key default_input_method. Writing that value is what switches the keyboard. That's the real lever. It's not an Intent object at all. It's a secure settings mutation.
And writing to Settings dot Secure requires a permission normal apps don't get.
WRITE_SECURE_SETTINGS. Which you grant via ADB or root. There's no dialog for it, no runtime prompt. You either have it or you don't, and getting it means plugging into a computer or unlocking your bootloader.
So the simple command Daniel intuited. Does it exist?
It does, at the shell level. Adb shell ime set, followed by the IME ID. There's also ime list to enumerate and ime enable to turn one on. That's the canonical way to do this from a shell. And it's simple. The catch is that it's a shell command, which means it runs with privileges a normal app doesn't have.
So the path is: enumerate the IDs, then write the chosen one to default_input_method through something with elevated permissions. The intent Daniel's looking for is effectively a settings write wearing an intent's clothing.
That's the whole trick. Once you see it, the shape of every IME-switching macro on Android makes sense. Nobody found a secret intent. They found the settings key and a way to write to it.
Let's talk about the automation side, because that's where Daniel actually wants to live. He mentioned Tasker and MicroDroid.
Tasker is the standard answer, and the recipe is well documented. You build a Profile with an Application condition, so it fires when you're in a specific app. The Task calls AutoTools, or the SecureTask plugin, and the action is Secure Settings, then Input Method, and you pick the target keyboard from a list. SecureTask does the same thing through its System plus, Input Method action.
And if you don't want a plugin?
Tasker's Custom Setting action can read and write Global, Secure, and System settings directly. So you point it at default_input_method in the Secure table and write the IME ID yourself. It's less friendly, but it's the same mechanism with fewer moving parts.
Now the permission wall. This is where most people stop, right?
This is where most people stop. AutoTools and SecureTask can write to Settings dot Secure, but they still need WRITE_SECURE_SETTINGS granted. So you're back to ADB or root. There's no way around it. The plugin doesn't grant the permission, it just uses it once you've granted it.
So the honest summary is: this is a power-user workaround, it requires a computer at least once, and it's fragile across Android versions.
All three. The settings key has been stable for a long time, which is in its favor. But the permission model tightens with each release, and an OEM skin might handle IME defaults differently. It's not something you'd recommend to your aunt. It's something you'd do for yourself and then write a blog post about.
Daniel's not asking for his aunt. He's asking for people building automations. And for that audience, the enumeration side is clean. GetEnabledInputMethodList gives you the IDs, the IDs are stable, and the write is a single settings value.
The enumeration is the part I'd call well designed. It's the switching that's locked down, and it's locked down for a reason that makes sense. That's an unusual combination. Usually when something's hard, it's because nobody thought about it. Here, somebody thought about it very carefully and decided you shouldn't have it.
Which brings us to context. Daniel's worried about shortcuts firing in the wrong window state. What does Tasker actually give you there?
More than most people realize. The Application condition is the obvious one, but Profiles support a lot more. Orientation. Docked or undocked. Variable state, so you can gate on a flag your own tasks set. And UI state through AutoInput, which can detect what's actually on screen, not just which app is in the foreground.
That's the difference between "I'm in Gmail" and "I'm in Gmail with a compose window open and the cursor in the body field."
Exactly that. And it matters for Daniel's case, because the same app can have a dozen states. You don't want your voice-keyboard macro firing while you're scrolling the inbox. You want it firing when you're in a text field and you've decided to dictate.
So you could build a toggle. One button that flips between voice and typing, gated on being in a compose window.
You could build almost anything. That's the second-order implication of the settings-write approach. Once switching is just a value you can write, it becomes a building block. Map a volume key long-press. Map a gesture. Map a button on a Bluetooth remote. Have it fire automatically when you enter a specific app and revert when you leave. The OS gives you one primitive, and the automation layer turns it into whatever workflow you want.
And the fragility is proportional to how clever you get.
Always is. The simplest version, one app, one keyboard, one condition, will survive a lot. The version with six conditions and UI-state detection and a toggle variable will break the first time an app updates its layout. That's not an Android problem. That's an automation problem.
There's a broader thing happening here too, which is the community pressure on FUTO. If the keyboard itself could switch, or if the voice input were integrated the way FUTO Keyboard does it, Daniel's problem partly evaporates.
It does. FUTO Keyboard has voice input built in, so there's no switching at all. The standalone Voice Input app exists for people who want to use it with a different keyboard, and that's the configuration Daniel's running. The GitHub issues asking for sherpa-onnx are about performance, not switching, but the integrated approach is the cleaner answer to the friction.
There are two roads. Integrate the voice input into the keyboard so there's nothing to switch, or keep them separate and automate the switch.
They trade off differently. Integration is smoother but locks you into one keyboard's implementation and one model. Separation gives you model choice, which is exactly why Daniel's running Parakeet behind a separate IME. He traded friction for performance, and now he's trying to buy the friction back with automation.
That's the honest framing of the whole episode, isn't it. He made a deliberate trade and now he's optimizing the cost.
Every power user does this. You pick the thing that's better and then you spend a weekend sanding off the rough edges. Sometimes the sanding is worth it. Sometimes you've just built a second job for yourself.
The answer to "how do developers discover which intents the OS offers" is: read the documentation, and when the documentation says you can't, believe it. The interesting work is finding the mechanism that isn't an intent.
The docs are unusually honest here. They don't just say no, they say why. That's a gift. Most platform documentation leaves you guessing at the reasoning. This one tells you the threat model in two sentences.
Can I ask you something, though. You've been building automations for years. When you hit a wall like this, how long do you spend looking for the intent before you accept there isn't one?
Too long. Every time. Because the intent is the elegant answer. It's the answer that would make the whole thing a two-line task instead of a permission grant and a settings write. You want it to exist, so you keep looking.
I do the same thing with APIs. I'll spend an afternoon convinced there's a method I'm missing, and then I read the source and it's just not there. The acceptance is the hard part, not the finding.
There's a lesson in that for anyone building on Android. When the platform says a client app cannot do a thing, that's not a challenge, it's a boundary. The workaround exists, but it exists because you're stepping outside the client app model.
Hilbert: Can I ask you something about the switchboard thing.
Go ahead.
Hilbert: You keep saying the system won't let an app switch the keyboard. I used to work a switchboard, years back, for a regional phone company. That was the whole job. Somebody calls in, you take the cord, you plug it into the jack, the call connects. You pull it out, the call ends. That's it. That's what you did for eight hours.
The parallel you're drawing is that the OS is the switchboard operator.
Hilbert: The OS is the operator and it doesn't want to hand you the cords. There was a rule on that board. You never plug into a line you don't own. You'd get written up for it. Because if you plug into the wrong line you're not just dropping a call, you're on somebody else's conversation. That's your WRITE_SECURE_SETTINGS right there. You're asking for the keys to the switchboard. They're not going to hand those to every app that asks.
The permission isn't arbitrary. It's the same rule, restated for software.
Hilbert: It's the same rule. The reason it's a permission and not a setting is that somebody, at some point, plugged into the wrong line and it mattered. That's usually why these things exist.
Did the rule ever get broken? In practice.
Hilbert: Sure. People did it. You'd hear about it. Somebody would patch into a line they shouldn't and there'd be a meeting about it and a new sign on the wall. But the rule stayed, because the alternative was worse.
That's the thing about security boundaries. They're not there because nobody trusts you personally. They're there because somebody, somewhere, did the thing.
Hilbert: I still have the headset from that job. It's in a box somewhere. I don't know why I kept it. It's a headset. It doesn't work with anything anymore.
Do you miss it?
Hilbert: The job? No. But there was something to it. You'd make a connection and you'd feel it. The cord had weight. You knew when it seated. Now everything's a setting you write and you don't feel anything. Anyway. I've got a delivery coming that needs a signature and the window's nearly shut, so I need to go stand by the door.
The practical answer for Daniel, and for anyone building what he's building, is that the enumeration is clean and the switching is a settings write. The intent he's hunting for is the wrong shape of answer.
The shape of the right answer is less satisfying but more durable. Enumerate the IDs, gate the trigger on real context, write the value with a permission you granted once. That's the whole recipe.
The open question is whether Android ever changes this. Voice input is getting better and more common, and the friction of switching between voice and typing is going to get more pronounced, not less.
It might. There's a version of this where the OS grows a proper API for IME switching that's gated behind a user-visible consent, the way accessibility services are. That would give power users what they want without opening the keylogger door.
Or it stays a workaround forever, and the people who care enough keep granting permissions over ADB.
Which is a strange place for a feature to live. The people who need it most are the ones least likely to have a computer handy to grant the permission.
That's a microcosm of the whole tension, isn't it. Users want control over their input methods. The OS restricts that control for security reasons. The workaround exists, but it's not for everyone, and it's not supposed to be.
The restriction is right. The friction is real. Both things are true, and the gap between them is where the automation lives.
That's the episode. Thanks to Hilbert Flumingtop for producing, and for the switchboard history.
This has been My Weird Prompts.
If you enjoyed this one, leave us a review on your podcast platform of choice. It helps other listeners find the show.
We'll be back soon.