All docs / Mobile + native Carrier SDKs

Android Carrier SDK

JNI wrapper for Carrier on Android: identity, friends, messages with receipts, Express offline delivery, files and sessions. The public coordinate is the 2022 upstream build; the 16 KB-aligned builds Beagle ships are not published yet.

Version
6.0.4 · Maven Central · 2022 build
Platform
Android · Java
implementation 'org.elastos:carrier:6.0.4'

Integration verified on 2026-11-06: a minimal Android app depending on org.elastos:carrier:6.0.4 from Maven Central was built with ./gradlew assembleDebug (JDK 17.0.15, Gradle 8.7, Android Gradle Plugin 8.5.1, compileSdk 34, minSdk 21), then run on an Android 14 arm64 emulator: the native libraries loaded, an identity was created, and the node reached onReady and Connected through the public bootstrap nodes. Friend, message, file and session samples below compile against the same artifact; they were not exercised against a second peer.

The Android Carrier SDK is a Java wrapper (JNI) around the native Carrier C library. It gives an Android app a self-generated Carrier identity, a friend list, end-to-end encrypted friend messages with delivery receipts, offline delivery through Express nodes, pull-based file transfer, and sessions/streams for raw peer-to-peer data. All classes live under org.elastos.carrier. The WebRTC calling SDK (/docs/android-webrtc) is built on top of it.

When to use it

Use it when you are writing a native Android app (Java or Kotlin) that must be a full Carrier peer on the device: it holds its own keys, talks to friends directly, and keeps working without any server you operate. Pick /docs/android-webrtc in addition when you need audio/video calls. If your code runs in Node.js or a browser, use the npm packages instead (see /docs/peer).

What you get today is the Elastos Carrier 6.0.4 binary on Maven Central. The public fork documented here (0xli/Elastos.NET.Carrier.Android.SDK, branch agent/permissionless-realtime-network) has the same Java API as that binary, plus one method, createIdentityAuthProof, which is a stub (see the API reference). No build of the fork itself is published.

Add it to your project

What you can resolve today is not what Beagle ships. org.elastos:carrier:6.0.4 on Maven Central is the original upstream Elastos build from 2022-11-01 (Maven metadata lastUpdated 20221101); it was not built from the public fork documented on this page. It lacks 16 KB page-size alignment — in the 6.0.4 AAR, arm64-v8a/libcarrierjni.so and all five x86_64 libraries have 4 KB ELF segment alignment — so Google Play may reject an app built with it, and it lacks the fixes Decent Network has made since. The 16 KB-aligned Carrier builds that Beagle Chat for Android ships with are not published yet. Use 6.0.4 to develop and evaluate; contact developer support before shipping to Play.

The only consumable distribution is Maven Central (org.elastos:carrier:6.0.4, published 2022-11-01). It is not on JitPack (JitPack has no builds of the fork), and the 5.3.2 coordinate in the repository README does not exist on Maven Central. The old Elastos Nexus repository (nexus.elastos.org) no longer resolves in DNS.

settings.gradle:

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()   // org.elastos:carrier:6.0.4 is published here
    }
}

app/build.gradle:

android {
    compileSdk 34
    defaultConfig {
        minSdk 21
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation 'org.elastos:carrier:6.0.4'
}

The AAR's manifest sets android:label on <application>, so the manifest merge fails unless you override it. It already declares INTERNET.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- The Carrier AAR's manifest also sets android:label; override it. -->
    <application
        android:label="Carrier sample"
        tools:replace="android:label">
        ...
    </application>
</manifest>

What the AAR contains:

ItemDetail
Java classesorg.elastos.carrier, .session, .filetransfer, .exceptions
Native librarieslibcarrierjni.so, libcarrier.so, libcarriersession.so, libcarrierfiletrans.so, libcrystal.so
ABIsarmeabi-v7a, arm64-v8a, x86, x86_64
Min SDK21
LicenseGPLv3 (per the POM and the repository LICENSE)

In the 6.0.4 AAR, arm64-v8a/libcarrierjni.so is built with 4 KB ELF segment alignment (the other four arm64-v8a libraries use 64 KB), and all five x86_64 libraries use 4 KB. It therefore does not meet Google Play's 16 KB page-size requirement for apps targeting Android 15 and later. Plan for a rebuilt AAR if you ship on Play.

Building the fork from source is not practical today. Its Gradle files use Android Gradle Plugin 3.3.2 and jcenter(), and the prebuilt native libraries it expects in app/native-dist/lib/ are not in git. The download script .script/download_libs.sh points at a release page that returns 404. You would need to cross-compile the native Carrier SDK for Android yourself and modernise the Gradle build. The native SDK's dependency downloads work again as of release v6.1.0 (its c-toxcore source now comes from a mirror release), but an Android cross-compile of v6.1.0 has not been verified for this page.

Initialize

Create a Carrier.Options with a persistent directory and at least one bootstrap node. Then call Carrier.createInstance(options, handler), followed by start(). The SDK defines no default bootstrap nodes. The two below are the public nodes also listed in the @decentnetwork/peer documentation.

import org.elastos.carrier.AbstractCarrierHandler;
import org.elastos.carrier.Carrier;
import org.elastos.carrier.ConnectionStatus;
import org.elastos.carrier.FriendInfo;
import org.elastos.carrier.UserInfo;
import org.elastos.carrier.exceptions.CarrierException;

public class MainActivity extends Activity {
    private static final String TAG = "CarrierSample";
    private final Handler main = new Handler(Looper.getMainLooper());
    private Carrier carrier;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(TAG, "Carrier native version: " + Carrier.getVersion());

        File dir = new File(getFilesDir(), "carrier");
        dir.mkdirs();

        Carrier.Options options = new Carrier.Options();
        options.setPersistentLocation(dir.getAbsolutePath()); // keys + friend list live here
        options.setUdpEnabled(true);

        List<Carrier.Options.BootstrapNode> bootstraps = new ArrayList<>();
        bootstraps.add(new Carrier.Options.BootstrapNode()
                .setIpv4("47.100.103.201").setPort("33445")
                .setPublicKey("CX1XH419p4xJ5SV4KvDxBeKYSRdMJW9QpdWJY8owUxHd"));
        bootstraps.add(new Carrier.Options.BootstrapNode()
                .setIpv4("154.64.235.176").setPort("33445")
                .setPublicKey("GdNtV2N74fZnLjhH7NhQ18nGdxb1k8jRM9dQaK7WnxmL"));
        options.setBootstrapNodes(bootstraps);

        try {
            carrier = Carrier.createInstance(options, new AbstractCarrierHandler() {
                @Override
                public void onConnection(Carrier c, ConnectionStatus status) {
                    Log.i(TAG, "connection: " + status);
                }

                @Override
                public void onReady(Carrier c) {
                    // Carrier thread: hop to the main thread before touching UI.
                    main.post(() -> Log.i(TAG, "ready"));
                }

                @Override
                public void onFriendRequest(Carrier c, String userId, UserInfo info, String hello) {
                    try {
                        c.acceptFriend(userId);
                    } catch (CarrierException e) {
                        Log.e(TAG, "acceptFriend", e);
                    }
                }

                @Override
                public void onFriendAdded(Carrier c, FriendInfo info) {
                    Log.i(TAG, "friend added: " + info.getUserId());
                }

                @Override
                public void onFriendMessage(Carrier c, String from, byte[] message,
                                            Date timestamp, boolean isOffline) {
                    Log.i(TAG, from + (isOffline ? " (offline): " : ": ")
                            + new String(message, StandardCharsets.UTF_8));
                }
            });

            Log.i(TAG, "address: " + carrier.getAddress()); // share this to be added as a friend
            Log.i(TAG, "userId:  " + carrier.getUserId());
            Log.i(TAG, "nodeId:  " + carrier.getNodeId());
            carrier.start(0); // spawns the Carrier thread (the SDK tests also pass 0)
        } catch (CarrierException e) {
            Log.e(TAG, "createInstance failed", e);
        }
    }

    @Override
    protected void onDestroy() {
        if (carrier != null) carrier.kill();
        super.onDestroy();
    }
}

Verified output (org.elastos:carrier:6.0.4, Android 14 arm64 emulator, 2026-11-06), from adb logcat -s CarrierSample CarrierCore:

I CarrierSample: Carrier native version: 60bd828f
I CarrierCore: Carrier node instance created
I CarrierSample: address: 8KVejycnD6Kv42HiPH9YLKcDfgB7dg35vwQjLG2pzKYD5942N6Ub
I CarrierSample: userId:  4L8hDmhCKHuRECoZwPHPbK2rQHwtT4tKwsrorYhG9Piy
I CarrierSample: nodeId:  4L8hDmhCKHuRECoZwPHPbK2rQHwtT4tKwsrorYhG9Piy
I CarrierCore: Native carrier node started
I CarrierSample: ready
I CarrierSample: connection: Connected[0]

Carrier.Options setters:

SetterNotes
setPersistentLocation(String)Required. Holds the identity keys and the friend list. Reuse the same directory to keep the same identity.
setSecretKey(byte[])Optional, exactly 32 bytes. Seeds a new identity. Ignored when persistent data already exists.
setUdpEnabled(boolean)false forces TCP only (slower).
setBootstrapNodes(List<BootstrapNode>)Required in practice; the SDK has no defaults. BootstrapNode has setIpv4, setIpv6, setPort (a String), setPublicKey.
setExpressNodes(List<ExpressNode>)Optional offline-message relays. ExpressNode has setIpv4, setPort, setPublicKey.

Identity

String address = carrier.getAddress();   // share this to be added as a friend
String userId  = carrier.getUserId();    // stable public key; used to address friends
String nodeId  = carrier.getNodeId();
boolean ok = Carrier.isValidAddress(address);
String idFromAddr = Carrier.getIdFromAddress(address); // == userId

UserInfo me = carrier.getSelfInfo();
me.setName("Alice");
me.setDescription("Android demo");
carrier.setSelfInfo(me);

carrier.setPresence(PresenceStatus.Away);

// Rotating nospam changes the address (old address stops accepting
// new friend requests); userId stays the same.
carrier.setNospam(carrier.getNospam() + 1);
  • address: Base58, 38 bytes decoded (public key plus nospam and checksum). Use it only for addFriend.
  • userId: Base58, 32 bytes decoded. It identifies a peer in every other call.
  • nodeId: on this build it equals the userId (see the verified output above).

Friends

carrier.addFriend(friendAddress, "hi, it's Alice");   // request; peer gets onFriendRequest
// receiving side, inside CarrierHandler.onFriendRequest(...):
//     carrier.acceptFriend(userId);
if (carrier.isFriend(friendUserId)) {
    FriendInfo f = carrier.getFriend(friendUserId);
    Log.i(TAG, f.getName() + " " + f.getConnectionStatus() + " " + f.getPresence());
    carrier.labelFriend(friendUserId, "work");
}
List<FriendInfo> all = carrier.getFriends();
carrier.removeFriend(friendUserId);

These handler callbacks report friend events: onFriendRequest, onFriendAdded, onFriendRemoved, onFriendConnection (ConnectionStatus.Connected / Disconnected), onFriendPresence (PresenceStatus.None / Away / Busy) and onFriendInfoChanged. The SDK also reports the whole list once through onFriends(carrier, List<FriendInfo>).

Messages

long msgId = carrier.sendFriendMessage(friendUserId, "hello",
        (messageId, state) -> {
            if (state == ReceiptState.ReceiptByFriend) {
                Log.i(TAG, messageId + " delivered");
            } else if (state == ReceiptState.DeliveredAsOffline) {
                Log.i(TAG, messageId + " stored for offline delivery");
            } else {
                Log.w(TAG, messageId + " failed");
            }
        });

// App-level request/response ("invite") carrying a string payload:
carrier.inviteFriend(friendUserId, "{\"op\":\"ping\"}",
        (from, status, reason, data) -> Log.i(TAG, "invite reply " + status + " " + data));
// receiving side, inside CarrierHandler.onFriendInviteRequest(c, from, data):
//     c.replyFriendInvite(from, 0, null, "{\"op\":\"pong\"}");
  • sendFriendMessage has two overloads: String and byte[]. Both require a non-null FriendMessageReceiptHandler and return a message id. The String form rejects messages of Carrier.CARRIER_MAX_USER_NAME_LEN (5 MiB) or longer. Split larger payloads yourself.
  • Incoming messages arrive in onFriendMessage(carrier, from, byte[] message, Date timestamp, boolean isOffline).

Files

File transfer is pull-driven: the receiver asks for data from an offset, and the sender writes it. Create one filetransfer.Manager per Carrier instance and keep it.

Sender:

org.elastos.carrier.filetransfer.Manager ftm =
        org.elastos.carrier.filetransfer.Manager.createInstance(carrier);
final FileTransferInfo info = new FileTransferInfo("photo.jpg", null, bytes.length);

FileTransfer ft = ftm.newFileTransfer(friendUserId, info, new FileTransferHandler() {
    @Override public void onStateChanged(FileTransfer t, FileTransferState s) {
        Log.i(TAG, "ft state " + s);
    }
    @Override public void onFileRequest(FileTransfer t, String fileId, String name, long size) { }
    @Override public void onPullRequest(FileTransfer t, String fileId, long offset) {
        try {   // receiver asked for data starting at offset: push it, then finish
            t.writeData(fileId, bytes, (int) offset, bytes.length - (int) offset);
            t.sendFinish(fileId);
        } catch (CarrierException e) {
            Log.e(TAG, "writeData", e);
        }
    }
    @Override public boolean onData(FileTransfer t, String fileId, byte[] data) { return true; }
    @Override public void onDataFinished(FileTransfer t, String fileId) { }
    @Override public void onPending(FileTransfer t, String fileId) { }
    @Override public void onResume(FileTransfer t, String fileId) { }
    @Override public void onCancel(FileTransfer t, String fileId, int status, String reason) { }
});
ft.connect();   // peer gets ManagerHandler.onConnectRequest(carrier, from, info)

Receiver:

final org.elastos.carrier.filetransfer.Manager[] ftm =
        new org.elastos.carrier.filetransfer.Manager[1];
ftm[0] = org.elastos.carrier.filetransfer.Manager.createInstance(carrier,
        (c, from, info) -> {
            try {
                FileTransfer ft = ftm[0].newFileTransfer(from, info, new FileTransferHandler() {
                    @Override public void onStateChanged(FileTransfer t, FileTransferState s) {
                        if (s == FileTransferState.Connected) {
                            try { t.pullData(info.getFileId(), 0); }
                            catch (CarrierException e) { Log.e(TAG, "pull", e); }
                        }
                    }
                    @Override public void onFileRequest(FileTransfer t, String id, String n, long sz) { }
                    @Override public void onPullRequest(FileTransfer t, String id, long off) { }
                    @Override public boolean onData(FileTransfer t, String id, byte[] data) {
                        // append data to your output file; return true to keep receiving
                        return true;
                    }
                    @Override public void onDataFinished(FileTransfer t, String id) { t.close(); }
                    @Override public void onPending(FileTransfer t, String id) { }
                    @Override public void onResume(FileTransfer t, String id) { }
                    @Override public void onCancel(FileTransfer t, String id, int st, String r) { }
                });
                ft.acceptConnect();
            } catch (CarrierException e) {
                Log.e(TAG, "accept file", e);
            }
        });

Other FileTransfer controls: addFile(FileTransferInfo), pendTransfer(fileId) / resumeTransfer(fileId) for flow control, cancelTransfer(fileId, status, reason), and getOutputStream(fileId). You can resume from a break point by calling pullData with a non-zero offset. There is no AbstractFileTransferHandler, so you implement all eight callbacks.

Sessions and calls

A session carries raw streams (reliable or unreliable, optionally multiplexed into channels, or port-forwarding) between two friends over ICE. Create one session.Manager per Carrier instance. For audio/video calls, use /docs/android-webrtc; it does its own signaling over Carrier and does not use this session API.

Initiator: add a stream, send the request once the stream is Initialized, then start() with the peer's SDP:

org.elastos.carrier.session.Manager sm =
        org.elastos.carrier.session.Manager.createInstance(carrier);
final Session session = sm.newSession(friendUserId);
session.addStream(StreamType.Application, Stream.PROPERTY_RELIABLE,
        new AbstractStreamHandler() {
            @Override
            public void onStateChanged(Stream stream, StreamState state) {
                if (state == StreamState.Initialized) {
                    try {
                        session.request((s, status, reason, sdp) -> {
                            if (status == 0) {
                                try { s.start(sdp); }
                                catch (CarrierException e) { Log.e(TAG, "start", e); }
                            }
                        });
                    } catch (CarrierException e) {
                        Log.e(TAG, "request", e);
                    }
                } else if (state == StreamState.Connected) {
                    try { stream.writeData("hello over a stream".getBytes()); }
                    catch (CarrierException e) { Log.e(TAG, "write", e); }
                }
            }

            @Override
            public void onStreamData(Stream stream, byte[] data) {
                Log.i(TAG, "stream data " + data.length);
            }
        });

Responder: the ManagerHandler receives onSessionRequest(carrier, from, sdp). Create a session back to from, add a matching stream, and on TransportReady reply and start:

final org.elastos.carrier.session.Manager[] sm =
        new org.elastos.carrier.session.Manager[1];
sm[0] = org.elastos.carrier.session.Manager.createInstance(carrier, (c, from, sdp) -> {
    try {
        final Session session = sm[0].newSession(from);
        session.addStream(StreamType.Application, Stream.PROPERTY_RELIABLE,
                new AbstractStreamHandler() {
                    @Override
                    public void onStateChanged(Stream stream, StreamState state) {
                        if (state == StreamState.TransportReady) {
                            try {
                                session.replyRequest(0, null);
                                session.start(sdp);
                            } catch (CarrierException e) {
                                Log.e(TAG, "reply/start", e);
                            }
                        }
                    }
                });
    } catch (CarrierException e) {
        Log.e(TAG, "session", e);
    }
});

Stream states go Initialized → TransportReady → Connecting → Connected, then Deactivated / Closed / Error. Stream.PROPERTY_* flags are COMPRESS, PLAIN, RELIABLE, MULTIPLEXING and PORT_FORWARDING. With MULTIPLEXING, use openChannel / writeData(channel, …) / closeChannel. With PORT_FORWARDING, the responder calls session.addService(name, PortForwardingProtocol.TCP, host, port) and the initiator calls stream.openPortForwarding(name, PortForwardingProtocol.TCP, host, port).

Offline messages (Express)

If you configure Express nodes in Options, a message to an offline friend is stored on an Express node. The sender then gets ReceiptState.DeliveredAsOffline in its receipt handler. The receiver gets the message later through onFriendMessage(…, isOffline = true). Without Express nodes there is no offline store, so a friend has to be online to receive a message.

List<Carrier.Options.ExpressNode> express = new ArrayList<>();
express.add(new Carrier.Options.ExpressNode()
        .setIpv4("EXPRESS_HOST")
        .setPort("443")
        .setPublicKey("EXPRESS_PUBLIC_KEY"));
options.setExpressNodes(express);

setIpv4 takes a host name or an IP address. Get the host, port and public key from the Express operator you use. Offline delivery was not exercised in this verification.

Threading and lifecycle

  • Carrier.createInstance is synchronous and loads libcarrierjni on first use of the class. getAddress() / getUserId() work immediately, before start().
  • start(int iterateInterval) spawns one Java thread that runs the native event loop. Every CarrierHandler callback runs on that thread. In the verified run, onConnection arrived on the Carrier thread, not the main thread. Post to a main-thread Handler before you touch views.
  • Don't block inside callbacks. onIdle fires on every loop iteration. File-transfer and stream callbacks also come from native threads.
  • onReady fires once the node has joined the network. onConnection(Connected/Disconnected) tracks the link to the network.
  • kill() stops the loop, joins the thread and invalidates the instance; create a new one to reconnect. Call cleanup() on session and file-transfer managers before kill(). Run one Carrier per persistent directory.
  • Errors throw CarrierException (getErrorCode(), getFacility(), getCode()), with subclasses GeneralException, SystemException, ICEException, DHTException and UnknownException.

API reference

Carrier

MemberSignature
createstatic Carrier createInstance(Options options, CarrierHandler handler) throws CarrierException
run / stopvoid start(int iterateInterval), synchronized void kill(), boolean isReady()
static helpersstatic String getVersion(), static boolean isValidId(String), static boolean isValidAddress(String), static String getIdFromAddress(String)
identityString getAddress(), String getUserId(), String getNodeId(), void setNospam(int), int getNospam()
profileUserInfo getSelfInfo(), void setSelfInfo(UserInfo), void setPresence(PresenceStatus), PresenceStatus getPresence()
friendsvoid addFriend(String address, String hello), void acceptFriend(String userId), void removeFriend(String userId), boolean isFriend(String userId), FriendInfo getFriend(String userId), List<FriendInfo> getFriends(), void labelFriend(String userId, String label)
messageslong sendFriendMessage(String to, String message, FriendMessageReceiptHandler handler), long sendFriendMessage(String to, byte[] message, FriendMessageReceiptHandler handler)
invitesvoid inviteFriend(String to, String data, FriendInviteResponseHandler handler), void replyFriendInvite(String to, int status, String reason, String data)
groupsGroup newGroup(), Group groupJoin(String friendId, byte[] cookie), void groupLeave(Group), Collection<Group> getGroups()
fork onlybyte[] createIdentityAuthProof(byte[] serverPublicKey, byte[] transcript): present in the fork's Java source but not in 6.0.4, and its JNI side is a "not implemented" stub that is not even registered. Don't use it.

CarrierHandler (extend AbstractCarrierHandler to override only what you need)

onIdle, onConnection(Carrier, ConnectionStatus), onReady, onSelfInfoChanged(Carrier, UserInfo), onFriends(Carrier, List<FriendInfo>), onFriendConnection(Carrier, String, ConnectionStatus), onFriendInfoChanged(Carrier, String, FriendInfo), onFriendPresence(Carrier, String, PresenceStatus), onFriendRequest(Carrier, String userId, UserInfo, String hello), onFriendAdded(Carrier, FriendInfo), onFriendRemoved(Carrier, String), onFriendMessage(Carrier, String from, byte[], Date, boolean isOffline), onFriendInviteRequest(Carrier, String from, String data), onGroupInvite(Carrier, String from, byte[] cookie), plus the GroupHandler methods onGroupConnected, onGroupMessage, onGroupTitle, onPeerName, onPeerListChanged.

Value types

TypeValues / members
ConnectionStatusConnected, Disconnected
PresenceStatusNone, Away, Busy
ReceiptStateReceiptByFriend, DeliveredAsOffline, Error
UserInfogetUserId, get/setName, get/setDescription, hasAvatar/setHasAvatar, get/setGender, get/setPhone, get/setEmail, get/setRegion
FriendInfo extends UserInfoget/setLabel, getConnectionStatus, getPresence
GroupgetId, invite(String friendId), sendMessage(byte[]) (max Group.MAX_APP_MESSAGE_LEN = 1024), getTitle / setTitle, getPeers(), getPeer(String)

org.elastos.carrier.filetransfer

ClassMembers
Managerstatic Manager createInstance(Carrier), static Manager createInstance(Carrier, ManagerHandler), FileTransfer newFileTransfer(String to, FileTransferInfo fileinfo, FileTransferHandler handler), cleanup()
ManagerHandlervoid onConnectRequest(Carrier carrier, String from, FileTransferInfo info)
FileTransferstatic String generateFileId(), connect(), acceptConnect(), addFile(FileTransferInfo), pullData(String fileId, long offset), writeData(String fileId, byte[] data[, int offset, int len]), getOutputStream(String fileId), sendFinish(String fileId), cancelTransfer(String fileId, int status, String reason), pendTransfer(String), resumeTransfer(String), getFileId(String filename), getFileName(String fileId), close()
FileTransferInfoFileTransferInfo(String filename, String fileId /* null = generate */, long size), getFileName(), getFileId(), getSize()
FileTransferHandleronStateChanged, onFileRequest, onPullRequest, boolean onData, onDataFinished, onPending, onResume, onCancel
FileTransferStateInitialized, Connecting, Connected, Closed, Failed

org.elastos.carrier.session

ClassMembers
Managerstatic Manager createInstance(Carrier), static Manager createInstance(Carrier, ManagerHandler), Session newSession(String to), cleanup()
ManagerHandlervoid onSessionRequest(Carrier carrier, String from, String sdp)
SessiongetPeer(), request(SessionRequestCompleteHandler), replyRequest(int status, String reason), start(String sdp), Stream addStream(StreamType type, int options, StreamHandler handler), removeStream(Stream), addService(String service, PortForwardingProtocol protocol, String host, String port), removeService(String), close()
SessionRequestCompleteHandlervoid onCompletion(Session session, int status, String reason, String sdp)
StreamgetStreamId(), getType(), getTransportInfo(), writeData(byte[] …), getOutputStream(), openChannel(String cookie), closeChannel(int), writeData(int channel, byte[] …), pendChannel(int), resumeChannel(int), openPortForwarding(String service, PortForwardingProtocol protocol, String host, String port), closePortForwarding(int)
StreamHandler / AbstractStreamHandleronStateChanged, onStreamData, boolean onChannelOpen, onChannelOpened, onChannelClose, boolean onChannelData, onChannelPending, onChannelResume
enumsStreamType (Audio, Video, Text, Application, Message), StreamState, CloseReason, PortForwardingProtocol (TCP)

CarrierExtension

An abstract class meant for the WebRTC SDK (its own docs advise ordinary apps not to use it). It provides a second friend-invite channel (inviteFriend, replyFriendInvite, abstract onFriendInvite) and getTurnServerInfo(), which returns the TURN server advertised by the Carrier network. All of its members are protected.

Source