Android Client Example
Before going through this Android Client example it is recommended to get familiar with the Nabto WebRTC platform using one of the getting started guides which do not require coding.
Example Android App
You may find the example client app in Nabto WebRTC SDK for Android. Simply clone the repository to your local drive and open it in Android Studio. The code we are interested in is located in the “app” application module. Follow the “run the example test application” instructions in the README.md file to test the application.
Android does not come with a standard WebRTC implementation. As such the application uses a dependency on GetStream Android WebRTC. This is the standard WebRTC implementation precompiled for Android. This is the same WebRTC library which is also used in Chrome etc.
The other dependency that the application has is of course the Nabto WebRTC SDK. The application is written in Java and is only about ~500 lines of code total, split among the following 4 files.
LoggingMessageTransportObserverAdapter.java
LoggingMessageTransportObserverAdapter.java
LoggingSignalingClientObserverAdapter.java
MainActivity.java
The first three classes simply implement Observer interfaces. MainActivity.java
contains the one and only MainActivity class for the whole app.
Note: It is not recommended to structure your own Android applications in this way. We skip many good practices in order to have a very short and simple to understand example.
It is important to understand the following
- The Nabto SDK for Android primarily handles the signaling aspect of WebRTC. We do not provide a complete WebRTC solution.
- As stated above, this app uses a standard WebRTC implementation for everything other than signaling.
You may want to use the example app to understand how to use a standard WebRTC library such as Google’s WebRTC. This is out of scope for this guide and may be done at your own discretion. This guide will mostly focus on the usage of the Nabto WebRTC SDK for signaling purposes.
Core concepts
The Nabto WebRTC SDK for Android is split into three modules, core
, util
and util-org-webrtc
. The core
module contains code that directly interfaces with the Nabto WebRTC platform to establish client connections to devices.
The util
module contains code built on top of the core module, including helper classes, classes for signing JSON messages and a standardized signaling message format. You are not required to use our signaling message format, the core module can send any arbitrary JSON across the line. However, this would require you to create a custom message format that your devices and clients agree on. Since we’re using a standard device implementation, we will also be using the standard message format.
The util-org-webrtc
module has code which is used with the org.webrtc classes which comes from the standard webrc.org implementation. There are several providers of the org.webrtc code, we list a few of them below.
SignalingClient
In the core module, a SignalingClient
represents a single logical client connection. A SignalingClient
object is created using the SignalingClientFactory
utility class. In the MainActivity.java
file you can see how to set up a SignalingClient
object the onCreate
method of the MainActivity
class.
After creating a SignalingClient, it will be in an inactive state. You should create a class that implements the SignalingClient.Observer
interface and add it to the client. After that you call the start
method to connect the client to the Nabto platform so you can begin to send and receive signaling messages.
The following code snippet gives a rough sketch of how to create client and start it. MyObserver
is your own class that implements SignalingClient.Observer
.
SignalingClientFactory.Options options = new SignalingClientFactory.Options();
options.setProductId("pr-xxxxxx");
options.setDeviceId("de-xxxxxx");
SignalingClient client = SignalingClientFactory.createSignalingClient(options);
MyObserver observer = new MyObserver();
client.addObserver(observer);
client.start();
Now you may send JSON messages back and forth with the device using the sendMessage
method on the client object.
ClientMessageTransport
In the util module there is a ClientMessageTransport
class that is made to automate a lot of details away when using our standard message format. This class handles signing messages and sending them through the SignalingClient
object. In the same MainActivity.onCreate
method from earlier you can see how it’s set up together with the SignalingClient
object. This makes the complete setup code in the example app the following:
var opts = new SignalingClientFactory.Options()
.setProductId(productId)
.setDeviceId(deviceId);
client = SignalingClientFactory.createSignalingClient(opts);
messageTransport = ClientMessageTransport.createSharedSecretMessageTransport(client, sharedSecret);
messageTransport.addObserver(new LoggingMessageTransportObserverAdapter() {
@Override
public void onWebrtcSignalingMessage(WebrtcSignalingMessageUnion message) {
super.onWebrtcSignalingMessage(message);
perfectNegotiation.onMessage(message);
}
@Override
public void onSetupDone(List<SignalingIceServer> iceServers) {
super.onSetupDone(iceServers);
setupPeerConnection(iceServers);
}
});
client.addObserver(new LoggingSignalingClientObserverAdapter());
client.start();
In particular, pay attention to the observer added to the messageTransport object.
The ClientMessageTransport
object receives a message from the device, it will parse that message into a WebrtcSignalingMessage
object which represents any possible signaling message adhering to the message format. The parsed message is then sent to all observers through the onWebrtcSignalingMessage
method. In our case we pass it on to the PerfectNegotiation
object.
The second observer method, onSetupDone
, is simply called when the device and client have exchanged “setup” message, notifying each other that they’re both ready to establish a WebRTC connection. onSetupDone
carries a list of ICE servers which can be used with e.g. Google’s WebRTC to create the actual WebRTC peer connection. In our case this is done in MainActivity.setupPeerConnection
.
ClientMessageTransport
also has a method called sendWebrtcSignalingMessage
. Think of this method as being a wrapper around SignalingClient.sendMessage
, and think of the observer onWebrtcSignalingMessage
as being a wrapper around the onMessage
method in SignalingClient.Observer
.
In this way, the ClientMessageTransport
object helps to ensure that messages are sent and arrive in the same standard format.
The PerfectNegotiation
object is responsible for handling and sending WebrtcSignalingMessages, these are the Descriptions and Candidates which are exchanged between WebRTC peers. For example, when the WebRTC peer connection produces an SDP description that must be sent to the device.
What’s next
With this, the guide is concluded. You may use SignalingClient
and ClientMessageTransport
in your own project as outlined above for a simple on the rails implementation, or you may decide to familiarize yourself more with the SDK and implement your own message format on top of the core module.