blob: c31297203c85228850aa18a07e366a094a7985d6 [file] [log] [blame]
// 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 'dart:typed_data';
import 'package:flutter/foundation.dart';
import 'platform_channel.dart';
export 'dart:typed_data' show ByteData;
/// A message encoding/decoding mechanism.
///
/// Both operations throw an exception, if conversion fails. Such situations
/// should be treated as programming errors.
///
/// See also:
///
/// * [BasicMessageChannel], which use [MessageCodec]s for communication
/// between Flutter and platform plugins.
abstract class MessageCodec<T> {
/// Encodes the specified [message] in binary.
///
/// Returns null if the message is null.
ByteData? encodeMessage(T message);
/// Decodes the specified [message] from binary.
///
/// Returns null if the message is null.
T? decodeMessage(ByteData? message);
}
/// An command object representing the invocation of a named method.
@immutable
class MethodCall {
/// Creates a [MethodCall] representing the invocation of [method] with the
/// specified [arguments].
const MethodCall(this.method, [this.arguments])
: assert(method != null);
/// The name of the method to be called.
final String method;
/// The arguments for the method.
///
/// Must be a valid value for the [MethodCodec] used.
///
/// This property is `dynamic`, which means type-checking is skipped when accessing
/// this property. To minimize the risk of type errors at runtime, the value should
/// be cast to `Object?` when accessed.
final dynamic arguments;
@override
String toString() => '${objectRuntimeType(this, 'MethodCall')}($method, $arguments)';
}
/// A codec for method calls and enveloped results.
///
/// All operations throw an exception, if conversion fails.
///
/// See also:
///
/// * [MethodChannel], which use [MethodCodec]s for communication
/// between Flutter and platform plugins.
/// * [EventChannel], which use [MethodCodec]s for communication
/// between Flutter and platform plugins.
abstract class MethodCodec {
/// Encodes the specified [methodCall] into binary.
ByteData encodeMethodCall(MethodCall methodCall);
/// Decodes the specified [methodCall] from binary.
MethodCall decodeMethodCall(ByteData? methodCall);
/// Decodes the specified result [envelope] from binary.
///
/// Throws [PlatformException], if [envelope] represents an error, otherwise
/// returns the enveloped result.
///
/// The type returned from [decodeEnvelope] is `dynamic` (not `Object?`),
/// which means *no type checking is performed on its return value*. It is
/// strongly recommended that the return value be immediately cast to a known
/// type to prevent runtime errors due to typos that the type checker could
/// otherwise catch.
dynamic decodeEnvelope(ByteData envelope);
/// Encodes a successful [result] into a binary envelope.
ByteData encodeSuccessEnvelope(Object? result);
/// Encodes an error result into a binary envelope.
///
/// The specified error [code], human-readable error [message] and error
/// [details] correspond to the fields of [PlatformException].
ByteData encodeErrorEnvelope({ required String code, String? message, Object? details});
}
/// Thrown to indicate that a platform interaction failed in the platform
/// plugin.
///
/// See also:
///
/// * [MethodCodec], which throws a [PlatformException], if a received result
/// envelope represents an error.
/// * [MethodChannel.invokeMethod], which completes the returned future
/// with a [PlatformException], if invoking the platform plugin method
/// results in an error envelope.
/// * [EventChannel.receiveBroadcastStream], which emits
/// [PlatformException]s as error events, whenever an event received from the
/// platform plugin is wrapped in an error envelope.
class PlatformException implements Exception {
/// Creates a [PlatformException] with the specified error [code] and optional
/// [message], and with the optional error [details] which must be a valid
/// value for the [MethodCodec] involved in the interaction.
PlatformException({
required this.code,
this.message,
this.details,
this.stacktrace,
}) : assert(code != null);
/// An error code.
final String code;
/// A human-readable error message, possibly null.
final String? message;
/// Error details, possibly null.
///
/// This property is `dynamic`, which means type-checking is skipped when accessing
/// this property. To minimize the risk of type errors at runtime, the value should
/// be cast to `Object?` when accessed.
final dynamic details;
/// Native stacktrace for the error, possibly null.
///
/// This contains the native platform stack trace, not the Dart stack trace.
///
/// The stack trace for Dart exceptions can be obtained using try-catch blocks, for example:
///
/// ```dart
/// try {
/// ...
/// } catch (e, stacktrace) {
/// print(stacktrace);
/// }
/// ```
final String? stacktrace;
@override
String toString() => 'PlatformException($code, $message, $details, $stacktrace)';
}
/// Thrown to indicate that a platform interaction failed to find a handling
/// plugin.
///
/// See also:
///
/// * [MethodChannel.invokeMethod], which completes the returned future
/// with a [MissingPluginException], if no plugin handler for the method call
/// was found.
/// * [OptionalMethodChannel.invokeMethod], which completes the returned future
/// with null, if no plugin handler for the method call was found.
class MissingPluginException implements Exception {
/// Creates a [MissingPluginException] with an optional human-readable
/// error message.
MissingPluginException([this.message]);
/// A human-readable error message, possibly null.
final String? message;
@override
String toString() => 'MissingPluginException($message)';
}