Giter Site home page Giter Site logo

ably / ably-flutter Goto Github PK

View Code? Open in Web Editor NEW
60.0 32.0 14.0 5.44 MB

A wrapper around our Cocoa and Java client library SDKs, providing iOS and Android support for those using Flutter and Dart.

Home Page: https://ably.com/download

License: Apache License 2.0

Java 19.38% Ruby 0.45% Objective-C 13.35% Dart 60.28% JavaScript 0.47% Kotlin 0.02% Swift 3.96% Shell 0.01% C 2.08%
client-library flutter dart realtime realtime-messaging websockets streaming android ios sdk

ably-flutter's Introduction

Ably Flutter Plugin

https://pub.dev/packages/ably_flutter .github/workflows/check.yaml .github/workflows/docs.yml .github/workflows/flutter_integration.yaml .github/workflows/flutter_example_app.yaml Features

Ably is the platform that powers synchronized digital experiences in realtime. Whether attending an event in a virtual venue, receiving realtime financial information, or monitoring live car performance data – consumers simply expect realtime digital experiences as standard. Ably provides a suite of APIs to build, extend, and deliver powerful digital experiences in realtime for more than 250 million devices across 80 countries each month. Organizations like Bloomberg, HubSpot, Verizon, and Hopin depend on Ably’s platform to offload the growing complexity of business-critical realtime data synchronization at global scale. For more information, see the Ably documentation.

Supported platforms

Requirements

  • Flutter 2.5.0 or higher
  • iOS 10 or newer
  • Android API Level 19 (Android 4.4, KitKat) or newer

This project uses Java 8 language features, utilizing Desugaring to support lower versions of the Android runtime (i.e. API Levels prior to 24).

If your project needs support for SDK Version lower than 24, Android Gradle Plugin 4.0.0+ must be used. You might also need to upgrade gradle distribution accordingly.

Installation

Specify Dependency

In pubspec.yaml file:

dependencies:
  ably_flutter: ^1.2.34

Import the package

import 'package:ably_flutter/ably_flutter.dart' as ably;

Updating to a newer version

When increasing the version of ably_flutter in your pubspec.yaml, if there are breaking changes, follow the updating / migration guide.

Usage

Please check demo code snippets and flutter example app for more detailed usage.

Authentication

Authentication using API Key

// Create an instance of ClientOptions with Ably key
final clientOptions = ably.ClientOptions(key: '<KEY>');

// Use ClientOptions to create Realtime or REST instance
ably.Realtime realtime = ably.Realtime(options: clientOptions);
ably.Rest rest = ably.Rest(options: clientOptions);

Also see docs: Auth and Security: Basic authentication

Token Authentication

Supplying a TokenCallback:

// Create an instance of ClientOptions with Ably token and authCallback
ably.ClientOptions clientOptions = ably.ClientOptions(
    key: '<TOKEN>', 
    clientId: '<CLIENT>', // Optional
    authCallback: (ably.TokenParams tokenParams) async {
        // `createTokenRequest` should be implemented to communicate with user server
        ably.TokenRequest tokenRequest = await createTokenRequest(tokenParams);
        // `authCallback` has to return an instance of TokenRequest
        return tokenRequest;
    }
);

// Use ClientOptions to create Realtime or REST instance
ably.Realtime realtime = ably.Realtime(options: clientOptions);
ably.Rest rest = ably.Rest(options: clientOptions);

Also see docs: Auth and Security: Token authentication

Realtime instance

Create an instance of the Realtime Client

ably.Realtime realtime = ably.Realtime(options: clientOptions);

Read Realtime time

DateTime time = realtime.time()

Connection state

Listen for all connection state events

realtime.connection
    .on()
    .listen((ably.ConnectionStateChange stateChange) async {
        // Handle connection state change events
    });

Listen for particular connection state event

realtime.connection
    .on(ably.ConnectionEvent.connected) // Any type of `ConnectionEvent` can be specified
    .listen((ably.ConnectionStateChange stateChange) async {
        // Handle connection state change events
    });

Retrieve connection id, state etc

String connectionId = realtime.connection.id;
ConnectionState state = realtime.connection.state;
String recoveryKey = await realtime.connection.createRecoveryKey(); // https://ably.com/docs/connect/states?q=recovery#connection-state-recover-options

Realtime channel

Create instance of Realtime channel

ably.RealtimeChannel channel = realtime.channels.get('channel-name');

Attach and detach from channel

await channel.attach()
await channel.detach()

Channel state

Listen for all channel state events

channel
    .on()
    .listen((ably.ChannelStateChange stateChange) async {
        // Handle channel state change events
    });

Listen for particular channel state event

channel
    .on(ably.ChannelEvent.failed) // Any type of `ConnectionEvent` can be specified
    .listen((ably.ChannelStateChange stateChange) async {
        // Handle channel state change events
    });

Channel messages

Listen for all messages

StreamSubscription<ably.Message> subscription = 
    channel
        .subscribe()
        .listen((ably.Message message) {
            // Handle channel message
        });

Listen for message with selected name

StreamSubscription<ably.Message> subscription = 
    channel
        .subscribe(name: 'event1')
        .listen((ably.Message message) {
            // Handle channel messages with name 'event1'
        });

Listen for messages with a set of selected names

StreamSubscription<ably.Message> subscription =
    channel
        .subscribe(names: ['event1', 'event2'])
        .listen((ably.Message message) {
            // Handle channel messages with name 'event1' or `event2`
        });

Stop listening for messages

await subscription.cancel()

Publish single message on channel

// Publish simple message
await channel.publish(
    name: "event1",
    data: "hello world",
);

// Publish message data as json-encodable object
await channel.publish(
    name: "event1",
    data: {
        "hello": "world",
        "hey": "ably",
    },
);

// Publish message as array of json-encodable objects
await channel.publish(
    name: "event1",
    data: [
        {
        "hello": {
            "world": true,
        },
        "ably": {
            "serious": "realtime",
        },
    ],
);

// Publish message as an `ably.Message` object
await channel.publish(
    message: ably.Message(
        name: "event1",
        data: {
            "hello": "world",
        }
    ),
);

Publish multiple messages on channel

await channel.publish(
    messages: [
        ably.Message(
            name: "event1",
            data: {
                "hello": "world",
            }
        ),
        ably.Message(
            name: "event1",
            data: {
                "hello": "ably",
            }
        ),
    ],
);

Channel history

Read channel history

// Get channel history with default parameters
ably.PaginatedResult<ably.Message> history = await channel.history()

// Get channel history with custom parameters
ably.PaginatedResult<ably.Message> filteredHistory = await channel.history(
    ably.RealtimeHistoryParams(
        direction: 'forwards',
        limit: 10,
    )
)

Realtime presence

Enter Realtime presence

// Enter using client ID from `ClientOptions`
await channel.presence.enter();

// Enter using client ID from `ClientOptions` with additional data
await channel.presence.enter("hello");
await channel.presence.enter([1, 2, 3]);
await channel.presence.enter({"key": "value"});

// Enter with specified client ID
await channel.presence.enterClient("user1");

// Enter with specified client ID and additional data
await channel.presence.enterClient("user1", "hello");
await channel.presence.enterClient("user1", [1, 2, 3]);
await channel.presence.enterClient("user1", {"key": "value"});

Update Realtime presence

// Update using client ID from `ClientOptions`
await channel.presence.update();

// Update using client ID from `ClientOptions` with additional data
await channel.presence.update("hello");
await channel.presence.update([1, 2, 3]);
await channel.presence.update({"key": "value"});

// Update with specified client ID
await channel.presence.updateClient("user1");

// Update with specified client ID and additional data
await channel.presence.updateClient("user1", "hello");
await channel.presence.updateClient("user1", [1, 2, 3]);
await channel.presence.updateClient("user1", {"key": "value"});

Leave Realtime presence

// Leave using client ID from `ClientOptions`
await channel.presence.leave();

// Leave using client ID from `ClientOptions` with additional data
await channel.presence.leave("hello");
await channel.presence.leave([1, 2, 3]);
await channel.presence.leave({"key": "value"});

// Leave with specified client ID
await channel.presence.leaveClient("user1");

// Leave with specified client ID and additional data
await channel.presence.leaveClient("user1", "hello");
await channel.presence.leaveClient("user1", [1, 2, 3]);
await channel.presence.leaveClient("user1", {"key": "value"});

Get Realtime presence

// Get all presence messages
List<ably.PresenceMessage> presenceMessages = await channel.presence.get();

// Get presence messages with specific Client ID
presenceMessages = await channel.presence.get(
    ably.RealtimePresenceParams(
        clientId: 'clientId',
    ),
);

// Get presence messages with specific Connection ID
presenceMessages = await channel.presence.get(
    ably.RealtimePresenceParams(
        connectionId: 'connectionId',
    ),
);

Read Realtime presence history

// Get presence history with default parameters
ably.PaginatedResult<ably.PresenceMessage> history = await channel.presence.history()

// Get presence history with custom parameters
ably.PaginatedResult<ably.PresenceMessage> filteredHistory = await channel.presence.history(
    ably.RealtimeHistoryParams(
        direction: 'forwards',
        limit: 10,
    )
)

Listen for all Realtime presence messages

StreamSubscription<ably.PresenceMessage> subscription =
    channel
        .presence
        .subscribe()
        .listen((presenceMessage) {
            // Handle presence message
        },
);

Listen for a particular presence message

StreamSubscription<ably.PresenceMessage> subscription =
    channel
        .presence
        .subscribe(action: PresenceAction.enter)
        .listen((presenceMessage) {
            // Handle `enter` presence message
        },
);

Listen for a set of particular presence messages

StreamSubscription<ably.PresenceMessage> subscription =
    channel
        .presence
        .subscribe(actions: [
            PresenceAction.enter,
            PresenceAction.update,
        ])
        .listen((presenceMessage) {
            // Handle `enter` and `update` presence message
        },
);

REST instance

Create an instance of the REST Client

ably.Rest rest = ably.Rest(options: clientOptions);

Read REST time

DateTime time = rest.time()

REST channel

Create instance of REST channel

ably.RestChannel channel = rest.channels.get('channel-name');

REST channel messages

Publish single message on REST channel

// Publish simple message
await channel.publish(
    name: "event1",
    data: "hello world",
);

// Publish message data as json-encodable object
await channel.publish(
    name: "event1",
    data: {
        "hello": "world",
        "hey": "ably",
    },
);

// Publish message as array of json-encodable objects
await channel.publish(
    name: "event1",
    data: [
        {
        "hello": {
            "world": true,
        },
        "ably": {
            "serious": "realtime",
        },
    ],
);

// Publish message as an `ably.Message` object
await channel.publish(
    message: ably.Message(
        name: "event1",
        data: {
            "hello": "world",
        }
    ),
);

Publish multiple messages on REST channel

await channel.publish(
    messages: [
        ably.Message(
            name: "event1",
            data: {
                "hello": "world",
            }
        ),
        ably.Message(
            name: "event1",
            data: {
                "hello": "ably",
            }
        ),
    ],
);

REST channel history

Read REST channel history

// Get channel history with default parameters
ably.PaginatedResult<ably.Message> history = await channel.history()

// Get channel history with custom parameters
ably.PaginatedResult<ably.Message> filteredHistory = await channel.history(
    ably.RestHistoryParams(
        direction: 'forwards',
        limit: 10,
    )
)

REST presence

Get REST presence

// Get all presence messages
List<ably.PresenceMessage> presenceMessages = await channel.presence.get();

// Get presence messages with specific Client ID
presenceMessages = await channel.presence.get(
    ably.RestPresenceParams(
        clientId: 'clientId',
    ),
);

// Get presence messages with specific Connection ID
presenceMessages = await channel.presence.get(
    ably.RestPresenceParams(
        connectionId: 'connectionId',
    ),
);

Read REST presence history

// Get presence history with default parameters
ably.PaginatedResult<ably.PresenceMessage> history = await channel.presence.history();

// Get presence history with custom parameters
ably.PaginatedResult<ably.PresenceMessage> filteredHistory = await channel.presence.history(
    ably.RestHistoryParams(
        direction: 'forwards',
        limit: 10,
    )
);

PaginatedResult handling

Get items on current page

// Example PaginatedResult returned from channel history
ably.PaginatedResult<ably.Message> paginatedResult = await channel.history(params);

// Get list of items from result
List<ably.Message> items = paginatedResult.items;

Get next page if available

// Example PaginatedResult returned from channel history
ably.PaginatedResult<ably.Message> paginatedResult = await channel.history(params);

// Check if next page is available
bool hasNextPage = paginatedResult.hasNext();

// Fetch next page if it's available
if (hasNextPage) {    
  paginatedResult = await paginatedResult.next();
}

Encryption

Create CipherParams

String key = 'base64EncodedKey'; // Can also be an UInt8List
CipherParams cipherParams = ably.Crypto.getDefaultParams(key: key);

Setup encryption on a channel

// For Realtime
RealtimeChannelOptions realtimeChannelOptions = ably.RealtimeChannelOptions(cipherParams: cipherParams);
RealtimeChannel channel = realtime.channels.get("channel-name");
channel.setOptions(realtimeChannelOptions)

// For REST
RestChannelOptions restChannelOptions = ably.RestChannelOptions(cipherParams: cipherParams);
RestChannel channel = rest.channels.get("channel-name");
channel.setOptions(restChannelOptions)

Known limitations

Missing features

Features that we do not currently support, but we do plan to add in the future:

  • Ably token generation (#105)
  • REST and Realtime Stats (#106)
  • Push Notifications Admin (#109)

RTE6a compliance

Using the Streams based approach doesn't fully conform with RTE6a from our client library features specification.

StreamSubscription subscriptionToBeCancelled;

// Listener registered 1st
realtime.connection.on().listen((ably.ConnectionStateChange stateChange) async {
  if (stateChange.event == ably.ConnectionEvent.connected) {
    await subscriptionToBeCancelled.cancel();       // Cancelling 2nd listener
  }
});

// Listener registered 2nd
subscriptionToBeCancelled = realtime.connection.on().listen((ably.ConnectionStateChange stateChange) async {
  print('State changed');
});

In the example above, the 2nd listener is cancelled when the 1st listener is notified about the "connected" event. As per RTE6a, the 2nd listener should also be triggered. It will not be as the 2nd listener was registered after the 1st listener and stream subscription is cancelled immediately after 1st listener is triggered.

This wouldn't have happened if the 2nd listener had been registered before the 1st was.

The Workaround - Cancelling using delay

Instead of await subscriptionToBeCancelled.cancel();, use

Future<void>.delayed(Duration.zero, () {
    subscriptionToBeCancelled.cancel();
});

Push Notifications

By default, push-related components in the sample app won't work on Android, because of a dummy google-services.json file. In order to use push messaging features of Ably SDK, additional FCM/APNS configuration is required.

See PushNotifications.md for detailed information on getting PN working with the example app.

Feature support

See Ably feature support matrix for a list of features supported by this SDK.

Support, feedback and troubleshooting

Please visit ably.com/support for access to our knowledge base and to ask for any assistance.

To see what has changed in recent versions, see the CHANGELOG.

Contributing

For guidance on how to contribute to this project, see CONTRIBUTING.md.

Resources

ably-flutter's People

Contributors

afur avatar andynicks avatar asoap avatar ben-xd avatar davyskiba avatar dependabot[bot] avatar ikbalkaya avatar ikurek avatar jakubjankowski avatar lmars avatar maratal avatar neelansh-ns avatar niksilver avatar owenpearson avatar quintinwillison avatar sacoo7 avatar starction avatar tiholic avatar ttypic avatar umair-ably avatar zoechi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ably-flutter's Issues

Improve our "pub points" score on pub.dev

We're currently [scoring|https://pub.dev/packages/ably_flutter_plugin/score] 40 out of a possible 110.

We're also labelled, perhaps as a result of this score, as "[UNIDENTIFIED]"... which doesn't sound or look too good!

What can we do to improve this?

native dart implementation

Since dart/flutter code supports mobile, web, and desktop natively would be a better choice to write the SDK from scratch and get the advantage of these integrations instead of wrapping existing libraries with their limitations.

Time to market can be slower at the beginning but in the future, the advantages can be huge
You would also gain a strategic advantage over concurrents like AWS amplify which is taking the same (wrong) direction, IMHO.

┆Issue is synchronized with this Jira Task by Unito

Supply Flutter plugin version to Ably services

Came out of a call @paddybyers, @niksilver, kavalerov and I had regarding ably/docs#845.

At the moment the only thing the server can "see" is the identifier presented by the underlying ably-cocoa or ably-java implementation. Ideally we need to present this version as well as the Flutter plugin version, though it may be acceptable to just (somehow) override the presented version to just pass thru the Flutter plugin version - with us then needing to derive the underlying native implementation versions from source code when debugging issues down the line.

Will need to align with or perhaps evolve the client library features specification, in particular RSC7b.

┆Issue is synchronized with this Jira Story by Unito

Logging severity required

There are three places where we emit log messages:

  • Dart code.
  • Objective-C code on iOS runtime.
  • Java code on Android runtime.

In all three of those situations we need the ability to log at a severity level appropriate to the message. Plus, of course, we need to be able to switch those log levels in or out at runtime.

Stabilise integration tests when running on Android

On each run of the Android matrix they're failing on at least one of the API levels.

At the time of writing on the latest push to main here. Also see this comment.

I'm also puzzled, at the time of writing, why the status badge (featured at the top of our readme) states that the flutter_integration workflow is passing

  • which it's clearly not. 🤔

┆Issue is synchronized with this Jira Uncategorised by Unito

Error: MissingPluginException

I am integrating Ably with a flutter app I am building to be able to do live data streaming. Anytime I debug using Microsoft edge or google chrome browser I get this error;

Error: MissingPluginException(No implementation found for method registerAbly on channel io.ably.flutter.plugin)
at Object.throw_ [as throw] (http://localhost:52520/dart_sdk.js:5344:11)
at platform_channel.MethodChannel.new._invokeMethod (http://localhost:52520/packages/flutter/src/services/system_channels.dart.lib.js:962:21)
at _invokeMethod.next ()
at http://localhost:52520/dart_sdk.js:39201:33
at _RootZone.runUnary (http://localhost:52520/dart_sdk.js:39058:58)
at _FutureListener.thenAwait.handleValue (http://localhost:52520/dart_sdk.js:34044:29)
at handleValueCallback (http://localhost:52520/dart_sdk.js:34604:49)
at Function._propagateToListeners (http://localhost:52520/dart_sdk.js:34642:17)
at _Future.new.[_completeWithValue] (http://localhost:52520/dart_sdk.js:34484:23)
at async._AsyncCallbackEntry.new.callback (http://localhost:52520/dart_sdk.js:34507:35)
at Object._microtaskLoop (http://localhost:52520/dart_sdk.js:39345:13)
at _startMicrotaskLoop (http://localhost:52520/dart_sdk.js:39351:13)
at http://localhost:52520/dart_sdk.js:34858:9

┆Issue is synchronized with this Jira Uncategorised by Unito

Ably Flutter - Error building for android: target SDK less than 24

Applications using ably library cannot be built with minSdkVersion version less than 24

See: https://github.com/ably/ably-flutter/blob/main/android/build.gradle#L38

{code}
--redacted/path--/ably_sample/android/app/src/main/AndroidManifest.xml Error:
uses-sdk:minSdkVersion 16 cannot be smaller than version 24 declared in library [:ably_flutter_plugin]
--redacted/path--/ably_sample/build/ably_flutter_plugin/intermediates/library_manifest/release/AndroidManifest.xml as the library might be using APIs not available in 16
Suggestion: use a compatible library with a minSdk of at most 16,
or increase this project's minSdk version to at least 24,
or use tools:overrideLibrary="io.ably.flutter.plugin" to force usage (may lead to runtime failures)

FAILURE: Build failed with an exception.

  • What went wrong:
    Execution failed for task ':app:processReleaseManifest'.

Manifest merger failed : uses-sdk:minSdkVersion 16 cannot be smaller than version 24 declared in library [:ably_flutter_plugin]
--redacted/path--/ably_sample/build/ably_flutter_plugin/intermediates/library_manifest/release/AndroidManifest.xml as the library might be using APIs not available in 16
Suggestion: use a compatible library with a minSdk of at most 16,
or increase this project's minSdk version to at least 24,
or use tools:overrideLibrary="io.ably.flutter.plugin" to force usage (may lead to runtime failures)

{code}
cc: @QuintinWillison @paddybyers @mattheworiordan
ps: This issue to help users getting started with flutter/android

Improvise logging for Channel connection timeout on platform code

Why?

I've been calling Realtime#channels#get#attach without calling Realtime#connect first
This iteratively tries to attach to the channel and on timeout, RealtimeChannelStatus will be set as suspended. I wasn't sure until paddybyers asked me whether I connected to the realtime instance in the first place!

Suggestion

Improvise VERBOSE/INFO logging on timeout and if realtime instance status is not connected to show:

attach timeout, realtime instance is not connected
retrying attach

NOTE: This enhancement must be done on platform code ably-java and ably-cocoa

┆Issue is synchronized with this Jira Task by Unito

ConnectionStateChange#previous is none for the first event from ably-cocoa

When a realtime instance is created, it is supposed to have initialized as connection state so that the first ConnectionChange Event must emit a ConnectionStateChange object with previous attribute set as initialized

This works as expected in Android, but ConnectionStateChange#previous from ios is null

Inconsistent ENUM Ordering between platform SDK's

The enum ordering is inconsistent between ably-java's ChannelEvent and ably-cocoa's ARTChannelEvent (Same applies to ChannelState too)

When it comes to ably-flutter, these enum’s will be encoded from platform side as the ordinal value of these enums (see: encoding in cocoa & encoding in java) and dart side will decode it using ChannelState in dart from the same index. This leads to decoding the values wrongly when it comes to android as dart ordering aligns with cocoa library which is same as mentioned in line 184 in Interface Definition

@QuintinWillison @paddybyers

Unhandled TimeoutException error being thrown occassionally

Hi there, I've been trying to get a chat app working on Android and iOS emulators. It was working fine before but recently, it started throwing an error occasionally on iOS and almost every time on Android:

E/flutter (12888): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: TimeoutException after 0:00:02.000000: Acquiring handle timed out.

I chatted with tiholic on Slack. Following his advice, I updated the platform.dart and platform_object.dart files to have the timeout value of 5 instead of 2. I ran it locally with this change and didn't see any errors anymore, neither on Android nor on iOS. It was all working as expected.

The project in question is publicly available if you'd like to try it out and reproduce the error.

┆Issue is synchronized with this Jira Bug by Unito

Defaults: Generate environment fallbacks

Generic Specification

Per RSC15g, introduced in ably/docs#965.

See ably/ably-js#682 and ably/ably-ruby#196 for reference implementations.

Flutter Specific Notes

Given this client library is a plugin (i.e. delegates most of its work to native implementations), I'm not sure how much work is required to to make this happen as the majority (if not all) of the work to complete this may be required to be completed in the upstream native dependencies via:

┆Issue is synchronized with this Jira Story by Unito

Basic Integration tests

This is a list of basic integration tests that we can enable.

  • 1. AppKey provisionining (from example) - without this other tests cannot be performed
  • 2. Platform Version
  • 3. Library Version
  1. Rest tests

    • a. Able to create Rest instance with client options
    • b. Able to create Rest channel with a name
    • c. Able to publish a message with name and data (both optional) [name=string, data=string|null|Map|List]
    • d. After publishing at-least one message RestInstance handle must have an integer value
  2. Realtime tests

    • a. Able to create Realtime instance with client options
    • b. Able to listen to ConnectionStateChange on Realtime instance
    • c. Able to listen to ConnectionStateChange with filter
    • d. Able to create RealtimeChannel
    • e. Able to listen to ChannelStateChange on Realtime instance
    • f. Able to listen to ChannelStateChange with filter
    • g. Able to listen a message on channel
    • h. Able to listen a message on channel with filtered names
    • i. Able to publish a message with name and data (both optional) [name=string, data=string|null|Map|List] (this published message will be received by above listeners)
    • j. After "publishing at-least one message"/"registering at-least one event listener" RealtimeInstance handle must have an integer value

Add SDK variant to be reported when connecting to Ably

We need to be ably to see in our data how many users are using Flutter sdk, and right now this information is not being reported as Flutter plugin is just a wrapper around native libraries. I believe we are ably to specify variant via public interface on the native SDK level - lets add a flutter specifier there so we can at least start seeing number of Flutter users right now.

This is a short term fix, long term fix will be support for reporting multiple layers of versions ably/docs#1034

┆Issue is synchronized with this Jira Uncategorised by Unito

lib/src/codec.dart could use some rework and tests

getCodecType should be rather _CodecPair getCodec(...) and return a codec instead of returning a number that can used to look up the _CodecPair in a Map?

The way getCodecType is written, it would fail if someone added an entry to codecMap because it would not be covered by the if/else in getCodecType anyway. So codecMap should in my opinion be private, or if getCodecType would be _CodecPair getCodec(...), codecMap would not be required at all.

I'd also try making _CodecPair const.

There are also no tests for this file.

There are probably more issues, but I didn't dig deeper.

┆Issue is synchronized with this Jira Task by Unito

Why do iOS integration tests require delays?

Understand why we need delays while already using await in these scenarios

//TODO(tiholic) iOS fails without this delay

//TODO(tiholic) understand why tests fail without this delay

//TODO(tiholic) iOS fails without this delay

//TODO(tiholic) understand why tests fail without this delay

┆Issue is synchronized with this Jira Task by Unito

Use named arguments for options classes and make all fields private

Python allows kwargs to pass all the possible options to create a ClientOptions object. With flutter, we need to have properties of all such objects (ClientOptions, ChannelOptions, etc) as public and SDK users need to instantiate the class and then set these properties.

So, as per the current implementation:

//usage 1
final options = ClientOptions();
options.environment = 'sandbox';
options.logLevel = LogLevel.verbose;
//usage 2
final options = ClientOptions()
    ..environment = 'sandbox'
    ..logLevel = LogLevel.verbose;

It would be more intuitive to dart developers if we can consider changing the constructors to use named arguments and make all the fields as private.

With the named arguments approach, the usage would be:

final options = ClientOptions(
  environment: 'sandbox',
  logLevel: LogLevel.verbose,
);

Getting error after add this plugin to project

Hello, after add this plugin to .pubspec:

  ably_flutter_plugin:
    git: https://github.com/ably/ably-flutter.git

I am getting errors during build:

Launching lib/main.dart on iPhone 11 in debug mode...
Running pod install...                                              5,5s
Running Xcode build...                                                  
                                                   
 └─Compiling, linking and signing...                         1,8s
Xcode build done.                                           32,4s
Failed to build iOS app
Error output from Xcode build:
↳
    ** BUILD FAILED **


Xcode's output:
↳
    ios/Pods/AblyDeltaCodec/xdelta/xdelta3/xdelta3.c:354:1: warning: unused function
    'xd3_rlist_length' [-Wunused-function]
    XD3_MAKELIST(xd3_rlist, xd3_rinst, link);
    ^
    In file included from ios/Pods/AblyDeltaCodec/xdelta/xdelta3/xdelta3.c:351:
    ios/Pods/AblyDeltaCodec/xdelta/xdelta3/xdelta3-list.h:114:73: note: expanded from
    macro 'XD3_MAKELIST'
    static inline usize_t                                                   \
                                                                            ^
    <scratch space>:25:1: note: expanded from here
    xd3_rlist_length
    ^
    ios/Pods/AblyDeltaCodec/xdelta/xdelta3/xdelta3.c:479:20: warning: unused function
    'xd3_emit_uint32_t' [-Wunused-function]
    static int         xd3_emit_uint32_t (xd3_stream *stream, xd3_output **output,
                       ^
    2 warnings generated.
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:43:53: warning: implicit boolean conversion of Objective-C object literal always evaluates to true [-Wobjc-literal-conversion]
        WRITE_VALUE(dictionary, TxErrorInfo_statusCode, @([e statusCode]));
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:29:9: note: expanded from macro 'WRITE_VALUE'
        if (VALUE) { \
        ~~  ^~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:54:62: warning: implicit boolean conversion of Objective-C object literal always evaluates to true [-Wobjc-literal-conversion]
        WRITE_VALUE(dictionary, TxConnectionStateChange_retryIn, @((int)([stateChange retryIn] * 1000)));
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:29:9: note: expanded from macro 'WRITE_VALUE'
        if (VALUE) { \
        ~~  ^~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:51:61: warning: implicit conversion loses integer precision: 'ARTRealtimeConnectionState' (aka 'enum ARTRealtimeConnectionState')
    to 'int' [-Wshorten-64-to-32]
        WRITE_ENUM(dictionary, TxConnectionStateChange_current, [stateChange current]);
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:36:67: note: expanded from macro 'WRITE_ENUM'
            WRITE_VALUE(DICTIONARY, JSON_KEY, [NSNumber numberWithInt:ENUM_VALUE]); \
                                              ~                       ^~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:29:9: note: expanded from macro 'WRITE_VALUE'
        if (VALUE) { \
            ^~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:51:61: warning: implicit conversion loses integer precision: 'ARTRealtimeConnectionState' (aka 'enum ARTRealtimeConnectionState')
    to 'int' [-Wshorten-64-to-32]
        WRITE_ENUM(dictionary, TxConnectionStateChange_current, [stateChange current]);
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:36:67: note: expanded from macro 'WRITE_ENUM'
            WRITE_VALUE(DICTIONARY, JSON_KEY, [NSNumber numberWithInt:ENUM_VALUE]); \
                                              ~                       ^~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:30:31: note: expanded from macro 'WRITE_VALUE'
            [DICTIONARY setObject:VALUE forKey:JSON_KEY]; \
                                  ^~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:52:62: warning: implicit conversion loses integer precision: 'ARTRealtimeConnectionState' (aka 'enum ARTRealtimeConnectionState')
    to 'int' [-Wshorten-64-to-32]
        WRITE_ENUM(dictionary, TxConnectionStateChange_previous, [stateChange previous]);
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:36:67: note: expanded from macro 'WRITE_ENUM'
            WRITE_VALUE(DICTIONARY, JSON_KEY, [NSNumber numberWithInt:ENUM_VALUE]); \
                                              ~                       ^~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:29:9: note: expanded from macro 'WRITE_VALUE'
        if (VALUE) { \
            ^~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:52:62: warning: implicit conversion loses integer precision: 'ARTRealtimeConnectionState' (aka 'enum ARTRealtimeConnectionState')
    to 'int' [-Wshorten-64-to-32]
        WRITE_ENUM(dictionary, TxConnectionStateChange_previous, [stateChange previous]);
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:36:67: note: expanded from macro 'WRITE_ENUM'
            WRITE_VALUE(DICTIONARY, JSON_KEY, [NSNumber numberWithInt:ENUM_VALUE]); \
                                              ~                       ^~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:30:31: note: expanded from macro 'WRITE_VALUE'
            [DICTIONARY setObject:VALUE forKey:JSON_KEY]; \
                                  ^~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:53:59: warning: implicit conversion loses integer precision: 'ARTRealtimeConnectionEvent' (aka 'enum ARTRealtimeConnectionEvent')
    to 'int' [-Wshorten-64-to-32]
        WRITE_ENUM(dictionary, TxConnectionStateChange_event, [stateChange event]);
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:36:67: note: expanded from macro 'WRITE_ENUM'
            WRITE_VALUE(DICTIONARY, JSON_KEY, [NSNumber numberWithInt:ENUM_VALUE]); \
                                              ~                       ^~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:29:9: note: expanded from macro 'WRITE_VALUE'
        if (VALUE) { \
            ^~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:53:59: warning: implicit conversion loses integer precision: 'ARTRealtimeConnectionEvent' (aka 'enum ARTRealtimeConnectionEvent')
    to 'int' [-Wshorten-64-to-32]
        WRITE_ENUM(dictionary, TxConnectionStateChange_event, [stateChange event]);
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:36:67: note: expanded from macro 'WRITE_ENUM'
            WRITE_VALUE(DICTIONARY, JSON_KEY, [NSNumber numberWithInt:ENUM_VALUE]); \
                                              ~                       ^~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:30:31: note: expanded from macro 'WRITE_VALUE'
            [DICTIONARY setObject:VALUE forKey:JSON_KEY]; \
                                  ^~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:64:59: warning: implicit boolean conversion of Objective-C object literal always evaluates to true [-Wobjc-literal-conversion]
        WRITE_VALUE(dictionary, TxChannelStateChange_resumed, @([stateChange resumed]));
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:29:9: note: expanded from macro 'WRITE_VALUE'
        if (VALUE) { \
        ~~  ^~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:61:58: warning: implicit conversion loses integer precision: 'ARTRealtimeChannelState' (aka 'enum ARTRealtimeChannelState') to
    'int' [-Wshorten-64-to-32]
        WRITE_ENUM(dictionary, TxChannelStateChange_current, [stateChange current]);
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:36:67: note: expanded from macro 'WRITE_ENUM'
            WRITE_VALUE(DICTIONARY, JSON_KEY, [NSNumber numberWithInt:ENUM_VALUE]); \
                                              ~                       ^~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:29:9: note: expanded from macro 'WRITE_VALUE'
        if (VALUE) { \
            ^~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:61:58: warning: implicit conversion loses integer precision: 'ARTRealtimeChannelState' (aka 'enum ARTRealtimeChannelState') to
    'int' [-Wshorten-64-to-32]
        WRITE_ENUM(dictionary, TxChannelStateChange_current, [stateChange current]);
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:36:67: note: expanded from macro 'WRITE_ENUM'
            WRITE_VALUE(DICTIONARY, JSON_KEY, [NSNumber numberWithInt:ENUM_VALUE]); \
                                              ~                       ^~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:30:31: note: expanded from macro 'WRITE_VALUE'
            [DICTIONARY setObject:VALUE forKey:JSON_KEY]; \
                                  ^~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:62:59: warning: implicit conversion loses integer precision: 'ARTRealtimeChannelState' (aka 'enum ARTRealtimeChannelState') to
    'int' [-Wshorten-64-to-32]
        WRITE_ENUM(dictionary, TxChannelStateChange_previous, [stateChange previous]);
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:36:67: note: expanded from macro 'WRITE_ENUM'
            WRITE_VALUE(DICTIONARY, JSON_KEY, [NSNumber numberWithInt:ENUM_VALUE]); \
                                              ~                       ^~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:29:9: note: expanded from macro 'WRITE_VALUE'
        if (VALUE) { \
            ^~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:62:59: warning: implicit conversion loses integer precision: 'ARTRealtimeChannelState' (aka 'enum ARTRealtimeChannelState') to
    'int' [-Wshorten-64-to-32]
        WRITE_ENUM(dictionary, TxChannelStateChange_previous, [stateChange previous]);
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:36:67: note: expanded from macro 'WRITE_ENUM'
            WRITE_VALUE(DICTIONARY, JSON_KEY, [NSNumber numberWithInt:ENUM_VALUE]); \
                                              ~                       ^~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:30:31: note: expanded from macro 'WRITE_VALUE'
            [DICTIONARY setObject:VALUE forKey:JSON_KEY]; \
                                  ^~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:63:56: warning: implicit conversion loses integer precision: 'ARTChannelEvent' (aka 'enum ARTChannelEvent') to 'int'
    [-Wshorten-64-to-32]
        WRITE_ENUM(dictionary, TxChannelStateChange_event, [stateChange event]);
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:36:67: note: expanded from macro 'WRITE_ENUM'
            WRITE_VALUE(DICTIONARY, JSON_KEY, [NSNumber numberWithInt:ENUM_VALUE]); \
                                              ~                       ^~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:29:9: note: expanded from macro 'WRITE_VALUE'
        if (VALUE) { \
            ^~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:63:56: warning: implicit conversion loses integer precision: 'ARTChannelEvent' (aka 'enum ARTChannelEvent') to 'int'
    [-Wshorten-64-to-32]
        WRITE_ENUM(dictionary, TxChannelStateChange_event, [stateChange event]);
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:36:67: note: expanded from macro 'WRITE_ENUM'
            WRITE_VALUE(DICTIONARY, JSON_KEY, [NSNumber numberWithInt:ENUM_VALUE]); \
                                              ~                       ^~~~~~~~~~
    /Users/alexey/Documents/dev/flutter/.pub-cache/git/ably-flutter-0c2f7074b7ffe6abcb5ba0a0a99aed7ab4917bd9/ios/Classes/codec/AblyFlutterWri
    ter.m:30:31: note: expanded from macro 'WRITE_VALUE'
            [DICTIONARY setObject:VALUE forKey:JSON_KEY]; \
                                  ^~~~~
    15 warnings generated.
    3 warnings generated.
    While building module 'ably_flutter_plugin' imported from
    ios/Runner/GeneratedPluginRegistrant.m:8:
    In file included from <module-includes>:1:
    In file included from
    build/ios/Debug-iphonesimulator/ably_flutter_plugin/ably_flutter_plugin.framework/Head
    ers/ably_flutter_plugin-umbrella.h:18:
    build/ios/Debug-iphonesimulator/ably_flutter_plugin/ably_flutter_plugin.framework/Head
    ers/AblyFlutterReader.h:3:9: error: include of non-modular header inside framework module 'ably_flutter_plugin.AblyFlutterReader':
    'build/ios/Debug-iphonesimulator/Ably/Ably.framework/Headers/ARTTokenDetails.h'
    [-Werror,-Wnon-modular-include-in-framework-module]
    #import "ARTTokenDetails.h"
            ^
    While building module 'ably_flutter_plugin' imported from
    ios/Runner/GeneratedPluginRegistrant.m:8:
    In file included from <module-includes>:1:
    In file included from
    build/ios/Debug-iphonesimulator/ably_flutter_plugin/ably_flutter_plugin.framework/Head
    ers/ably_flutter_plugin-umbrella.h:18:
    In file included from
    build/ios/Debug-iphonesimulator/ably_flutter_plugin/ably_flutter_plugin.framework/Head
    ers/AblyFlutterReader.h:3:
    build/ios/Debug-iphonesimulator/Ably/Ably.framework/Headers/ARTTokenDetails.h:18:1:
    error: duplicate interface definition for class 'ARTTokenDetails'
    @interface ARTTokenDetails : NSObject<NSCopying>
    ^
    In module 'Ably' imported from
    build/ios/Debug-iphonesimulator/Ably/Ably.framework/Headers/ARTTokenDetails.h:10:
    build/ios/Debug-iphonesimulator/Ably/Ably.framework/Headers/ARTTokenDetails.h:18:12:
    note: previous definition is here
    @interface ARTTokenDetails : NSObject<NSCopying>
               ^
    While building module 'ably_flutter_plugin' imported from
    ios/Runner/GeneratedPluginRegistrant.m:8:
    In file included from <module-includes>:1:
    In file included from
    build/ios/Debug-iphonesimulator/ably_flutter_plugin/ably_flutter_plugin.framework/Head
    ers/ably_flutter_plugin-umbrella.h:18:
    In file included from
    build/ios/Debug-iphonesimulator/ably_flutter_plugin/ably_flutter_plugin.framework/Head
    ers/AblyFlutterReader.h:3:
    build/ios/Debug-iphonesimulator/Ably/Ably.framework/Headers/ARTTokenDetails.h:23:49:
    error: property has a previous declaration
    @property (nonatomic, readonly, copy) NSString *token;
                                                    ^
    In module 'Ably' imported from
    build/ios/Debug-iphonesimulator/Ably/Ably.framework/Headers/ARTTokenDetails.h:10:
    build/ios/Debug-iphonesimulator/Ably/Ably.framework/Headers/ARTTokenDetails.h:23:49:
    note: property declared here
    @property (nonatomic, readonly, copy) NSString *token;
                                                    ^
    While building module 'ably_flutter_plugin' imported from
    ios/Runner/GeneratedPluginRegistrant.m:8:
    In file included from <module-includes>:1:
    In file included from
    build/ios/Debug-iphonesimulator/ably_flutter_plugin/ably_flutter_plugin.framework/Head
    ers/ably_flutter_plugin-umbrella.h:18:
    In file included from
    build/ios/Debug-iphonesimulator/ably_flutter_plugin/ably_flutter_plugin.framework/Head
    ers/AblyFlutterReader.h:3:
    build/ios/Debug-iphonesimulator/Ably/Ably.framework/Headers/ARTTokenDetails.h:28:59:
    error: property has a previous declaration
    @property (nonatomic, readonly, strong, nullable) NSDate *expires;
                                                              ^
    In module 'Ably' imported from
    build/ios/Debug-iphonesimulator/Ably/Ably.framework/Headers/ARTTokenDetails.h:10:
    build/ios/Debug-iphonesimulator/Ably/Ably.framework/Headers/ARTTokenDetails.h:28:59:
    note: property declared here
    @property (nonatomic, readonly, strong, nullable) NSDate *expires;
                                                              ^
    While building module 'ably_flutter_plugin' imported from
    ios/Runner/GeneratedPluginRegistrant.m:8:
    In file included from <module-includes>:1:
    In file included from
    build/ios/Debug-iphonesimulator/ably_flutter_plugin/ably_flutter_plugin.framework/Head
    ers/ably_flutter_plugin-umbrella.h:18:
    In file included from
    build/ios/Debug-iphonesimulator/ably_flutter_plugin/ably_flutter_plugin.framework/Head
    ers/AblyFlutterReader.h:3:
    build/ios/Debug-iphonesimulator/Ably/Ably.framework/Headers/ARTTokenDetails.h:33:59:
    error: property has a previous declaration
    @property (nonatomic, readonly, strong, nullable) NSDate *issued;
                                                              ^
    In module 'Ably' imported from
    build/ios/Debug-iphonesimulator/Ably/Ably.framework/Headers/ARTTokenDetails.h:10:
    build/ios/Debug-iphonesimulator/Ably/Ably.framework/Headers/ARTTokenDetails.h:33:59:
    note: property declared here
    @property (nonatomic, readonly, strong, nullable) NSDate *issued;
                                                              ^
    While building module 'ably_flutter_plugin' imported from
    ios/Runner/GeneratedPluginRegistrant.m:8:
    In file included from <module-includes>:1:
    In file included from
    build/ios/Debug-iphonesimulator/ably_flutter_plugin/ably_flutter_plugin.framework/Head
    ers/ably_flutter_plugin-umbrella.h:18:
    In file included from
    build/ios/Debug-iphonesimulator/ably_flutter_plugin/ably_flutter_plugin.framework/Head
    ers/AblyFlutterReader.h:3:
    build/ios/Debug-iphonesimulator/Ably/Ably.framework/Headers/ARTTokenDetails.h:38:59:
    error: property has a previous declaration
    @property (nonatomic, readonly, copy, nullable) NSString *capability;
                                                              ^
    In module 'Ably' imported from
    build/ios/Debug-iphonesimulator/Ably/Ably.framework/Headers/ARTTokenDetails.h:10:
    build/ios/Debug-iphonesimulator/Ably/Ably.framework/Headers/ARTTokenDetails.h:38:59:
    note: property declared here
    @property (nonatomic, readonly, copy, nullable) NSString *capability;
                                                              ^
    While building module 'ably_flutter_plugin' imported from
    ios/Runner/GeneratedPluginRegistrant.m:8:
    In file included from <module-includes>:1:
    In file included from
    build/ios/Debug-iphonesimulator/ably_flutter_plugin/ably_flutter_plugin.framework/Head
    ers/ably_flutter_plugin-umbrella.h:18:
    In file included from
    build/ios/Debug-iphonesimulator/ably_flutter_plugin/ably_flutter_plugin.framework/Head
    ers/AblyFlutterReader.h:3:
    build/ios/Debug-iphonesimulator/Ably/Ably.framework/Headers/ARTTokenDetails.h:43:59:
    error: property has a previous declaration
    @property (nonatomic, readonly, copy, nullable) NSString *clientId;
                                                              ^
    In module 'Ably' imported from
    build/ios/Debug-iphonesimulator/Ably/Ably.framework/Headers/ARTTokenDetails.h:10:
    build/ios/Debug-iphonesimulator/Ably/Ably.framework/Headers/ARTTokenDetails.h:43:59:
    note: property declared here
    @property (nonatomic, readonly, copy, nullable) NSString *clientId;
                                                              ^
    While building module 'ably_flutter_plugin' imported from
    ios/Runner/GeneratedPluginRegistrant.m:8:
    In file included from <module-includes>:1:
    In file included from
    build/ios/Debug-iphonesimulator/ably_flutter_plugin/ably_flutter_plugin.framework/Head
    ers/ably_flutter_plugin-umbrella.h:18:
    In file included from
    build/ios/Debug-iphonesimulator/ably_flutter_plugin/ably_flutter_plugin.framework/Head
    ers/AblyFlutterReader.h:3:
    build/ios/Debug-iphonesimulator/Ably/Ably.framework/Headers/ARTTokenDetails.h:53:12:
    error: definition of 'ARTTokenDetails' must be imported from module 'Ably.ARTTokenDetails' before it is required
    @interface ARTTokenDetails (ARTTokenDetailsCompatible) <ARTTokenDetailsCompatible>
               ^
    In module 'Ably' imported from
    build/ios/Debug-iphonesimulator/Ably/Ably.framework/Headers/ARTTokenDetails.h:10:
    build/ios/Debug-iphonesimulator/Ably/Ably.framework/Headers/ARTTokenDetails.h:18:12:
    note: previous definition is here
    @interface ARTTokenDetails : NSObject<NSCopying>
               ^
    While building module 'ably_flutter_plugin' imported from
    ios/Runner/GeneratedPluginRegistrant.m:8:
    In file included from <module-includes>:1:
    In file included from
    build/ios/Debug-iphonesimulator/ably_flutter_plugin/ably_flutter_plugin.framework/Head
    ers/ably_flutter_plugin-umbrella.h:18:
    In file included from
    build/ios/Debug-iphonesimulator/ably_flutter_plugin/ably_flutter_plugin.framework/Head
    ers/AblyFlutterReader.h:3:
    build/ios/Debug-iphonesimulator/Ably/Ably.framework/Headers/ARTTokenDetails.h:53:29:
    warning: duplicate definition of category 'ARTTokenDetailsCompatible' on interface 'ARTTokenDetails'
    @interface ARTTokenDetails (ARTTokenDetailsCompatible) <ARTTokenDetailsCompatible>
                                ^
    In module 'Ably' imported from
    build/ios/Debug-iphonesimulator/Ably/Ably.framework/Headers/ARTTokenDetails.h:10:
    build/ios/Debug-iphonesimulator/Ably/Ably.framework/Headers/ARTTokenDetails.h:53:12:
    note: previous definition is here
    @interface ARTTokenDetails (ARTTokenDetailsCompatible) <ARTTokenDetailsCompatible>
               ^
    1 warning and 8 errors generated.
    ios/Runner/GeneratedPluginRegistrant.m:8:9: fatal error: could not build module
    'ably_flutter_plugin'
    #import <ably_flutter_plugin/AblyFlutterPlugin.h>
     ~~~~~~~^
    1 warning and 9 errors generated.

What am I doing wrong?

ably-java authCallback flow expects synchronous response

According to [ably-java source|https://github.com/ably/ably-java/blob/main/lib/src/main/java/io/ably/lib/rest/Auth.java#L581], authCallback expects a response as a {{String}} or {{TokenDetails}} or {{TokenRequest}}.

Java code can call MethodChannel api to flutter side, but only asynchronously using a {{MethodChannel.Response}} callback. See: {{io.flutter.plugin.common.MethodChannel}} in https://api.flutter.dev/javadoc/

Unsupported properties by dependencies

Following properties are not supported on ably-java / ably-cocoa

ably-cocoa

Unsupported properties

ARTClientOptions
  • useTokenAuth: TO3j4 - boolean – When true, token authentication will always be used by the client
  • port: TO3k4 - integer – for development environments only; allows a non-default Ably non-TLS port to be specified
  • tlsPort: TO3k5 - integer – for development environments only; allows a non-default Ably TLS port to be specified
  • httpOpenTimeout: TO3l3 - integer – default 4,000 (4s). Timeout for opening the connection, available in the client library if supported by the transport
  • httpRequestTimeout: TO3l4 - integer – default 10,000 (10s). Timeout for any single HTTP request and response
  • httpMaxRetryCount: TO3l5 - integer – default 4,000 (4s). Timeout for opening the connection, available in the client library if supported by the transport
  • realtimeRequestTimeout
  • fallbackRetryTimeout
  • channelRetryTimeout
  • transportParams: will be added under ably/ably-cocoa#1112
  • asyncHttpThreadpoolSize
  • pushFullWait
ARTErrorInfo
  • code: TI1 - Ably code, not the same as statusCode
  • href: TI4 - optional, included in REST responses
  • requestId: TI1, RSC7c - via addRequestIds client option (TO3p)
  • cause: TI1 - optional, an inner ARTErrorInfo instance

ably-java

Unsupported properties

ErrorInfo
  • requestId
  • cause
Auth.TokenParams
  • nonce
PresenceMessage
  • extras
ChannelOptions
  • modes
    (an extra parameter encrypted is supported instead whose documentation is missing from docs.ably.io)

Unsupported APIs

Rest#Channels#Channel
  • Rest#setChannelOptions

this list will be updated with new findings

┆Issue is synchronized with this Jira Task by Unito

Should we implement EventEmitter?

Current implementation of event streams using "flutter streams channel" plugin which will create an instance of Event Channel on platform side.

This discussion sheds some light on different approaches that can be followed to implement the same along with caveats of each approach.

install via pub.dev ?

hi all, we're very keen to use Ably in our Flutter app. are you able to put this package onto pub.dev ? if not can you give me info on how to install into an existing Flutter app ?

Enum for direction

direction string used in RestHistoryParams and similar query filter param classes can be an enum which can be encoded to a string while passing on to platform side.

┆Issue is synchronized with this Jira Task by Unito

typed Message#data

Currently the property data in Message (Rest/Realtime publishable message) is of type Object, which could allow users to pass int, double, bool and other primitive types (as per OOP) which are not supported to be sent over the wire as per Ably SDK.

A fail fast approach would be to have data as Union type (not supported by dart yet, but probably soon dart-lang/language#546) or have an interface that could take allow only allowed types as different named arguments which would be a deviation from spec.

Message(data: MessageData(map: {}))
Message(data: MessageData(list: []))
Message(data: MessageData(str: "message-data"))

See this thread for discussion #21 (comment)

Presence subscription example

Hi guys, I have been using the SDK for a while. First off all I want to thank you thant you made and keep making great job here and I didn't face with any warnings or errors yet.

However when I tried to use Presence I didn't made that happen bcs the methods and parameters are not similar with doc in ably website.
So can you please help me with that?

zoechi tiholic QuintinWillison

┆Issue is synchronized with this Jira Story by Unito

push notification

Hi,
is push notification supported?
is there documentation to follow in order to integrate FCM and APN ?

thanks

┆Issue is synchronized with this Jira Story by Unito

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.