Skip to content

fix: restored local feed access on Android 17 - #1281

Open
mvanhorn wants to merge 3 commits into
spacecowboy:masterfrom
mvanhorn:fix/1277-local-network-permission
Open

mvanhorn wants to merge 3 commits into
spacecowboy:masterfrom
mvanhorn:fix/1277-local-network-permission

Conversation

@mvanhorn

@mvanhorn mvanhorn commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

What does this change?

On Android 17 (API 37), Feeder can no longer fetch feeds hosted on the local network, such as a self-hosted FreshRSS instance, as reported in #1277. Android 17 puts LAN access behind the new ACCESS_LOCAL_NETWORK runtime permission, and Feeder neither declares nor requests it, so requests to local hosts fail while public feeds keep working. The manifest has no ACCESS_LOCAL_NETWORK declaration and nothing in the app asks for the permission, so on API 37 the platform blocks connections to local addresses.

Declared android.permission.ACCESS_LOCAL_NETWORK in AndroidManifest.xml. In MainActivity, on API 37 and newer, the app now asks for the permission once on launch when it is not already granted. The request is remembered in SharedPreferences before the dialog is shown, so denying it or recreating the activity does not prompt again; users can still grant it later from system settings, and the existing onResume sync picks that up. When the permission is granted from the dialog, a normal RSS sync is queued through runOnceRssSync so local feeds recover right away. Older Android versions are untouched. MainActivityTest now checks that the permission is declared in the merged manifest, pre-grants it on API 37 so the dialog does not block the test, and recreates the activity to make sure that path does not crash.

Ran ./gradlew testFdroidDebug locally for the Feeder MainActivity change; it passed.
Ran ./gradlew ktlintFormat, ktlintCheck, compileFdroidDebugKotlin, compileFdroidDebugAndroidTestKotlin, lintFdroidDebug and testFdroidDebug locally; all passed. I checked that ACCESS_LOCAL_NETWORK exists in the API 37 platform stubs. I did not run the instrumented MainActivityTest on an API 37 device or emulator, so the permission dialog flow itself is not covered by a local run.

Fixes #1277

Checklist

  • Ran ./gradlew ktlintFormat and committed the result
  • If the Room schema changed: added a MIGRATION_N_N+1 in AppDatabase.kt (not applicable, the schema is unchanged)
  • If the Room schema changed: added a migration test in app/src/androidTest/.../db/room/ (not applicable)

Screenshots (if UI change)

No app UI changed. On Android 17 the only visible difference is the system local network permission dialog on first launch.

@spacecowboy

spacecowboy commented Oct 23, 2026 •

Copy link
Copy Markdown
Owner

Thanks @mvanhorn this does fix the issue. However I'm not sure if it's appropriate to always request this permission. I can imagine users wondering why the app is requesting this when they don't have any local feeds which will be the majority of users.

It's also problematic that a user has to go via system settings to grant the permission if it is denied.

I think the ideal way of handling this would be in the Add feed screen. If the user is inputting a LAN-local address, this would be the time to request this permission. The user should understand immediately why the app is requesting the permission, and likely they also know that they are inputting a LAN-local address. If the permission were to be denied, then the app can ask again the next time a local address is added.

As a migration step, for users which already have local feeds added, the app can ask once on resume just like you are doing here.

That way the majority of users will never see this while fixing the issue for the power users

Per review, request the local network permission from the Add feed
screen when the entered URL points at a LAN-local address (a private,
link-local or loopback IP, or a host such as .local or .lan), and hold
the search until the permission result arrives. A denied permission is
asked for again the next time a local address is entered.

Users who already have a LAN-local feed are asked once on resume as a
migration step; everyone else is never prompted.
@mvanhorn

Copy link
Copy Markdown
Contributor Author

@spacecowboy moved the request to the Add feed screen in d63ed34. When the entered URL points at a LAN-local address (a private, link-local or loopback IP, or a host ending in .local, .lan, .home.arpa and similar), the app asks for the local network permission there, and a search started while the dialog is open waits for the answer. If it's denied, it asks again the next time a local address is entered. The on-resume prompt is now a one-time migration step that only runs for users who already have a LAN-local feed.

One gap: a bare LAN hostname like http://nas/feed.xml, or a regular DNS name that resolves to a private address, isn't detected, since catching those would mean resolving DNS while the user types. Do you want that handled, or is the suffix and IP check enough?

@spacecowboy

Copy link
Copy Markdown
Owner

I think we need to resolve hostnames to their addresses. That way we won't miss any

Pass ACCESS_LOCAL_NETWORK as a string literal, as the notification
permission does, so lint's InlinedApi check passes with minSdk 29.

This branch has not been deployed

No deployments
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.

Loading feeds from local server fails

2 participants