diff --git a/packages/flutter/lib/src/services/platform_channel.dart b/packages/flutter/lib/src/services/platform_channel.dart index a57deb694c..b2c6c7d5d8 100644 --- a/packages/flutter/lib/src/services/platform_channel.dart +++ b/packages/flutter/lib/src/services/platform_channel.dart @@ -129,7 +129,17 @@ class MethodChannel { /// The messenger used by this channel to send platform messages. /// /// The messenger may not be null. - BinaryMessenger get binaryMessenger => _binaryMessenger ?? ServicesBinding.instance!.defaultBinaryMessenger; + BinaryMessenger get binaryMessenger { + assert( + _binaryMessenger != null || ServicesBinding.instance != null, + 'Cannot use this MethodChannel before the binary messenger has been initialized. ' + 'This happens when you invoke platform methods before the WidgetsFlutterBinding ' + 'has been initialized. You can fix this by either calling WidgetsFlutterBinding.ensureInitialized() ' + 'before this or by passing a custom BinaryMessenger instance to MethodChannel().', + ); + + return _binaryMessenger ?? ServicesBinding.instance!.defaultBinaryMessenger; + } final BinaryMessenger? _binaryMessenger; /// Backend implementation of [invokeMethod]. diff --git a/packages/flutter/test/services/use_platform_channel_without_initialization_test.dart b/packages/flutter/test/services/use_platform_channel_without_initialization_test.dart new file mode 100644 index 0000000000..c2049e87e4 --- /dev/null +++ b/packages/flutter/test/services/use_platform_channel_without_initialization_test.dart @@ -0,0 +1,24 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + // We need a separate test file for this test case (instead of including it + // in platform_channel_test.dart) since we rely on the WidgetsFlutterBinding + // not being initialized and we call ensureInitialized() in the other test + // file. + test('throws assertion error iff WidgetsFlutterBinding is not yet initialized', () { + const MethodChannel methodChannel = MethodChannel('mock'); + + // Ensure that accessing the binary messenger before initialization reports + // a helpful error message. + expect(() => methodChannel.binaryMessenger, throwsA(isA() + .having((AssertionError e) => e.message, 'message', contains('WidgetsFlutterBinding.ensureInitialized()')))); + + TestWidgetsFlutterBinding.ensureInitialized(); + expect(() => methodChannel.binaryMessenger, returnsNormally); + }); +}