Layer FAQs | Comparably
Layer Claimed Company
Layer is the open communications layer for the Internet. We make it easy for developers to add rich messaging, voice and video to any app. read more
EMPLOYEE
PARTICIPANTS
8
TOTAL
RATINGS
55

Layer FAQs

Layer's Frequently Asked Questions page is a central hub where its customers can always go to with their most common questions. These are the 123 most popular questions Layer receives.

Frequently Asked Questions About Layer

  • Here are some troubleshooting tips:

    If you create a conversationthe recipient won't see it until the first message is sent. If you want to be able to create a conversation without any messages, use the Platform API.

    Take a look at Logs in the Dashboard. Logscan also tell you if a message was sent. If you've got multiple dashboard logins within the same company make surethe app ID being used in the app and the app id in the dashboard are the same.

    Make sure you're connected to Layer. It's possible to be authenticated but not connected (for example: if the device isin airplane mode). Make sure you always connectWithCompletion (on iOS) or connect (on Android) as soon as possible, preferably on app launch. Both iOS and Android SDK's have a isConnected flag you can check. NOTE: You are able to create conversations and send messages without actually being connected. Those conversations and messages will get queued up but won't be sent untilyou're connected.If you're sending messages but nothing is showing up in the Dashboard Logs it could mean you're not connected.

    Make sure all the participant names in the conversation are correct and match up.For example:If your internal user id's have a prefix of"USER_" (such as USER_123) make sure the participant name/authenticated user id contain the same prefix. If one of the participant names is 123, but you're logged in as USER_123 that user won't see any messages.

    Make sure that the participant is actually in the conversation, and hasn't been removed or blocked. Users only have access to conversations they are participants of.

    When debugging, it's very helpful to listen to Layer Change Notifications ( iOS docs / Android docs ). They will let you know on both the sender and receiver side if a conversation and message was created/updated/deleted,participants were added/removed, and more. If you are receiving change notifications but nothing is changing in the UI you probably have a UI bug.

    View Article
  • In order to send a message, you must first have an authenticated Layer application. After authenticating, it is only a few lines of code to send a message.

    // Creates and returns a new conversation object with a single participant represented by your backend's user identifier for the participant

    LYRConversation *conversation = [LYRClient newConversationWithParticipants:[NSSet setWithArray:@[@"USER-IDENTIFIER"]]];

    LYRMessagePart *part = [LYRMessagePart messagePartWithText:@"Hi, how are you?"];

    // Creates and returns a new message object with the given conversation and array of message parts

    LYRMessage *message = [self.layerClient newMessageWithParts:@[part] options:nil error:nil];

    // Sends the specified message

    [conversation sendMessage:message error:&error];

    View Article
  • This will typically happen there is a mismatch between your app id, key id, and provider ID. Make sure the app id used in the XCode matches the provider ID and key ID in your auth server.

    View Article
  • Layer SDK v0.11.0 Transition Guide

    Breaking API Changes

    This version of LayerKit includes a substantial change to Message ordering in order to enhance performance. Previous version of LayerKit utilized a property named `index`, which was a monotonically increasing integer equal to the number of Messages that have been synchronized. From v0.11.0, the Layer SDK now maintains a new property named `position`. The `position` of a Message is a value that is calculated immediately when the Message is synchronized and never changes. This greatly improves performance reduces the overhead associated with syncing large amounts of Message content.

    Layer SDK v0.10.0 Transition Guide

    Key API Changes

    If you are upgrading from SDK version 0.8.20 or older, there are some architectural changes you need to take into account. Creating a Conversation, Message, and MessagePart are now created with a LayerClient object, and sending a message is done with the Conversation itself:

    //There is no change in how the LayerClient is instantiated

    LayerClient client = LayerClient.newInstance(Context context, String App_ID, String GCM_Project_Number);

    //MessagePart.newInstance(text) becomes

    MessagePart part = client.newMessagePart(text);

    //Message.newInstance(conversation, parts) is created with the client, and does not require

    // a conversation object

    Message message = client.newMessage(parts);

    //Conversation.newInstance(participants) becomes

    Conversation conversation = client.newConversation(participants);

    //The conversation sends the message istself, so layerClient.sendMessage(message) becomes

    conversation.send(message);

    Changes to the Message object

    Several methods that used to exist on the LayerClient object have been moved to the Message object. Marking messages as read, deleting messages, and other functionality can now be performed directly on the message object.

    //layerClient.markMessageAsRead(message) becomes

    message.markAsRead();

    //layerClient.deleteMessage(message, deletionMode) becomes

    message.delete(deletionMode);

    //When creating push notifications, layerClient.setMetadata(message, metadata) becomes

    message.setMetadata(metadata);

    Changes to the Conversation object

    The Conversation object can now manage its own metadata, participant list, and typing indicators.

    //layerClient.addParticipants(conversation, participantList) becomes

    conversation.addParticipants(participantList);

    //layerClient.removeParticipants(conversation, participantList) becomes

    conversation.removeParticpants(participantList);

    //layerClient.putMetadata(conversation, metadata, doMerge) becomes

    conversation.putMetadata(metadata, doMerge);

    //layerClient.sendTypingIndicator(activeConversation, TypingIndicator.STARTED) becomes

    conversation.send(TypingIndicator.STARTED);

    //layerClient.getUnreadMessageCount(conversation) will need to be replaced by a query

    public int getUnreadMessageCount(Conversation conversation){

    Query query = Query.builder(Message.class)

    .predicate(new CompoundPredicate(CompoundPredicate.Type.AND,

    new Predicate(Message.Property.CONVERSATION, Predicate.Operator.EQUAL_TO, conversation),

    new Predicate(Message.Property.IS_UNREAD, Predicate.Operator.EQUAL_TO, true)))

    .sortDescriptor(new SortDescriptor(Message.Property.SENT_AT, SortDescriptor.Order.DESCENDING))

    .build();

    List<Message> results = layerClient.executeQuery(query, Query.ResultType.OBJECTS);

    if(results == null)

    return 0;

    return results.size();

    }

    Querying

    One of the biggest changes to SDK version 0.9.+ is Querying. Queries can be executed on a variety of message and conversation properties, and the results can be sorted based on specific fields, allowing for a variety of UI configurations. To learn more about Querying, start with this guide.

    View Article
  • Support Levels

    Layer offers 3 different levels of support to meet various customer needs: Standard, Professional, and Enterprise.

    Standard

    Professional

    Enterprise

    Full developer documentation and self-support help center

    24/7 monitoring for system stability and uptime

    Ticket support channel during business hours

    Guaranteed response times for support tickets

    Priority handling for support tickets

    Private communication channel with Customer Success team

    Onboarding and integration workshops, with optional on-site

    Elevated go-live support

    Quarterly integration reviews

    Ticket Priorities

    Before submitting a ticket, first check our status page and search our documentation for potential answers. If neither of these provide the information you're looking for, please submit a ticket describing what is happening with relevant technical details, and assign a priority level that accurately reflects the impact this is having.

    Priority level

    Urgent: Core use cases are prevented fromsucceeding for >10% of users with no available workaround.

    High: There is a significant impact on common use cases reducing quality of service for >2% of users with no available workaround.

    Normal: There is an impact on common use cases reducing quality of service for some users with a workaround available.

    Low: General questions and all other situations.

    Response times

    Enterprise support

    Professional support

    Standard support

    Urgent

    Within 2 business hours

    Within 1 business day

    As soon as possible

    High

    Within 4 business hours

    Within 1 business day

    As soon as possible

    Normal

    Within 1 business day

    Within 2 business days

    As soon as possible

    Low

    Within 2 business days

    As soon as possible

    As soon as possible

    Support Hours

    Layer has engineers around the world monitoring our system 24/7/365 for stability and uptime, and any platform-related incidents will be responded to without delay.

    For application and integration support, we have the following business hours:

    9:00am - 5:00pm PST

    Monday - Friday, excluding major U.S. holidays

    View Article
  • Communications are incredibly complicated to implement in-house. Not only do users expect to be able to send messages back and forth in near-realtime with low latency, modern chat clients must incorporate syncing across devices, read receipts, typing indicators, group conversations, file transfer, and much more. Creating so many features from the ground up is expensive and difficult. Layer provides a solution to this challenge, freeing you to focus on creating content to delight your users and scale your product forward without the overhead of maintaining messaging infrastructure.

    View Article
  • Layer retains data based on a policy configurable at the account level. By default, all data is retained and able to be synchronized for the life of the application in which it resides. Upon termination of an account, Layer will retain data for 90 days before expunging it from the system. Operational logs may contain historical references and activity but end user content is never exposed.

    View Article
  • For technical products we recommend starring any relevant public Github repositories to receive email updates about any code changes and version updates. For company, features, and article updates we will send out periodic newsletters to all customer emails that have registered an account on www.layer.com.

    View Article
  • Layer offers almost unparalleled customization and freedom within our system. Unlimited messages, conversations, and users, no restrictions on the type of data sent, and no cap on the amount of rich content stored with us. However, Layer does currently impose a single important limitation on our messaging service:

    Layer conversations can have a maximum of 25 participants, however, we have a Channel object available on web that supports up to 250 participants. There are no short-term plans to support this on Android or iOS.

    View Article
  • Absolutely! Layer offers full-featured UI libraries for Android, iOS, and Web that easily expose all the powerful capabilities of the underlying data and synchronization engines. These UI libraries come standard with highly customizable components that can be matched to your existing branding and look and feel of your products.

    View Article
  • Yes! Layer provides a full stack for communications, while you retain complete control over everything else in your product including user management. Layer integrates easily with any type of backend technology, including cloud backend services such as Azure, AWS, GCS, and Heroku.

    View Article
  • Layer powers rich, native (in-app) messaging as well as desktop and mobile web experiences. This is different from SMS-type messaging that involves your phone number. How this actually manifests itself in your product is up to you. The Layer SDK allows you to send any type of payload including text, photo, voice recording, video recording, location data and game metadata, just to name a few. A few sample use cases include:

    Basic Messaging

    Group Messaging

    Photo Messaging

    Ephemeral Messaging

    Location Sharing

    View Article
  • Layer offers a full suite of Server APIs to allow system-level access to your app's content and actions.

    View Article
  • Yes, you can delete a user Identity from Layer using our Server API and, in fact, we have a robust set of APIs for user management.Deleting an identity that is referenced by a pre-existing conversation or message has no impact on those entities.

    View Article
  • You can refer to our Troubleshooting and Integration Checklist in our Android documentation.

    View Article
  • Staging and Production are very similar environments. Staging is not capped by performance, number of users, or messages. Staging apps can also send and receive push notifications provided development credentials have been uploaded to the dashboard.

    However, there is 1 important difference between Staging and Production: user sessions on Staging only last for 5 minutes.After 5 minutes, the user will be de-authenticated and won't be able to send/receive messages. You will be issued an authentication challenge when the user is de-authenticated, and you can then re-authenticate the user.

    We recommend that you do all your testing on Staging.

    Note: While the Staging and Production app ID's look very similar they are actually different GUIDs. The "staging" and "production" prefixes are only used for developers to quickly identify their appIDs.

    View Article
  • Follow the instructions in Multiple FCM senders in the same app in the Android docs.

    View Article
  • Layer implements a federated authentication flow, which means that its up to you to verify user login credentials, and then tell Layer that the user should be authenticated. This means that you must provide a custom service to verify user credentials. We do not provide this functionality.

    At a high level, there are three main steps in the authentication flow:

    You request anoncefrom Layer, which is a unique string used to identify a single authentication request.

    Your authentication provider uses this nonce and your user's login credentials to generate and sign anidentity token, then sends it back to your app.

    Your app sends this identity token to Layer and we authenticate that user into our system.

    For complete authentication and identity token information, please see our Authentication documentation ( Android, iOS, Web ).

    View Article
  • For everymessage in a conversation, the sender will receive delivery and read receipts from all theother participants in that conversation which will set specific flags on that message. These receipts canincreasethe size of the conversation, which can have an impact on sync and UI performance.

    For example, in a conversation with two participants, when one user sends a message, the other participant will send one delivery receipt and one read receipt, a 1:2 ratio. But in a conversation with five users, when one user sends a message, there will be 4 delivery and 4 read receipts, a 1:8 ratio.

    For conversations with over5 participants, Layer recommends disabling delivery receipts which will speed up syncing and improve overall performance. Disabling these receiptscan only be done when a conversation is initialized in code.

    Android

    Conversation conversation = Conversation.newInstance(new ConversationOptions().deliveryReceipts(false), participants);

    iOS

    BOOL deliveryReceiptsEnabled = false;NSError *error = nil;LYRConversation *conversation = [layerClient newConversationWithParticipants:participants options:@{LYRConversationOptionsDeliveryReceiptsEnabledKey: @(deliveryReceiptsEnabled) } error:&error];

    View Article
  • To assist in setting up a backend, Layer provides sample backend implementations for the following languages:

    Node

    Go

    Ruby

    Python

    Scala

    Java

    PHP

    View Article
  • Absolutely. Layer iOS products willwork with Swift today, and there are Swift apps in Production using Layer.

    Getting Started

    To get started, add the following to your SwiftBridgeHeader file:

    @import LayerKit;

    Please Note: Sincethe Swift language and the tools supporting it are constantly evolving you may run into challenges with integration. If you have tips you'd like to share about Swift or if you run into issues using Swift, let us know.

    View Article
  • Block is a user Policy that defines how two users on the system are able to interact. The unidirectional action of blocking a user results in the blockee losing certain privileges in relation to the blocker.

    Frequently Asked Questions:

    1. Who can perform a block action?

    Any user can elect to block any other user, and it affects both users' ability to see or message one another (see #4).

    2. Who should be explicitly aware of a block?

    Only the blocker, explicitly. Although the blockee may be able to interpret that they are blocked from cues (see #3 -- if messages never get delivered or a group conversation cannot be created with that participant)

    3. Can a user unblock?

    Yes, a block is a fundamentally reversible action. We allow a user to manage their own block list, both adding and removing people from this list. When a user unblocks, it is acceptable for the history of messages sent during the block period to be synchronized to a new device or upon cold synchronization.

    4. What information or actions are blocked? *

    Message delivery

    Receipts and message state

    Conversation creation

    if a group conversation is created with the blocker in the participant list, they are filtered out upon conversation creation

    Add participant

    if a blocker tries to add blockee to a conversation, she will get an error

    Actions still permitted:

    Remove participant

    Sync historical messages

    Delete conversation

    * All of these are blocked bidirectionally. Block is an inherently unidirectional action (A blocks B), yet some actions should be unpermitted in a two-way fashion. Actions like sending a message to a blocked contact should not be permitted by either party after the blocker has elected to block.

    5. Do the unpermitted actions fail silently or have an error?

    These actions should fail silently to the blocked user.

    6. How does blocking work in group chats or channels?

    In short, the users will be aware that each other is in the participant list, but no messages from that user will be visible. Either user can remove themself from the conversation.

    E.g. If a user Carol adds two participants to a group conversation, Alice and Bob, and Alice has blocked Bob (Carol has not blocked anyone, and is not aware of any blocking), both Alice and Bob will be added to Carol's conversation. Alice and Bob will be aware of each other as participants in the conversation (participant list), although neither will be able to see the messages of the other user. If Alice and Carol are conversing, Bob will only see Carol's side of the conversation; likewise if Bob and Carol are conversing, Alice will only see Carol's side of the conversation.

    View Article
  • The current Atlas Messenger projects for iOS and Android are designed to only work with a special "Atlas Messenger" project. Atlas Messengeruses a Layer identity server and token provider designed to only be used with this project. To create this special App ID you must go to the Atlas build page. If you use a different App ID you will see a "Request failed: forbidden" or "404" error when you try to authenticate.

    View Article
  • A monthly authenticated user (MAUTH) is a unique user who has authenticated and established a session with Layerduring the calendar month.

    Once a user is authenticated and establishes a session with Layer, it doesnt matter how long they stay logged in, or how many messages they send,they'reonly counted once per month.

    View Article
  • If you are having trouble with Push, the first place you should check is the Logs in the dashboard. It will show you if a device was properly registered for pushes and if/when a push was successfully sent:

    SimulatorRemoteNotifications

    Here are a fewreasons why you might not be receiving push notifications on iOS.

    1.Your app ID is incorrect

    Make sure the app ID you've uploaded your p12 filein the dashboardmatches the one in you XCode project. If you switch to the production, you will need to change the app id in XCode and re-upload your push certs.

    2. The certificate is invalid

    To test your push certificate, we recommend using a third party tool like Houston or APNS Tester to send pushes to the device. If the pushes don't work with the third party then you'll need to re-create your certs.

    Here's an example of a push using Houston:

    apn push "<5e8f5cc0 be283f88 cc4ebb7d b6091499 80f51631 5ebf4928 b59a2a62 198d20d0>" -c -out "apple_push_notification.pem" -m "Hello from the command line!"

    We recommend that you upload development cert, production, and any ad-hoc certs. Layer will automatically determinewhich cert touse.

    NOTE: If you switch from using a Layer Staging ID to a Layer Production ID you will need to re-upload all your certs.

    3. Your device is not correctly registered for push notifications

    Here are 2 common mistakes people make in theircode:1. Make sure you are registering for Push Notifications on app launch. This can be done by placing this code inside didFinishLaunchingWithOptions:

    // Checking if app is running iOS 8

    if ([application respondsToSelector:@selector(registerForRemoteNotifications)]) {

    // Register device for iOS8

    UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];

    [application registerUserNotificationSettings:notificationSettings];

    [application registerForRemoteNotifications];

    } else {

    // Register device for iOS7

    [application registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeBadge];

    }

    2. Make sure you are correctly calling [layerClient updateRemoteNotificationDeviceToken...]

    We recommend calling inside didRegisterForRemoteNotificationsWithDeviceToken to send Layer the device token. Without the device token we don't know which device to send pushes to.If the third party tool above works but Layer push does not work then the cause is mostly likely related to device tokens not being sent to Layer.

    For more information about push integration, check out our Push Integration docs.

    TIP: You can also check to see if the app is failing to register by implementing didFailToRegisterForRemoteNotificationsWithError. If you look at the error you should be able to figure out why you're not seeing pushes.

    - (void) application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error

    {

    NSLog(@"PUSH ERROR: %@", error);

    }

    TIP #2:The updateRemoteNotificationDeviceToken will only work if you're connected to Layer. So if you're calling `updateRemoteNotificationDeviceToken` but you're not seeing a message "Push: registered apns device..." in the logs you are probably not connected to Layer. The easiest way to fix this is to move the connectWithCompletion call to inside `didFinishLaunchingWithOptions`.If the clientisn'tauthenticated wewon'tpush up the token, but we will still store it. When the client authenticates and starts messaging services then the Layer SDK pushes the stored token up again.

    4.There's a problem with your provisioning profile or your XCode projectis using the wrong profile/certificate.

    Here are 2 common mistakes people make in their XCode projects:

    1.Make sure your provisioning profiles are up-to-date. The device info is store in the certificates so any time you add a new device to the profile you will need to re-create the profile and certificates.

    2. Make sure that your XCode Project Settings is pointing the correct Certificate and Provisioning profile:

    For more information about Apple's push notification steps, check out our Push Notification docs.

    5. You're not setting LYRMessageOptionsPushNotificationAlertKey when sending the message

    You configure what you want the push text to be when you send a message by seeing theLYRMessagePushNotificationAlertMessageKey option. Here's example code:

    NSString *messageText = @"Hi how are you?"

    LYRMessagePart *part = [LYRMessagePart messagePartWithText:messageText];

    // Configure the push notification text to be the same as the message text

    LYRMessage *message = [layerClient newMessageWithParts:@[part] options:@{LYRMessagePushNotificationAlertMessageKey: messageText} error:nil];

    6. Your .p12 is missing the certificate or the key

    When inside the Keychain Access app make sure you are exporting the key and the certificate:

    7. You are using silent notifications and the phone is unplugged

    We currently recommend that developers do not rely on silent notifications. Weve done extensive testing on silent notifications internally with various combinations of sound, alert, and content-available flags and the net outcome is that there is no way to guarantee that iOS will wake the app up in response to a push notification. We believe this is because of how iOS handles power management. For example: if you plug the device into a power source it will get woken up on every push. When its not plugged in we've perceived that whether or not the app will be awakened is unpredictable.

    If you want reliable, immediate delivery of push notifications we recommend utilizing the LYRMessagePushNotificationAlertMessageKey option to set Alert text and to use the "Show unread in badges" feature in the dashboard. If you try to use silent notifications and emit local notifications then you will always be subject to latency and a variable amount of batching. Unfortunately, the behavior is out of our control at this time.

    If pushes worked and then you stopped receiving pushes but haven't made any changes on your end, please check our Status page for any outages. If nothing is listed, please submit a support request.

    8. You are using TestFlight to distribute builds but you haven't uploaded Production Push Certs to Layer.

    TestFlight builds act similar to production builds, and they do not work with development push certificates. You need to create a App Store Distribution profile and Production Push Cert in the Apple Developer Portal for TestFlight AND you must upload them to Layer (Both Layer Staging and Production app id's do accept Apple Production Push certs).

    ---

    NOTE: The simulator is incapable of receiving push notifications. You can send mock playloads to a simulator using for testing purposes.

    View Article
  • Yes, participant lists for Layer conversations are mutable, meaning that your application can add or remove participants at will. The Layer service does not enforce any ownership over conversations.

    View Article
  • LayerChangeEventListener is an interface that can ideally be implemented on a view. Once one of the static methods, onEventMainThread or onEventAsync, are implemented, you will then need to register the LayerChangeEventListener on the LayerClient as such:

    layerClient.registerEventListener(this);

    Here's an example implementation of onEventMainThread:

    public void onEventMainThread(LayerChangeEvent event) { List changes = event.getChanges(); for (LayerChange change: changes) { switch (change.getChangeType()) { case INSERT: // Object was created System.out.println("Object was created."); break; case UPDATE: // Object was update System.out.println("Object was updated."); break; case DELETE: // Object was deleted System.out.println("Object was deleted."); break; } break; }}

    View Article
  • This guide has been deprecated, and currently only applies to customers grandfathered into our 2015 pricing plans.

    The current support levels are described here

    All foursupport options provide access to our knowledge base and ticketing system. In addition:

    Basic support provides limited email support during business hours.

    Standard support provides email support during business hours with an eight hour guaranteed first response time, plus our Standard SLA.

    Premiumsupport providesemail and video call support during business hours with an eight hour guaranteed response time, plus a four hour guaranteed response time for live operations issues, a named Account Manager, and our Standard SLA. Tickets are handled via our Premiumticketing queue. Pre-launch review upon request and ongoing best practice updates included.

    Enterprise support provides email, video call, and dedicated live chatsupport 24/7 with a four hour guaranteed response time, plus a two hour guaranteed response time for live operations issues, a namedAccount Manager, and our Enterprise SLA. Tickets are handled via our Enterprise ticketing queue. Pre-launch review, ongoing reviews, and ongoing best practice updates included.

    View Article
  • Yes, Layer is HIPAA-compliant.

    For full HIPAAcompliance, a company like Layer would be a Business Associate and is subject to the 4 rules described here. These are the HIPAA Privacy Rule, the HIPAA Security Rule, the HIPAA Enforcement Rule, and the HIPAA Breach Notification Rule.

    Of these 4 rules, the HIPAA Security Rule covers technical, physical and administrative safeguards for confidentiality, integrity, and security of protected health information (PHI). The other 3 rules refer to company processes and procedures.

    At Layer, we have implemented privacy and security company policies that we believe match the requirements specified in the HIPAA rules. When used with end-to-end encryption, our technical capabilities match the requirements of the HIPAA Security rule. (Many of the requirements such as facility access controls are satisfied by running on Google Cloud Platform).

    View Article
  • Layer authentication requires that a backend application generate Layer identity tokens on behalf of client applications.

    This mechanism is designed to delegate the concerns of authentication and identity to your backend application. This allows you to authenticate users within the Layer service without sharing credentials, and greatly enhances client security.

    View Article
  • Once a nonce is obtained, the authenticating client has 10 minutes to present it to an identity provider and obtain an external identity token. Once a nonce is used you generate an identity token it can't be re-used.

    View Article
  • When you call layerClient.sendMessage on Android or [messagesend] on iOS, your message is immediately persisted to the local data store and enqueued for delivery. The method returns a BOOL value which returns true if the message object has passed validation and is enqueued for delivery.

    If the client has an internet connection, a synchronization process is immediately kicked off which will send the message off of the device. If the device does not have a current connection, the message will remain enqueued in the local data store and will be immediately sent once the device establishes an internet connection.

    View Article
  • As of LayerKit 0.20.0 (released in March 2016), LayerKit is ATS-compliant.

    View Article
  • For information on generating Layer identity tokens, please see the Layer Authentication Guide.

    View Article
  • You can use the LYRQueryController with a LYRQuery that only fetches messages where isUnread is true, this would give you a count of all unread messages.

    @property (nonatomic, retain) LYRQueryController *queryController;

    ...

    LYRQuery *query = [LYRQuery queryWithQueryableClass:[LYRMessage class]];

    query.predicate = [LYRPredicate predicateWithProperty:@"isUnread" predicateOperator:LYRPredicateOperatorIsEqualTo value:@(YES)];

    self.queryController = [self.client queryControllerWithQuery:query error:nil];

    self.queryController.delegate = self;

    NSError *error;

    BOOL success = [self.queryController execute:&error];

    if (success) {

    NSLog(@"Query fetched %tu message objects", [self.queryController numberOfObjectsInSection:0]);

    } else {

    NSLog(@"Query failed with error: %@", error);

    }

    Your interface has to implement the queryControllerDidChangeContent: delegate method. This method will get called every time the unread count will change:

    - (void)queryControllerDidChangeContent:(LYRQueryController *)queryController

    {

    self.numberOfUnreadMessagesLabel.text = [NSString stringWithFormat:@"%d", queryController.count];

    }

    But if you want to get the number of unread conversations, then you should setup the query withLYRConversation instead of LYRMessage:

    LYRQuery *query = [LYRQuery queryWithQueryableClass:[LYRConversation class]];

    View Article
  • If a user has been authenticated and you request a nonce, the nonce will come back nil. Layer will cache the user so will only need to re-authenticate if the user has been deauthenticated. So you should check if the user is authenticated before request a nonce.

    View Article
  • When generating the Layer identity token, the first thing to ensure is that each of the header and claim parameters are of the correct type. They should be the following

    Header

    typ - String

    alg - String

    cty - String

    kid - String

    Claim

    iss - String *prn - String

    iat - Integer in RFC 3339 seconds

    exp - Integer in RFC 3339 seconds

    nce - String

    Aditional items to check:

    Layer identity tokens must be signed with the RS256 algorithm

    Ensure you are using Base64URL encoding and NOT base64 encoding

    View Article
  • This error tends to occur when you call connectWithCompletion immediately after the appdoes Facebook/Google/LinkedIn/etc OAuth authentication. This causes a "Generation of key pair failed with result code -34018" error and Layer can't connect. This is because multiple SDK's are interacting with the Keychain at the same time.

    We believe this issue has not been resolved in LayerKit v0.19.1. Please update to the latest SDK and try again.

    View Article
  • Conversation objects are created by calling

    newConversationWithParticipants

    on the LYRClient object.

    // Creates and returns a new conversation object with a single participant represented by your backend's user identifier for the participant

    LYRConversation *conversation = [LYRClient newConversationWithParticipants:[NSSet setWithArray:@[@"USER-IDENTIFIER"]]];

    View Article
  • While the Layer SDK's appear large at a glance, the overall size the LayerKit framework adds to your mobile after compilation is relatively small.

    iOS: ~6.5 MB (See Why is my XCode IPA archive so large? )

    Android: ~700 KB

    View Article
  • The Layer SDK allows you to send any type of payload including text, photo, voice recording, video recording, location data and game metadata, just to name a few. Messages can contain large files of any type, up to 2GB each. A few sample use cases of these features include simple chat, group messaging, photo messaging, ephemeral messaging, and location sharing.

    View Article
  • Yes, you can create conversations with just yourself. This conversation and its messages will then be synchronized among all of your devices.

    Many Layer developers use this functionality for synchronizing user preferences among devices.

    View Article
  • Yes, your application can create as many conversations as it would like with the same participant lists.

    View Article
  • When a user is added to a conversation, they are immediately given access to all previous message content. They will also recieve all future messages sent within the context of the conversation.

    View Article
  • Aftera conversation is created using the iOS or Android SDKs, it is stored in memory and only written to the local database whenthe first message is sent. This can only happen after cold sync (the initial sync after authentication) completes.

    In other words, when creating a conversation, you must wait for cold syncing to finish,and the conversation must contain at least one message, before it will return in a query.

    This can lead to a race condition where the same set of participants might inadvertently create multiple conversations.

    To ensure all users in a given conversation are using the same object, you can use distinct conversations. Conversations are distinct by default, and only need to be created when a user is ready to send a message.

    Note: Conversations lose their distinct status if the participant list changes (users are added or removed), after which trying to access a distinct conversation will return a new conversation object.

    iOS

    Try to create a conversation with a given user. If a conversation with this user exists, an error will be returned containing the existing conversation.

    NSSet *participants = [NSSet setWithObjects:otherUserID, nil];NSDictionary *options = @{};LYRConversation *conversation = [self.layerClient newConversationWithParticipants:participants options:options error:error];if (error && error.code == LYRErrorDistinctConversationExists) { conversation = error.userInfo[LYRExistingDistinctConversationKey];}

    Android

    Try to create a conversation with a given user. If a conversation with this user exists, an exceptionwill be throwncontaining the existing conversation.

    public Conversation getDistinctConversation(String otherUserID){ Conversation conversation = null; try { conversation = layerClient.newConversation(otherUserID); } catch (LayerConversationException e) { if (e.getType() == LayerException.Type.DISTINCT_CONVERSATION_EXISTS) { conversation = e.getConversation(); } else { throw e; } } return conversation;}

    View Article
  • If you don't have access to a server with an SSL cert, you can use a service like ngrok for testing. ngrok lets you expose local servers behind NATs and firewalls to the public internet over secure tunnels.

    View Article
  • First take a look at the response headers coming from Layer and pay attention to the content length. If it's greater than zero then we are sending you some content, but your backend is not correctly reading/parsing it. If the content length is zero contact Layer Support.

    View Article
  • Yes. Check out our docs about retrieving conversations and retrieving messages.

    View Article
  • Yes, Layer authentication requires that a backend application generate Layer identity tokens on behalf of your client applications. For information on generating Layer identity tokens, please see the Layer Authentication Guide for iOS, Android, or the Client API.

    View Article
  • On iOS you would run a query like this:

    LYRQuery *query = [LYRQuery queryWithClass:[LYRMessage class]];

    LYRPredicate *conversationPredicate = [LYRPredicate predicateWithProperty:@"conversation" operator:LYRPredicateOperatorIsEqualTo value:conversation];

    LYRPredicate *unreadPredicate = [LYRPredicate predicateWithProperty:@"isUnread" operator:LYRPredicateOperatorIsEqualTo value:@(YES)];

    LYRPredicate *userPredicate = [LYRPredicate predicateWithProperty:@"sender.userID" operator:LYRPredicateOperatorIsNotEqualTo value:self.client.authenticatedUserID];

    query.predicate = [LYRCompoundPredicate compoundPredicateWithType:LYRCompoundPredicateTypeAnd subpredicates:@[conversationPredicate, unreadPredicate, userPredicate]];

    NSError *error;

    NSUInteger count = [self.client countForQuery:query error:&error];

    if (!error) {

    NSLog(@"%tu unread messages in conversation", count);

    } else {

    NSLog(@"Query failed with error %@", error);

    }

    On Android, the query would look like this:

    Query query = Query.builder(Message.class)

    .predicate(new CompoundPredicate(CompoundPredicate.Type.AND,

    new Predicate(Message.Property.CONVERSATION, Predicate.Operator.EQUAL_TO, conversation),

    new Predicate(Message.Property.IS_UNREAD, Predicate.Operator.EQUAL_TO, true)))

    .build();

    List<Integer> resultArray = layerClient.executeQuery(query, Query.ResultType.COUNT);

    int count = resultArray.get(0).intValue();System.out.println(count + " unread messages in conversation");

    View Article
×
Rate your company