Skip to content

Remove Android permissions that plugins inject; bump serious_python to 4.5.1 - #6742

Merged
FeodorFitsner merged 1 commit into
mainfrom
fix/android-remove-plugin-permissions
Jul 31, 2026
Merged

Remove Android permissions that plugins inject; bump serious_python to 4.5.1#6742
FeodorFitsner merged 1 commit into
mainfrom
fix/android-remove-plugin-permissions

Conversation

@FeodorFitsner

@FeodorFitsner FeodorFitsner commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Setting an Android permission to false had no effect on permissions that arrive from somewhere other than the app's own configuration. The template only skipped emitting the <uses-permission> entry, so anything contributed by Gradle's manifest merger — which folds in the manifest of every Flutter plugin, and also synthesises permissions on its own — passed straight through with no way to stop it.

The bug in practice

Flet Studio removed every storage permission from its pyproject.toml in #6740, and READ_EXTERNAL_STORAGE / WRITE_EXTERNAL_STORAGE still shipped to Google Play. The merger report explains why:

uses-permission#android.permission.WRITE_EXTERNAL_STORAGE
ADDED from [:camera_android_camerax] .../AndroidManifest.xml:11:5-13:38

uses-permission#android.permission.READ_EXTERNAL_STORAGE
IMPLIED from .../AndroidManifest.xml reason: io.flutter.plugins.camerax requested WRITE_EXTERNAL_STORAGE

flet-camera pulls in camera_android_camerax, which declares WRITE_EXTERNAL_STORAGE bounded to maxSdkVersion="28" — correct on its part. The merger then implies READ_EXTERNAL_STORAGE from it, because write access implied read access before API 19.

The implied entry carries no maxSdkVersion. So a properly bounded permission quietly produces an unbounded one — precisely the shape Google Play's storage policy objects to, and neither name appears anywhere in the app's config.

The fix

Permissions set to false now render as:

<uses-permission android:name="..." tools:node="remove" />

and the template's <manifest> gained the tools namespace. This strips them during the merge rather than merely declining to add them.

[tool.flet.android.permission]
"android.permission.READ_EXTERNAL_STORAGE" = false
"android.permission.WRITE_EXTERNAL_STORAGE" = false

Why changing false is safe

false never had another meaning to change. No permission is set to False by flet's own defaults (android_permissions defaults to just INTERNET: True) or by any cross-platform permission bundle — only android_features uses False, through a separate template loop. So false can only come from an explicit user declaration, where removal is the evident intent.

Removing a permission that nothing declares is a no-op, so false stays safe for names no plugin contributes. Both entry points agree: --android-permissions X=false parses through parse_cli_bool_value to a real bool.

Verification

Against the real plugin set, on Flet Studio's release APK:

Permissions
before 11, incl. both storage entries
after 9, neither present

Confirmed in aapt2 dump permissions on the built APK and in the merged manifest; every other permission intact.

Also in this PR

  • serious_python 4.4.2 → 4.5.1 in the build template.
  • Bundled python-build snapshot re-pinned 20260727 → 20260730 (dart_bridge 1.7.1).

serious_python 4.5.1 tracks the same python-build release (pythonReleaseDate = "20260730"), so PYTHON_BUILD_RELEASE_DATE stays in sync as the comment on that constant requires. 4.5.1 is published on pub.dev.

Docs

New section: Removing a permission a plugin adds, covering the camerax example, how to read manifest-merger-release-report.txt to find where any permission came from, and a caution that removing one a plugin genuinely needs turns a build-time concern into a runtime failure.

78 flet-cli tests pass.

Summary by Sourcery

Actively remove Android permissions disabled in configuration during manifest merge and align bundled Python tooling versions.

Bug Fixes:

  • Ensure Android permissions set to false in flet configuration are removed from the merged manifest, including those introduced or synthesized by Flutter plugins.

Enhancements:

  • Document how to remove plugin-added Android permissions and how to trace their origins via Gradle’s manifest merge report.
  • Update Android manifest template to declare the tools namespace and emit removal nodes for disabled permissions.

Build:

  • Bump serious_python dependency to 4.5.1 in the build template and re-pin the bundled python-build snapshot to the 20260730 release.

Documentation:

  • Expand Android publishing docs with guidance on removing plugin-added permissions and locating their sources in manifest merger reports.

…o 4.5.1

Setting an Android permission to `false` had no effect on permissions that
arrive from somewhere other than the app's own configuration. The template
only skipped emitting the <uses-permission> entry, so anything contributed by
Gradle's manifest merger -- which folds in the manifest of every Flutter
plugin, and also synthesises permissions on its own -- passed straight through
with no way to stop it.

Flet Studio hit this after removing every storage permission from its
pyproject.toml: READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE still shipped
to Google Play. The merger report explains why:

  uses-permission#android.permission.WRITE_EXTERNAL_STORAGE
  ADDED from [:camera_android_camerax] .../AndroidManifest.xml:11:5-13:38
  uses-permission#android.permission.READ_EXTERNAL_STORAGE
  IMPLIED from .../AndroidManifest.xml reason: io.flutter.plugins.camerax
      requested WRITE_EXTERNAL_STORAGE

flet-camera pulls in camera_android_camerax, which declares
WRITE_EXTERNAL_STORAGE bounded to maxSdkVersion="28" -- correct on its part.
The merger then implies READ_EXTERNAL_STORAGE from it, because write access
implied read access before API 19. The implied entry carries no
maxSdkVersion, so a properly bounded permission quietly produces an unbounded
one, which is the shape Google Play's storage policy objects to.

Permissions set to `false` now render as

  <uses-permission android:name="..." tools:node="remove" />

and the template's <manifest> gained the tools namespace. This strips them
during the merge rather than merely declining to add them. Removing a
permission nothing declares is a no-op, so `false` stays safe for names no
plugin contributes.

`false` never had another meaning to change: no permission is set to False by
flet's own defaults or by any cross-platform permission bundle (only
android_features uses False, via a separate loop), so it can only come from an
explicit user declaration, where removal is the evident intent. Both entry
points agree -- `--android-permissions X=false` parses through
parse_cli_bool_value to a real bool.

Verified against the real plugin set: Flet Studio's release APK goes from 11
permissions to 9, with both storage entries absent from `aapt2 dump
permissions` and from the merged manifest, and every other permission intact.

Also bumps serious_python 4.4.2 -> 4.5.1 in the build template and re-pins the
bundled python-build snapshot 20260727 -> 20260730 (dart_bridge 1.7.1).
serious_python 4.5.1 tracks the same python-build release, so
PYTHON_BUILD_RELEASE_DATE stays in sync with its pythonReleaseDate as the
comment on that constant requires.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@FeodorFitsner
FeodorFitsner merged commit a15ab62 into main Jul 31, 2026
19 of 129 checks passed
@FeodorFitsner
FeodorFitsner deleted the fix/android-remove-plugin-permissions branch July 31, 2026 21:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant