Migrating the Flutter plugin from v4
This page takes an app from any 4.x release of the Flutter plugin to 5.3.0. For a fresh integration, use the Flutter guide instead.
5.3.0 speaks frame version 2 and needs a v5 relay. A v4 plugin cannot talk to a v5 relay (the relay answers 478), and 5.3.0 cannot talk to a v4 relay. Plan the app release alongside the relay upgrade.
Dependency, package name and import
The repository and the package were renamed:
dependencies:
# was:
# mte_relay_client_plugin:
# git:
# url: https://github.com/Eclypses/mte-relay-client-flutter.git
# ref: 4.2.11
mte_relay:
git:
url: https://github.com/Eclypses/relay-client-plugin-flutter.git
ref: v5.3.0
// was: package:mte_relay_client_plugin/mte_relay_client_plugin.dart
// and package:mte_relay_client_plugin/mte_relay_response_model.dart
import 'package:mte_relay/mte_relay.dart';
The CocoaPods variant (mte-relay-client-flutter-pod) is discontinued; 5.3.0 uses Swift
Package Manager on iOS.
Platform minimums
| v4 | 5.3.0 | |
|---|---|---|
| iOS | 14.0 | 16.0 |
Android minSdk | — | 28 |
| Xcode | 14.0 | 15.0 |
On iOS, set IPHONEOS_DEPLOYMENT_TARGET to 16.0 in Build Settings on the Runner project, where
the Flutter template sets it, and on the Runner target too if it overrides the value.
If your app uses package:http: the whole migration
5.3.0 adds RelayHttpClient, an http.Client. Swap the construction and point the URL at your
relay; your http.Response handling stays as it is, and no setup call is needed:
// was: final client = http.Client(); (or a MteRelayClientPlugin call per request)
final client = RelayHttpClient();
Failures, the relay's own included, arrive as http.ClientException. If this covers your app,
the typed-API changes below do not apply to you.
headersToEncrypt is now unencryptedHeaders, and means the opposite
v4 encrypted only the headers you listed. 5.3.0 encrypts every header and leaves in the clear only those you list. Porting a v4 list unchanged would send exactly the headers you meant to protect in the clear, so in most cases drop the argument.
Content-Type, Content-Length, Host, X-MTE-Relay-Route and X-MTE-Relay-Client are
reserved and always encrypted; listing one throws.
The typed API
MteRelayClient replaces MteRelayClientPlugin as the main class, with typed request and
response models in place of Map arguments.
| v4 | 5.3.0 |
|---|---|
MteRelayClientPlugin | MteRelayClient; MteRelayClientPlugin only to write an upload's body |
initializeRelay() | initialize() — optional; the first request initializes |
relayDataTask(Map args) | send(RelayRequest) → RelayResponse, or stream(RelayRequest) |
Result.fromMap(response) | the RelayResponse that send() returns |
'url' / 'body' in the args map | serverUrl / body (Uint8List) on RelayRequest, or RelayRequest.text(...) |
relayDownloadFile(Map args) | startDownload(RelayFileDownloadRequest) |
'downloadLocation' | destinationPath — required; the app chooses it |
relayUploadFile(Map args) | startUpload(RelayFileUploadRequest), body written through MteRelayClientPlugin (sendChunk/closeStream) |
rePair({url, pathnamePrefix}) | repair(serverUrl, pathnamePrefix: ...) |
adjustRelaySettings({url, pairPoolSize}) | updateSettings(serverUrl, RelayClientSettings(...)) |
enableFileLogging({'url': ..., 'isEnabled': ...}) | enableFileLogging(bool) |
readLogFile({'url': ...}) / clearLogFile({'url': ...}) | readLogFile() / clearLogFile() |
| several callback streams | one events stream of RelayOperationEvent |
final relay = MteRelayClient();
final response = await relay.send(RelayRequest.text(
serverUrl: 'https://your-relay-server.com',
route: '/api/login',
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'email': 'user@example.com', 'password': 'P@ssw0rd!'}),
));
await relay.repair('https://your-relay-server.com');
await relay.updateSettings(
'https://your-relay-server.com',
RelayClientSettings(minPairs: 5, basePairs: 8, maxPairs: 15,
keepAliveIntervalSeconds: 300, acquisitionWaitTime: 1.0),
);
The stream chunk size and pair persistence settings are gone.
File transfer notes
- Leave
unencryptedHeadersempty for uploads: the multipart framing headers travel encrypted, and listingContent-TypeorContent-Lengththrows. - The relay's advertised request-body limit now applies to streamed uploads too; an upload over it is refused before anything is sent.
- A download needs a non-empty, writable
destinationPath. The plugin does not pick a directory for you.