DEV Community

Cover image for Every Endoscope App Is a Subscription Trap, So I Built My Own With an AI Agent
Evgeniy Uryadov
Evgeniy Uryadov

Posted on Originally published at automata.sale

Every Endoscope App Is a Subscription Trap, So I Built My Own With an AI Agent

USB endoscopes are wonderful hardware: a camera on a flexible probe for the price of a sandwich. The software situation around them is a scandal. Every app I tried on the stores was an ad network with a subscription attached: ads every ten seconds, a 30-second recording cap, a watermark, a paywall to save your own photos.
So I did what I do for a living: wrote a one-paragraph spec, sat an AI coding agent next to me, and built the app the stores refuse to sell honestly.

What the agent shipped in one evening

EndoscopeCam: plain Java, 1.5 MB, no frameworks, no ads, no analytics. It doesn't even hold the INTERNET permission, so it physically cannot send anything anywhere.

  • full-screen live preview from any UVC-compliant USB camera;
  • photos to Pictures/Endoscope, MP4 video (H.264, MediaCodec + MediaMuxer) to Movies/Endoscope, no time limits;
  • resolution picker fed by the camera's own descriptors, with automatic YUYV/MJPEG selection (the reason cheap endoscopes work at all);
  • auto-launch when the probe is plugged in. The USB plumbing uses the maintained org.uvccamera library (Apache 2.0, prebuilt natives on Maven Central), which saved us from writing any JNI. ## The part that took a week: a 23-millisecond silence The first build died quietly on my Xiaomi (HyperOS 3, Android 16). The app ran, the camera was detected, and the permission dialog never showed up. No crash, no error, just a toast about denied access. The chase went through every red herring MIUI offers: pop-up window permissions, "display over other apps", cold reboots. What finally cracked it was counting milliseconds in the app's own logs:
15:42:52.858 requestPermission: sent, waiting for system dialog
15:42:52.866 permission broadcast: granted=false dtMs=23
Enter fullscreen mode Exit fullscreen mode

Twenty-three milliseconds is not a human rejecting a dialog. That is code answering before any UI could possibly appear. Reading the AOSP source settled it:

If the app doesn't have camera permission do not request permission to the USB device.
Since Android 13, UsbUserPermissionManager treats any USB device with hasVideoCapture() == true as a camera. If the calling app does not hold the CAMERA runtime permission, requestPermission() answers denied immediately and silently. No dialog is ever shown.
One line in the manifest (<uses-permission android:name="android.permission.CAMERA"/>) plus one runtime request, and the same code that failed for a week worked on the first try.
The method that cracked it, for anyone debugging a silent Android denial:

  1. log every step of your own flow with timings (adb logcat -s YourTag);
  2. an instant denial broadcast is a framework decision, not a user action;
  3. pull the system's own jar and grep the dex strings (unzip services.jar, count class references) to see which code path exists on the device;
  4. read the AOSP source for the exact component before trusting any forum advice. ## Try it The APK's free on my site, and a Play Store release is coming. Works on Android 7.0+ with any UVC endoscope over OTG. --- This article was prepared with AI assistance (drafting and adaptation) and reviewed by the author before publishing. Originally published at https://automata.sale/en/blog/ai-automation/endoscope-app-built-with-ai/ tags: android, aiagents, java, debugging

Top comments (0)