Android developer verification and what it means for application distribution

- Posted in Android by

Android’s developer verification system continues its rollout across the ecosystem. What started as a security proposal is now becoming a platform-level requirement that affects how applications are distributed on Android, including outside Google Play.

From F-Droid's perspective 1, 2, 3, this feels like a shift in how Android handles software distribution. It is moving towards a model where publishing software depends on centralised identity verification.


System-wide verification becoming platform enforcement

Developer verification is no longer limited to store accounts.

It is being applied at the platform level across certified Android devices, including applications installed outside Google Play.

That means installation is no longer just a matter of user choice or distribution method. It increasingly depends on whether the developer has been verified within a central system. Link

Even where sideloading still exists technically, distribution is more closely tied to identity approval than it used to be.


Independent distribution under pressure

Android has long supported different ways of installing apps, including third-party app stores and direct APK installation.

A lot of projects exist because that model allows software to be shared without central approval. Link

Developer verification changes part of that assumption.

If installing apps on certified devices depends on a verified developer identity, then alternative distribution stops being fully independent in practice. It becomes tied back to the same upstream system.

There is also a related point raised in F-Droid’s recent writing on trust: that trust in software systems does not come from blindly trusting organisations, but from transparent mechanisms such as open source code, reproducible builds, and verifiable infrastructure. That framing feels relevant here, because the more distribution depends on central identity verification, the more the balance shifts away from verifiable processes and towards institutional trust.


Structured developer tiers

There are also now different categories of developer accounts, including limited or hobbyist options.

These accounts come with restrictions on how widely apps can be distributed and how many devices they can reach.

It creates a clearer separation between types of developers:

  • fully verified developers with standard access
  • restricted accounts with limited distribution
  • unverified developers with reduced reach on certified devices

Google’s documentation describes these limited accounts as intended for students, hobbyists, and learners, with caps on distribution and reduced requirements.


Regulatory context: DMA and European institutions

The EU Digital Markets Act requires large platforms to allow effective third-party distribution and to avoid restrictions that undermine alternative app ecosystems.

The European Parliament has also asked formal questions about whether developer verification is compatible with these rules and whether it could affect sideloading or alternative distribution channels.

The European Commission has said it is monitoring how Android’s distribution model fits within these obligations, including sideloading and third-party app stores.

At the moment, there is no final regulatory decision specifically on developer verification. It is still being reviewed.


Privacy and structural considerations

Developer verification introduces a permanent link between software publishing and real-world identity.

That changes something that has been fairly central to open ecosystems: the ability to publish software without needing a central identity check.

Some of the structural effects seem fairly clear:

  • more centralised developer identity records
  • less room for pseudonymous publishing
  • stronger links between software and verified identities or organisations
  • increased visibility of distribution activity at platform level

What still remains technically true

Android still allows installation from outside app stores.

But technical ability is not the only thing that matters anymore when it comes to distribution.

Whether software can be installed is increasingly shaped by whether the developer is verified, rather than whether a user chooses to install it directly. Link


Implications for users

For most people, the changes are not immediately obvious. Apps still install through existing methods depending on device settings and region.

Over time though, it may become more noticeable:

  • more friction when installing apps from independent sources
  • some apps may not install if the developer is not verified
  • fewer small or independent apps available on certified devices
  • a clearer split between verified and unverified software

Official rollout structure

Stage Period Source
Early access begins November 2025 Google Android Developer documentation
Verification opens to all developers March 2026 Google Developer Console documentation
System service rollout begins (device-level verifier installed for later enforcement) June 2026 https://android-developers.googleblog.com/2026/06/android-developer-verification.html
Android system verifier service (com.google.android.verifier) introduced across certified devices June 2026 https://support.google.com/android/answer/17065026
Update confirming rollout progress and continued enforcement preparation June 18 2026 https://android-developers.googleblog.com/2026/06/android-developer-verification.html
Android Developer ID Status API and Developer Console API early access begins July 2026 https://developer.android.com/developer-verification
Limited distribution accounts introduced (students, hobbyists, learners, up to 20 devices) July 2026
Limited distribution accounts and Developer Console API launch globally August 2026
Advanced flow for installing apps from unverified developers introduced with security checkpoints August 2026
App registration required for participating stores in Brazil, Indonesia, Singapore and Thailand 30 September 2026
Enforcement phase begins in selected countries (Brazil, Indonesia, Singapore and Thailand) September 2026
Global expansion of verification requirement 2027 onwards

Android, Trust Layers, and What Installing an App Feels Like Now

- Posted in Android by

I’ve been working around Android long enough to remember when installing an APK from outside the Play Store didn’t feel like a “process.” It was just something you did.

You downloaded a file, enabled “unknown sources,” tapped install, and that was it. No real ceremony around it.

That simplicity is still technically there, but over time it has started to feel… layered. Not blocked, not removed, just surrounded by more steps that you notice more when you’re outside the default ecosystem.

And the strange part is that none of these changes arrived all at once. They accumulated quietly.

I still catch myself using the word sideloading, even though that wasn’t really what we called it in the early Android days. Back then it was just “installing from unknown sources,” which felt like a permission toggle rather than a category of activity.

The term sideloading itself came from broader computing and enterprise contexts and only later became the dominant way people describe installing apps outside official channels. Within Android discussions, it gradually replaced earlier terms like “unknown sources” or “non-Market installation.”

That shift in language is small, but it matches how the experience itself has changed.

The first thing I really noticed over time wasn’t that APK installation disappeared, it didn’t, but that the system started inserting more checkpoints around it.

Instead of a single switch, there are now per-app permissions. Instead of quiet installs, there are more warnings. Background installs are more restricted. Play Protect scans things more actively in the background.

On top of that, there are simply more hurdles in general now, more verification prompts, more “are you sure” flows, more conditions before an app is allowed to behave normally.

Individually, none of this is dramatic. But together, it changes the feeling of installing something outside the Play Store. It’s still possible, but it’s no longer frictionless.

And this is where an important point often gets missed in discussions about Android’s openness.

Sideloading still exists, yes. APKs still install. Developer options still allow it. Nothing has been fully removed.

But the practical experience has shifted from “a simple action” to “a managed process.”

You are no longer just installing an app. You are moving through a sequence of system decisions:

permissions, warnings, scans, identity checks, and background restrictions.

So even though the feature still exists, the friction profile around it has completely changed.

And that friction matters more than people sometimes admit.

One of the more subtle framing issues in this space is how Google often describes these users.

They tend to refer to them as “power users”.

The problem is that this label does not really match reality.

Most people installing APKs, using F-Droid, or avoiding the Play Store are not developers or technically advanced users. They are just regular end users who want different software choices, fewer adverts, more privacy, or more control over their devices.

Calling them “power users” creates the impression that they are a niche group doing something complex or exceptional. In practice, they are not. They are simply users whose needs fall outside the default ecosystem.

So the label is slightly misleading. Not because the users are doing anything advanced, but because the system has gradually made even basic alternative choices feel advanced.

Then there’s ecosystem-level friction where ad-heavy apps, tracking-heavy SDKs, and integrity-driven SDKs collectively shape what kind of apps feel usable without trade-offs like ads, tracking, or reduced functionality behind blockers.

On top of that, there are simply more verification prompts, more “are you sure” flows, more conditions before an app is allowed to behave normally.

This also extends into ecosystem-level friction where ad-heavy apps, tracking-heavy SDKs, and integrity-driven SDKs collectively shape what kind of apps feel usable without trade-offs like ads, tracking, or reduced functionality behind blockers.

And that friction matters more than people sometimes admit.

Then there’s developer verification, which feels like a different kind of shift altogether.

On paper, it’s straightforward. Developers distributing apps outside official channels may need to verify their identity. The reasoning is usually tied to reducing impersonation and making it harder for malicious apps to keep resurfacing.

I understand the logic behind it. From a platform perspective, it is a clean solution to a real problem.

But from the outside, especially if you’ve been part of smaller projects or open-source work, it changes what “publishing an app” feels like. It is no longer just building and sharing software. It becomes tied to identity in a way that wasn’t always part of the original model.

Even if nothing is blocked outright, the expectation shifts.

What surprised me more is how much of Android’s trust model now sits outside the app itself.

Play Integrity is a good example of this shift.

I’ve seen apps that don’t just check whether they are installed correctly, they evaluate the environment they are running in. If the device is rooted, running a custom ROM, or failing integrity checks, the app may refuse to run or may restrict features.

Banking and payment apps are the most common examples where this shows up.

Google justifies these restrictions on sideloading as measures for "fraud prevention" and "risk analysis", but it's unclear how much they actually reduce fraud or improve user safety in practice. From a developer perspective, this is usually framed as security and abuse prevention. From a user perspective, especially in everyday usage, it can also show up in more subtle ways, for example when a third-party keyboard is being used, or when accessibility services are active on the device. Even though some banking apps rely on accessibility features themselves, certain combinations of active services can still trigger restrictions. This often feels less like a strict security boundary and more like a broad compatibility filter.

So the question becomes less “is this app installed?” and more “is this environment acceptable?”

Another place where this shows up is through application protection systems such as PAIRIP (Protected Android Integrity Runtime Protection), which some developers use to make apps harder to modify, repackage, or analyse.

I understand why these systems exist. From a developer perspective, protecting an app from tampering, piracy, fraud, or reverse engineering is a reasonable goal. If you are distributing software to millions of devices, especially in areas like finance or payments, additional protections can feel like an obvious choice.

What I find interesting is how these protections are experienced from the other side.

For most users, PAIRIP is not something they actively interact with. They usually only notice it when something stops working. An app might refuse to launch on a custom ROM, behave unexpectedly on a rooted device, or fail in an environment that looks unusual to the protection system.

And because these checks often happen quietly in the background, it is not always obvious what went wrong. The app simply does not run, or reports a generic error, leaving users to guess whether the problem is security-related, compatibility-related, or something else entirely.

Developers end up feeling some of this friction too. Stronger protection can reduce certain risks, but it can also create support requests from legitimate users whose devices fail checks despite working perfectly well for everything else.

So once again, the question becomes less about whether an app can be installed and more about whether the environment it runs in is considered acceptable.

That is a subtle shift, but it feels consistent with a broader pattern across Android. More and more trust decisions are happening outside the software itself, through layers that evaluate devices, accounts, configurations, and runtime behaviour before an app is allowed to operate normally.

Then there’s the Google account layer, which is harder to point at directly because it is spread across services.

reCAPTCHA is part of that picture. It used to be a simple “prove you are human” step. Now it often behaves more like a risk-based system that reacts to behaviour, device history, and account context.

And in practice, many flows feel smoother when you are inside a long-standing Google account, and more restrictive when you are not.

It does not directly control APK installation, but it affects surrounding actions, sign-ins, downloads, API access, and verification flows when something looks unusual.

Another layer sits at the app level itself.

Many banking apps, food delivery apps, shopping apps, and media apps include analytics, advertising, and anti-fraud systems.

For example, some apps may collect signals such as device identifiers, installed app environment metadata, interaction patterns, or network context. This is typically used for fraud prevention, personalization, advertising measurement, or service optimization.

In practice, users often experience this indirectly, through recommendations, pricing experiments, or offers that seem shaped by past behaviour. It is difficult to draw a strict boundary between personalization, profiling, and advertising-driven optimization, because all of them rely on overlapping data signals.

There is also another layer that shows up through ad-supported ecosystems. Many apps include third-party ad SDKs, and in some cases ad content may lead to external websites or redirect flows. While platforms like the Play Store enforce policies against malicious behaviour, users may still occasionally encounter misleading ads or unsafe redirects depending on the ad network or implementation quality.

This is also where ad blockers or private DNS tools change the experience significantly, because they remove or reduce this entire advertising and tracking layer. That creates a very different version of the same apps, especially in free, ad-supported ecosystems.

In the middle of all this, I keep coming back to F-Droid.

F-Droid stands out because it isn’t just another app store with different policies, it reflects a different way of thinking about trust in software distribution. Instead of centering trust around developer identity, device attestation, or platform-controlled enforcement systems, it leans heavily on transparency, reproducible builds where possible, and open community review.

That difference matters in practice. It changes what is being verified and who gets to decide what “trusted” means. In mainstream ecosystems, trust is often tied to identities, accounts, and centralized enforcement rules. In F-Droid’s model, trust is primarily derived from the ability to inspect, build, and verify the source itself.

This also creates a clearer separation between software and identity infrastructure. Developers can publish without being embedded into a centralized verification pipeline, and users can install software without their device state or account status being part of the gatekeeping process.

F-Droid isn’t trying to replicate commercial app stores feature by feature. It operates on a different assumption entirely, that trust should come from openness and verifiability rather than layered identity checks and enforcement systems.

What I’ve ended up noticing is that Android hasn’t stopped being open. That would be too simple.

Instead, it has become a system where openness still exists, but it is surrounded by more conditions than it used to be.

Developer identity is one layer. Device integrity is another. Account systems and verification flows like reCAPTCHA sit around the edges. App-level analytics, ads, and protection systems such as Play Integrity and PAIRIP add further layers. And beyond that, there are simply more friction points across installation and runtime than before.

From a critical perspective, a recurring concern among users and developers is that many of these additional layers, such as identity verification, device integrity checks, account-linked risk scoring, and app-level analytics, do not only address security threats in isolation. Instead, they also concentrate control points within a smaller set of platform and infrastructure providers. For some users, especially those outside mainstream device configurations, this can feel less like neutral security enforcement and more like a system where usability increasingly depends on compliance with layered platform-defined trust signals.

Do all of these exist without reason? Do they address real problems, malware, fraud, impersonation, and abuse?

Moreover, when you use the system as a developer or as a user outside the default ecosystem, installation is no longer a single decision. It becomes a sequence of checks across different layers.

Installing an app is still possible.

It just does not feel like one step anymore.

And depending on how you use your device, that shift can feel like either added protection or a growing stack of systems you do not directly control.

Either way, it is not quite the same Android it used to be.

[Guide] Forgejo Repository Migration (Existing Databases)

- Posted in Guides by

Forgejo Repository Migration (Existing Databases)

Objective: Merge repositories into a Forgejo instance without overwriting the existing database.

  1. Stop Forgejo on Source sudo systemctl stop forgejo

  2. Archive Repositories tar czf forgejo-repositories.tar.gz /var/lib/forgejo/data/forgejo-repositories

  3. Transfer to New Server scp forgejo-repositories.tar.gz user@new-server:/root/

  4. Extract Safely mkdir -p /root/forgejo-import tar xzf forgejo-repositories.tar.gz -C /root/forgejo-import

  5. Merge into Forgejo Storage rsync -a /root/forgejo-import/var/lib/forgejo/data/forgejo-repositories/ \ /var/lib/forgejo/data/forgejo-repositories/ sudo chown -R git:git /var/lib/forgejo/data/forgejo-repositories

  6. Restart Forgejo sudo systemctl start forgejo

  7. Adopt Unregistered Repositories

Admin → Site Administration → Repositories → Unadopted Repositories
Scan and adopt repositories
Assign owners and confirm

Verifiy

Repositories appear in UI
Branches and commits are intact
Git clone works
Existing repos are unaffected

Note: Only repositories are migrated; database remains intact.

[Blog] Migrating Forgejo Repositories into an existing instance

- Posted in First Timers by

Migrating Forgejo Repositories into an existing instance (without overwriting the database)

This is a Forgejo migration scenario where multiple approaches were attempted, including official documentation, community guides, and requesting help on Mastodon.

In the end, the working solution was a repository-level migration combined with Forgejo’s “Adopt Repositories” feature, without touching or overwriting the existing database.


The goal was to merge repositories from an old Forgejo server into a new one.

However, the situation was more complex than anticipated:

  • Both servers already had active Forgejo installations
  • The new server already contained repositories and users
  • The database on the new server could not be overwritten
  • The old server was only accessible via filesystem (URL was demised in error)

I tried taking this into account: Migrate your Forgejo site - community blog, and going through the forgejo upgrades & cheat-sheets.

While helpful for full-instance migrations, these guides assume:

  • A complete database export is available
  • The target system is being fully replaced
  • There are no existing repositories on the destination instance

This did not match the constraints I was facing.


Moreover, restoring an existing SQLite database dump to another running instance has its own problems:

  • The new server already has an active database
  • Overwriting the database would cause data loss
  • Merging two Forgejo databases is not safely supported

I then tried Various Git-based backup options:

  • git clone --mirror
  • git bundle
  • direct filesystem copying

While these successfully preserved Git history, they did not solve the core issue:

Forgejo does not automatically register repositories that exist on disk.

As a result, repositories did not appear in the web interface after transfer.


While I tried to find help on Mastodon (directly from Forgejo team) and on XMPP, the responses I received either:

  • Referred back to full database migration guides
  • Suggested rebuilding repositories manually
  • Did not account for the “existing instance + filesystem-only source” scenario

I was honestly stuck.


I finally found this approach:

  • Filesystem-level repository transfer
  • Forgejo’s built-in repository adoption feature
  • Preservation of the existing database on the new server

This allowed both systems to be merged safely.


Stop Forgejo on the source server

To ensure consistency, Forgejo was stopped before copying repositories:

```bash id="s1" sudo systemctl stop forgejo


--- Backup repositories from the source server Repositories are stored as bare Git repositories in: ```id="s2" /var/lib/forgejo/data/forgejo-repositories

They were archived using:

```bash id="s3" tar czf forgejo-repositories.tar.gz /var/lib/forgejo/data/forgejo-repositories


This preserves full Git history, branches, and tags. --- Transfer to the new server The archive was copied to the new server: ```bash id="s4" scp forgejo-repositories.tar.gz user@new-server:/root/

Extract into a staging directory (You can copy directly to the prod folder as well)

To avoid disrupting existing repositories on the new instance, the archive was extracted safely:

```bash id="s5" mkdir -p /root/forgejo-import tar xzf forgejo-repositories.tar.gz -C /root/forgejo-import


--- Merge repositories into Forgejo storage The repositories were then merged into the active Forgejo repository directory: ```bash id="s6" rsync -a /root/forgejo-import/var/lib/forgejo/data/forgejo-repositories/ \ /var/lib/forgejo/data/forgejo-repositories/

Correct ownership was applied (I applied to only the updated repo folders and files):

```bash id="s7" sudo chown -R git:git /var/lib/forgejo/data/forgejo-repositories


--- Restart Forgejo Forgejo was restarted: ```bash id="s8" sudo systemctl start forgejo

At this moment, the repositories existed on disk but were not yet visible in the web interface.

This is expected behaviour because Forgejo relies on its database for repository registration.


Using “Unadopted Repositories”

Forgejo provides a built-in mechanism for handling this situation.

In the web interface:

  1. Log in as an administrator
  2. Navigate to Site Administration
  3. Open Repositories
  4. Select Unadopted Repositories
  5. Click the scan icon (magnifying glass)

Forgejo scanned the repository directory and listed all repositories that existed on disk but were not yet registered in the database.


Adopting repositories

Each repository was then:

  • Selected individually
  • Assigned to a user or organisation
  • Adopted into Forgejo

For my instance, I had separate user wise repositories listed for me.

Once adopted, Forgejo automatically:

  • Created the required database entries
  • Linked repository metadata to the filesystem
  • Made the repositories visible in the UI

Verifying the details

  • All repositories appeared in the interface
  • Branches and commit histories were intact
  • Git cloning worked via HTTPS and SSH
  • Existing repositories on the new server remained unaffected

I have written a steps only blog too, since I am sure several people will face this or maybe facing it already.