diff --git a/lib/data/db/database.dart b/lib/data/db/database.dart index e9abf31..c277111 100644 --- a/lib/data/db/database.dart +++ b/lib/data/db/database.dart @@ -596,8 +596,10 @@ Future initDatabasePath() async { Future _resolveDatabasePath() async { if (_dbPath != null) return _dbPath!; // initDatabasePath() failed (channel not ready before runApp). Retry now - // that the engine is fully initialised, with brief back-off. - const delays = [100, 300, 600]; + // that the engine is fully initialised, with back-off. Some slow Android + // devices need several seconds for the Pigeon channel to become ready + // (issue #166), so use a longer schedule than the initial attempt. + const delays = [200, 500, 1000, 2000]; for (final ms in delays) { try { final dir = await getApplicationSupportDirectory(); diff --git a/test/unit/database_path_test.dart b/test/unit/database_path_test.dart new file mode 100644 index 0000000..ad60e4c --- /dev/null +++ b/test/unit/database_path_test.dart @@ -0,0 +1,41 @@ +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; + +import 'package:sharedinbox/data/db/database.dart'; + +// Fake PathProviderPlatform that always throws PlatformException(channel-error) +// to simulate the Pigeon channel not being ready at startup (issue #166). +class _UnavailablePathProvider extends Fake + with MockPlatformInterfaceMixin + implements PathProviderPlatform { + @override + Future getApplicationSupportPath() async { + throw PlatformException( + code: 'channel-error', + message: 'Simulated: path_provider channel not ready', + ); + } +} + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + // Regression test for https://codeberg.org/guettli/sharedinbox/issues/166: + // On some slow Android devices the path_provider Pigeon channel is not ready + // when initDatabasePath() runs before runApp(). initDatabasePath() must + // absorb the PlatformException and let the app start; _resolveDatabasePath() + // then retries with back-off on first DB access. + test( + 'initDatabasePath completes without throwing when path_provider is unavailable', + () async { + final prev = PathProviderPlatform.instance; + PathProviderPlatform.instance = _UnavailablePathProvider(); + addTearDown(() => PathProviderPlatform.instance = prev); + + // Must not throw — the exception is swallowed so the app can continue. + await expectLater(initDatabasePath(), completes); + }, + ); +}