Gmail Hide Ads

Removes sponsored conversation rows from the Gmail inbox before they are measured, so an advertisement leaves no row and no empty gap.

An advertisement is identified by its view class, not by the badge it renders. Gmail's English badge is the string resource string/ad, whose value is simply Ad; matching that text needs a word list in every language Gmail ships, and it collapsed ordinary mail during testing. The class name carries the same information and cannot be mistaken.

Gmail serves these advertisements in the Promotions and Social tabs. With the Promotions tab switched off in Gmail's settings, Gmail delivers none and the module has nothing to remove.

Scope

The module declares a static scope of:

com.google.android.gm

META-INF/xposed/scope.list carries that declaration, so no scope selection is required in the manager. Do not add other applications.

Requirements

  • A framework implementing the modern Xposed API, version 101 or newer. The legacy de.robv.android.xposed API is not used, so a framework implementing only that API cannot load this module.
    • Rooted: Vector on Android 8.1 or newer, with Magisk or KernelSU and Zygisk enabled.
    • Rootless: LSPatch, the JingMatrix fork. It embeds Vector into a patched Gmail APK and loads modern libxposed modules through the same runtime. The archived LSPosed/LSPatch build predates the modern API and cannot load this module.
  • Android 8.0 (API 26) or newer.
  • The official Gmail application (com.google.android.gm).

Installation

  1. Install the APK from the release attached to this repository.
  2. Enable Gmail Hide Ads in the framework manager. With LSPatch, select it when patching Gmail in manager mode, or embed it in integrated mode.
  3. Force-stop Gmail once, then reopen it.
  4. A working start-up logs the framework, the detected Gmail build, and the installed layer:
Gmail Hide Ads v1.0.0: loading in com.google.android.gm, framework=Vector 2.2, api=102
Host: 2026.08.17.974752392.Release (65972134)
Layer installed: ad-teaser
Active layers: 1/1

Each removal is logged with the class and view id that matched:

Collapsed advertisement row #1: com.google.android.gm.ads.adteaser.BasicAdTeaserItemView#basic_ad_teaser_item

How it works

Gmail is minified on every release, so almost nothing inside it keeps a stable name. Its advertisement rows are the exception, and that exception is what this module is built on.

Every Gmail ad row is inflated from a layout that names its root class in XML. R8 cannot rename a class a layout refers to by name, so these survive minification intact:

com.google.android.gm.ads.adteaser.BasicAdTeaserItemView
com.google.android.gm.ads.adteaser.VideoAdTeaserItemView
com.google.android.gm.ads.adteaser.ImageCarouselAdTeaserItemView
com.google.android.gm.ads.adteaser.RichButtonChipAdTeaserItemView
com.google.android.gm.ads.adteaser.AppInstallButtonChipAdTeaserItemView
com.google.android.gm.ads.adteaser.EuSingleImageAdTeaserItemView

The hook is installed on ViewGroup.addView(View, int, ViewGroup.LayoutParams) — the overload the other four public addView signatures funnel into, and the first moment a row has its layout parameters. Hooking an Android framework method rather than a Gmail class means a Gmail update does not move the hook point.

A view is classified by walking its superclasses for a name under com.google.android.gm.ads. ending in AdTeaserItemView, so a release that subclasses one of these is still recognized. The verdict is cached per class, because addView is a hot path. A matching row has its layout height zeroed and its visibility set to GONE before it is ever measured — both are required, since GONE stops the row drawing but a RecyclerView layout manager still measures its attached children.

The hook target is deoptimized through XposedInterface.deoptimize, because the shorter addView overloads are small enough for ART to inline and an already compiled caller could otherwise bypass the hook.

There is no restore path, and none is needed: Gmail gives an advertisement its own RecyclerView item type, so a row of one of these classes is never rebound to ordinary mail. If the layer cannot install, it is logged and skipped and Gmail is left exactly as it was.

The module carries no native library and no DEX-search dependency.

Validation

The ad row class names were read out of the compiled layouts of Gmail 2026.08.17.974752392.Release (65972134) and confirmed present and unrenamed in its DEX.

Measured on a Pixel 8 Pro running Android 17 with Vector 2.2 (libxposed API 102). A real sponsored row was collapsed in the Promotions tab, logged as BasicAdTeaserItemView#basic_ad_teaser_item, leaving the list with no advertisement and no empty gap. Gmail rendered normally throughout Primary, Promotions, Social, Updates and Forums under repeated scrolling, with no crash and no ordinary mail collapsed.

One caveat, stated plainly: Gmail delivers these advertisements intermittently, so a side-by-side capture of the same row with the module disabled was not obtained. The evidence is the logged removal of a genuine ad row instance, not a paired screenshot.

Troubleshooting

Problem Suggested action
No advertisement is ever removed Expected when none is being served. Gmail shows these only in the Promotions and Social tabs; with the Promotions tab switched off in Gmail's settings there is nothing to remove.
Sponsored rows still appear Confirm the module is enabled and that the log reports Active layers: 1/1. If the layer installed but nothing is collapsed, Gmail has probably renamed its ad row classes.
No module log entries at all Verify the module is enabled and Gmail is in scope, then force-stop Gmail once. The framework must implement libxposed API 101 or newer.
ViewGroup.addView hook rejected The framework refused the hook. Check that it reports API 101 or newer in the start-up line.
Rows not collapsed after a Gmail update Capture the Collapsed advertisement row lines, or their absence, along with the Host: line naming the Gmail build, and open an issue.
An advertisement briefly reappears while scrolling fast RecyclerView can re-attach a cached row through a path that bypasses addView. Report the Gmail version if this is reproducible.

Credits

Project Contribution
Vector by JingMatrix The ART hooking framework, and the method deoptimization used to reach inlined framework methods. GPL-3.0.
LSPatch by JingMatrix Embeds Vector into a patched APK, which is how this module runs without root. GPL-3.0.
libxposed API The modern Xposed module API this module compiles against. Apache-2.0.

Disclaimer

Not affiliated with, endorsed by, or sponsored by Google LLC. "Gmail" is a trademark of Google LLC and is used only to name the application this module targets. The module modifies Gmail's behaviour in memory on the user's own device; it does not redistribute or patch the Gmail APK, and it transmits nothing off the device. Provided for educational and personal use. App updates may break the hook without notice.

Releases

1.0.0

Stable

9/9/2026, 1:37:53 PM

First release in the Xposed Module Repository.

Removes sponsored conversation rows from the Gmail inbox before they are measured, matching an ad row by its view class rather than by badge text. Requires a framework implementing the modern Xposed API 101 or newer: Vector with root, or the JingMatrix fork of LSPatch without.

The application ID is io.github.mrxsin.gmailhideads. If you previously installed a build under the old my.MrxSiN prefix, this installs alongside it rather than upgrading it, so uninstall the old copy.

Assets

1