VModal Android SDK: Visual Search for Video Libraries in Kotlin
Video Search SDK for Android Kotlin. Integrate in any video app
At a glance
- What is it?
- A Kotlin client that adds image-semantic video search and streaming uploads to an Android app, with a UI-free API and a full Compose demo to copy from. The useful part is the coupled upload, index and search flow; the awkward part is that your API key lives in the app process.
- Who is it for?
- Adopt it if you are building an Android video library where users search by visual meaning and you already own authentication, storage and lifecycle handling, because the SDK deliberately imposes none of those. Skip it if you need an iOS or web client from the same codebase, or if you cannot accept a runtime API key inside the app process.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly Kotlin, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 18, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What VModal adds to an Android video app
The README frames the SDK as a "Visual Memory for video and images". Concretely, it lets a user describe a moment in words or supply an image and get back matching moments from a video collection, instead of scrubbing a timeline. The example in the README is a query like "Find the red car entering the parking lot".
The audience is narrow and clearly stated: Android developers working in Kotlin, Compose or Views, who already have a video library and want search inside their own app. The SDK is UI-free by design. The README says "Your app owns the screens and lifecycle", and the client handles the gateway, request models, response parsing, signed upload streams, progress and cancellation. There is no login screen, no design system, and no imposed navigation.
That split matters for evaluation. This is not a turnkey video app. It is the network and parsing layer for one feature, and the demo application exists to show how to wire that feature into screens you write yourself.
How the client, upload flow and search contracts fit together
The architecture visible in the README is a thin typed client over a remote gateway. Your code configures the client with runtime credentials, calls methods on a coroutine facade, and collects state in caller-owned scopes. The README is explicit that the SDK does not hard-code a main dispatcher inside its calls, which means the threading decision stays with the ViewModel or whatever owns the scope.
Uploads are the part with the most design detail. The SDK accepts Android content:// URIs, so a video chosen through the system photo picker streams directly rather than being copied to a device path first. The README describes a cold upload Flow plus a callback UploadHandle for compatibility, which suggests two consumption styles over the same operation. Progress and cancellation are part of the contract, and a CoroutineWorker option is mentioned for work that should outlive a single screen.
Search is a chain rather than a single call. The README lists collection listing, image index creation and checking, search against a selected collection, and then one bulk request to resolve result images. The prompt in the README adds a constraint that is easy to miss: "Keep collection, stream, index-job, search-hit, and resolved-image contracts explicitly coupled so data from one scope cannot appear under another." That is a warning about state hygiene. If you keep a single flat result list across collections, you can render hits from a collection the user is no longer viewing.
One more detail worth respecting: the README says not to attach the VModal bearer token when loading presigned image URLs. Presigned URLs carry their own authorization, and adding the token to those requests is the kind of mistake that leaks credentials into logs.
Installing the SDK and running the full-app example
The repository ships an install script and a checked-in Gradle wrapper, and the README tells you to use that wrapper rather than generating a new one. Clone the repository first, then run the install and check steps from the SDK directory.
git clone https://github.com/v-modal/vmodal_sdk_android
cd vmodal_sdk_android
cd uinterface/sdk_android
bash install.sh install
bash install.sh checkThe check step is the one to watch. If the toolchain is wrong, it fails here rather than halfway through a Gradle sync. The README pins the environment: Android SDK 34, JDK 17, and ANDROID_HOME or ANDROID_SDK_ROOT set when you build from the command line.
The demo to copy from is examples/03_fullapp. It is a Compose application that configures the client with a key supplied at runtime, calls auth.me(), lists collections, uploads a selected content:// URI or a bundled sample with progress and cancellation, creates and checks an image index, runs a search, resolves result images in one bulk request, and shows them in a responsive grid. Build and install it with the wrapper:
cd examples/03_fullapp
./gradlew --no-daemon :app:testDebugUnitTest :app:assembleDebug
adb devices
./gradlew --no-daemon :app:installDebugExpect a normal Android install and a launch screen asking for credentials. The README requires an unlocked Android 7.0 / API 24 or newer emulator or device; the minimum SDK in the prompt is 24. With a device attached you can also run ./gradlew --no-daemon :app:connectedDebugAndroidTest.
On credentials, the README is unambiguous. Supply the VModal API key only at runtime, and never put it in source, resources, Gradle properties, local.properties, logs, or the manifest. The SDK expects to be handed a key by the host app, not to read one from a file.
The API key stays in the app process
This is the limitation to think about before anything else. The README's own instructions say credentials are kept in memory only and supplied at runtime, and that they must never be committed or printed. That is good hygiene for a demo, but it does not answer the production question: an Android APK is distributed to users, and anything the app can hold, a determined user can extract.
There is no mention of a server-side token exchange, a proxy, or short-lived scoped credentials issued by your own backend. If your threat model includes users abusing a VModal key at your expense, the SDK as documented does not solve that for you, and the README does not claim it does. The honest reading is that this client is built for apps where the key is either low-risk or already mediated by infrastructure you control outside the SDK.
A second constraint is scope. This is an Android Kotlin SDK. If you also ship iOS or web, you are integrating a second client for the same feature, and the README gives no indication of a shared abstraction across platforms. The same applies to the bulk image resolution step: it is one request for many URLs, which is efficient, but it means your result rendering waits on a batch rather than resolving lazily per item.
VModal against a general-purpose media backend
The obvious comparison is a media platform such as Mux or Cloudinary, which also handle upload and playback but approach the problem from asset delivery rather than semantic retrieval. With those, you upload an asset, get a playback ID or a transformed URL, and search is something you build on top of metadata you attach yourself. VModal starts from the opposite end: the searchable index is the product, and the README's whole flow is oriented around creating an image index and querying it by meaning.
That difference shows up in the API shape. A media backend gives you an asset lifecycle and expects you to store your own metadata and query it in your own database. VModal gives you collections, index jobs and search hits, and expects you to keep those contracts coupled. If your feature is "play this video reliably at scale", the media backend is the closer fit. If your feature is "find the moment where this happens", VModal is doing work you would otherwise have to build with an embedding pipeline and a vector store.
Self-hosting is the third position. Running your own visual search stack keeps data inside your perimeter and removes the key-in-the-app problem, at the cost of operating inference and indexing infrastructure. The README does not describe a self-hosted deployment, so that path means leaving this SDK behind.
Maintenance, licence and upgrade cost
The repository is not archived, and the last push was on 2026-09-13, days before this writing. There are no releases retrieved, so versioning appears to happen on the main branch rather than through tagged artifacts. That has a practical consequence: you cannot pin to a release number, and the README's install path is a git clone plus a shell script, not a published Maven coordinate. The prompt does mention preserving an "optional Maven Local verification path", which suggests local publication is possible, but the README does not document a public artifact repository.
Upgrade cost therefore tracks the branch. When you pull, you re-run bash install.sh check and bash test.sh test in uinterface/sdk_android, then rebuild the example, and you should expect the typed request and response contracts to be the main source of breakage. The README's insistence on keeping collection, stream, index-job, search-hit and resolved-image contracts coupled means those types are load-bearing in your UI code.
On licensing, the repository is Apache-2.0, which permits commercial use and modification and requires you to preserve notices and state changes. The README does not discuss attribution requirements for the VModal service itself, and the licence covers the SDK code, not the hosted API. Terms for the service are a separate question the README does not answer, so read them before shipping. None of this is legal advice.
Editorial conclusion
Adopt it if you are building an Android video library where users search by visual meaning and you already own authentication, storage and lifecycle handling, because the SDK deliberately imposes none of those. Skip it if you need an iOS or web client from the same codebase, or if you cannot accept a runtime API key inside the app process. Before writing product code, clone the repository, run bash install.sh check and bash test.sh test from uinterface/sdk_android, then open examples/03_fullapp and confirm that upload, index, search and bulk image resolution behave against a real key on an API 24+ device.
Frequently asked questions
What is the purpose of the VModal Android SDK?
It gives an Android app semantic video and image search plus mobile-friendly uploads, exposed as a small typed Kotlin API. The README describes it as a "Visual Memory for video and images", and the host app keeps ownership of screens, lifecycle and authentication.
How do I use the VModal Android SDK in my app?
Clone the repository, run bash install.sh install and bash install.sh check from uinterface/sdk_android, then follow examples/03_fullapp, which configures the client with a runtime API key, lists collections, uploads a content:// URI, creates an image index, searches and resolves result images in one bulk request.
Where should the VModal API key be stored in an Android app?
The README says to supply it only at runtime and keep it in memory, never in source, resources, Gradle properties, local.properties, logs or the manifest. It also says not to attach the bearer token when loading presigned image URLs.
Which Android versions and toolchain does the VModal SDK require?
The README specifies Android SDK 34, JDK 17, Gradle 8.6 and Kotlin 1.9 or newer, with a minimum of Android 7.0 / API 24 on an unlocked emulator or device. It also asks you to use the checked-in Gradle wrapper.
Community notes