Sandbox: keep a launch intent for the FGS
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
pre-commit / pre-commit (${{ matrix.group }}) (flutter, flutter-analyze, ) (push) Waiting to run
pre-commit / pre-commit (${{ matrix.group }}) (mypy, mypy, ) (push) Waiting to run
pre-commit / pre-commit (${{ matrix.group }}) (pylint, pylint, ) (push) Waiting to run
pre-commit / pre-commit (${{ matrix.group }}) (rest, , mypy,pylint,flutter-analyze) (push) Waiting to run
Tests / test (push) Waiting to run
Tests / lock-popup-safety (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (0) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (1) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (2) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (3) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (4) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (5) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (6) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (7) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (8) (push) Waiting to run
Tests / flutter test (shard ${{ matrix.shard }}) (9) (push) Waiting to run
Tests / flutter-coverage (push) Blocked by required conditions
Tests / web-coverage (push) Waiting to run
release-apk / release (APK) (push) Waiting to run
repo-contract / repo contract (push) Waiting to run

2811f78 hid the sandbox from the launcher by removing its LAUNCHER
category. flutter_foreground_task builds its notification from
getLaunchIntentForPackage, which then returned null; the NPE meant
startForeground never ran and Android killed the app with
ForegroundServiceDidNotStartInTimeException on the first set tap and
on every resume. A separate MAIN+INFO filter (checked before LAUNCHER)
restores the intent and leaves the launcher entry hidden. The daily
flavor keeps LAUNCHER and was never affected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WzxdWYdwRAtMg7ki6TKxuU
This commit is contained in:
Krzysztof Rudnicki 2026-11-01 22:11:44 +01:00
parent 7264dcb1f7
commit aa56bc219e
2 changed files with 50 additions and 0 deletions

View File

@ -14,6 +14,14 @@
android:name="android.intent.category.LAUNCHER"
tools:node="remove"/>
</intent-filter>
<!-- Load-bearing: getLaunchIntentForPackage tries INFO before
LAUNCHER, and flutter_foreground_task's notification needs
that intent. Without it the service never calls
startForeground and Android kills the app. -->
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.INFO"/>
</intent-filter>
</activity>
</application>
</manifest>

View File

@ -0,0 +1,42 @@
// The sandbox flavor is hidden from the launcher, which removes the only
// intent filter `getLaunchIntentForPackage` used to find. flutter_foreground_task
// builds its notification from that intent; null made `startForeground` throw,
// so Android killed the app with ForegroundServiceDidNotStartInTimeException.
import 'dart:io';
import 'package:flutter_test/flutter_test.dart';
/// Relative to the package root, which is `flutter test`'s cwd.
const _manifestPath = 'android/app/src/sandbox/AndroidManifest.xml';
void main() {
late String manifest;
setUpAll(() => manifest = File(_manifestPath).readAsStringSync());
test('the sandbox stays out of the launcher', () {
expect(
manifest,
matches(
RegExp(
r'category\s+android:name="android\.intent\.category\.LAUNCHER"'
r'\s+tools:node="remove"',
),
),
);
});
test('a MAIN + INFO filter keeps the package launchable by intent', () {
final filters = RegExp(r'<intent-filter>(.*?)</intent-filter>', dotAll: true)
.allMatches(manifest)
.map((m) => m.group(1)!);
expect(
filters.where(
(f) =>
f.contains('android.intent.action.MAIN') &&
f.contains('android.intent.category.INFO'),
),
isNotEmpty,
);
});
}