Ramiz RajaBook a call
← Writing
The App-Rescue Playbook

Hiring an Android Developer? Read the Git Log Before the CV

Eight months of work arrived in one commit. Four checks that would have caught it, and the Play Console setup to do before any money moves.

Ramiz RajaNovember 3, 20267 min read
Hiring an Android Developer? Read the Git Log Before the CV

Before you hire an Android developer, or an Android app developer through an agency, look at what one commit can hide:

$ git show --shortstat <one commit>
 93 files changed, 3184 insertions(+), 809 deletions(-)

That commit held eight months of work on an Android app whose first Android code I had written years earlier. When I came back to lead it, the shared repository's last commit was eight months old, though the version number had moved on twenty builds. The rest lived on someone's machine until I asked for it and it arrived in one push.

Nobody was hiding anything. Nobody had checked. A portfolio, a Kotlin test and a good interview won't show you this, and it costs the most later. I'm one of the people you could hire, so read this as the list I'd want you to run on me:

  1. Their git history, and proof of when work reached a shared remote.
  2. Whether they can read your app's Google Play deadlines off the build file.
  3. How a build gets from a merge to your testers.
  4. Who owns the Play Console account and the upload key: you.

Why an Android hire goes wrong late, not early

A working demo shows someone can build screens. It doesn't show whether they keep the work somewhere you own, can maintain the app or can ship it without help. Those problems arrive on Google's schedule instead of yours.

Google Play raises its required target Android version every year, and each Play Billing Library version has a two-year deprecation cycle. Miss either and you can't ship an update until someone catches up. And when the developer leaves, you find out whether the code, history, upload key and Play Console account are yours or theirs.

A Kotlin-only exercise won't test any of that unless you design it to. Here's what to check.

Check 1: ask to see their git history, not just their code

The commit cost nothing on the day. What was gone was the sequence: which change fixed which bug, why a sending delay had been added, which of those 93 files moved together. For every line that commit introduced, git blame points at one commit dated my first day, and can't recover the individual changes made over those eight months.

The fix was a working rule, not a tool: work lives on a remote the business owns, pushed at least daily, with real commit messages.

So ask a candidate to screen-share the commit log of a current project. git log --since="3 months ago" --format="%ad %s" --date=short needs no source code on screen, so an NDA isn't a blocker. You're looking for small, coherent commits with messages that say why. A month of silence followed by "misc fixes" is the pattern that becomes your eight-month commit.

A log shows when commits were made, not when they were pushed. So also ask for pull requests, CI runs or the host's activity view, which record when work reached the remote.

For apps on their CV, the Play listing names the developer account, not the people. My own apps, like ResizePing, LeadPing and StatusPing, are listed under "PingApps Lab", not my name. Ask for the commit history, their role in that team's Play Console, or a reference.

Check 2: can they read your app's Google Play deadlines off the build file?

When I came back to a client app I first built in 2017, it was on Play Billing Library 7, with its deprecation deadline weeks away.

The version bump was small: four files, 14 lines added. But a commit years earlier, on the same day as a target API raise, had removed every test file, and none had come back in three and a half years. A billing change would ship with nothing guarding the code that takes payments.

So the tests came first: 29 unit test files before I touched billing. Then the upgrade surfaced the real cost. A reconnection option I'd enabled moved the billing setup and disconnect callbacks onto the library's own timing, and an old unlocked ArrayList of waiting callbacks could now throw ConcurrentModificationException. The fix and its test were bigger than the upgrade:

CommitFilesLines
Billing 7 to 9: version bump and API changes4+14 / −6
Callback drain under a lock, with a test2+199 / −29

The follow-up added about fourteen times as many lines as the bump, and was only safe because tests existed by then.

The full year-by-year record of that app is in what it costs to maintain an app.

The check: open your app's build.gradle (or .kts) with the candidate. A good Android developer finds targetSdk and the billing dependency in a minute, says what Google Play will require next, and asks whether there are tests before promising a date. The current requirement and the order I'd raise it in are in the target API level checklist.

Check 3: how does a build get from a merge to your testers?

On the message-automation app I lead now, QA used to get APKs hand-delivered over Slack. Every test build depended on one person remembering to build it.

I rebuilt the pipeline to deploy to Play internal testing, ending the hand-off. The app then shipped more than ten production releases in three months; the longer story is in an app that hasn't shipped in a year.

Here is the shape of that kind of pipeline, excerpted from my own LeadPing release workflow. Its automatic trigger is switched off for now, since I release LeadPing from my machine, and it runs when started by hand:

# Query the actual Play Store to find the highest version code across all
# tracks. This prevents "version code already used" errors caused by local
# release-bundle runs that uploaded to Play Store without committing.
- name: Find highest Play Store version code
  env:
    SERVICE_ACCOUNT_JSON: ${{ secrets.PLAY_SERVICE_ACCOUNT_JSON }}
  run: |
    pip install google-auth --quiet
    python3 scripts/check_play_version.py

# ... build the AAB, smoke-test the release APK on an emulator ...

- name: Deploy to Play Store internal testing
  uses: r0adkll/[email protected]
  with:
    serviceAccountJsonPlainText: ${{ secrets.PLAY_SERVICE_ACCOUNT_JSON }}
    track: internal
    # ... package name, release files, status, mapping file ...

The upload credential lives in the CI secret store, not the repo, and the pipeline guards against a failure caused by uploading by hand.

A good answer names the tools (GitHub Actions, Fastlane, Gradle Play Publisher), the track, and one time it broke. "I build it in Android Studio and send the APK" describes manual delivery. Ask someone else on the team to show they can produce and distribute the same signed build without that developer.

Check 4: who owns the Play Console account and the upload key

My Play Console login opens onto several developer accounts belonging to businesses I've built for. In each I'm an invited user. Removing me is one click, and nothing about their app, listing or revenue changes. Insist on that setup, for two Android reasons:

  • Play App Signing. With it on, Google holds the key that signs your app. Check that uploads use a separate upload key, which Google recommends but an older app may not have set up. With that split, a lost upload key is a reset request from the account owner, not the end of your app. The upload key and the Play service-account JSON belong in your CI secret store, under your account.
  • The testing rule for new personal accounts. Google's Play Console Help says developers with personal accounts created since late 2023 "must run a closed test for their app with a minimum of 12 testers who have been opted in continuously for at least 14 days" before they can apply for production access. A developer publishing from their fresh personal account saves you nothing: the app sits in their account and you still wait out the test. Open an organization account in your business's name and invite them.

If you hire a dedicated Android developer through an agency, the same holds: they join your accounts. The contract should assign code and IP to you and require work in your repository. More on who should hold what: what an app handover should leave you holding.

Interview questions for an Android developer, and the answers to listen for

  • "Show me the commit history of something you're working on." Small commits, reasons in the messages, PRs or CI runs.
  • "What does this app target, and what will Play require next?" Read off the Gradle file.
  • "Have you upgraded the Play Billing Library? What broke?" A specific API or callback problem.
  • "How did your last app's builds reach testers?" A named CI tool, a track, a failure they fixed.
  • "Where will the upload key live?" Your secret store, with Play App Signing on.

Ask Kotlin and Compose questions too. These five cover what costs you after they've gone.

Before you sign

Run the four checks on whoever you shortlist, me included. I do app rescue for Android apps stuck after a developer left or blocked by a Play deadline. For iOS, see how to hire an iOS developer.