Getting started with deepstreamHub is easy and takes less than ten minutes. However, if you have any questions, please get in touch.
This guide will take you through getting started on Android with deepstreamHub's three core concepts: Records, Events and RPCs.
Create a free account and get your API key
Connect to deepstreamHub and log in
The first thing to do is create a new Android application and include the following line in your build.gradle
file.
compile 'io.deepstream:deepstream.io-client-java:2.0.4'
Because we'll be needing to pass the same client between activities in our app, we can use the built-in DeepstreamFactory
to create a client and keep a reference to it.
In your MainActivity
you'll need to do the following:
DeepstreamFactory factory = DeepstreamFactory.getInstance();
DeepstreamClient client = factory.getClient("<Your app url">);
client.login();
From here, whenever we have a reference to our factory we can do factory.getClient()
and get the same client back. Our MainActivity
is just a basic Activity
with buttons pointing to our three pages EventActivity
, RpcActivity
and RecordActivity
. So we'll ignore that for now and jump right into events.
Event (publish-subscribe)
Events are deepstreamHub’s publish-subscribe mechanism. Clients and backend processes can subscribe to event-names (sometimes also called “topics” or “channels”) and receive messages published by other endpoints.
Events are non-persistent, one-off messages. For persistent data, please use records.
EditText
for input, a Button
for sending the data, and a TextView
to display this data.
To send the data in the EditText
, we can do the following:
submitButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String eventPayload = inputField.getText().toString();
client.event.emit("test-event", eventPayload);
inputField.setText("");
}
});
And to display any incoming data in our TextView
, we can do:
client.event.subscribe("test-event", new EventListener() {
@Override
public void onEvent(String s, final Object o) {
runOnUiThread(new Runnable() {
@Override
public void run() {
outputField.setText((String) o);
}
});
}
});
After this, we should have something that looks like the following:
Records (data-sync)
Records are the documents in deepstreamHub’s realtime datastore. A record is identified by a unique id and can contain any kind of JSON data. Clients and backend processes can create, read, write, update and observe the entire record as well as paths within it. Any change is immediately synchronized amongst all connected subscribers.
Records can be arranged in lists and collections and can contain references to other records to allow for the modelling of relational data structures.
You can learn more about records in the records tutorial.
Record
with two fields, firstname
and lastname
. We also need two EditText
fields in our Activity
.
The first thing want to do is get a reference to our Record
, with the Java SDK it looks like this:
Record record = client.record.getRecord("test-record");
record.setMergeStrategy(MergeStrategy.REMOTE_WINS);
Next, we want to add a TextWatcher
on the input fields, so that whenever new data is entered, the Record
will be updated with these changes. To update the Record
data, we'll be using the Record.set(String path, Object data)
method.
firstnameInputField.addTextChangedListener(new CustomTextChangedWatcher("firstname"));
lastnameInputField.addTextChangedListener(new CustomTextChangedWatcher("lastname"));
With our CustomTextChangedWatcher
just being the following:
private class CustomTextChangedWatcher implements TextWatcher {
private String field;
CustomTextChangedWatcher(String recordField) {
this.field = recordField;
}
@Override
public void afterTextChanged(Editable s) {
if (s.toString().length() == 0) {
return;
}
record.set(field, s.toString());
}
}
After this, we just need to subscribe to the firstname
and lastname
fields and update the EditText
's whenever they change. This is similar to the above code snippet where we're just wrapping the RecordPathChangedCallback in a class and keeping a reference to something (in this case the corresponding EditText
).
record.subscribe("firstname", new CustomRecordPathChangedCallback(firstnameInputField), true);
record.subscribe("lastname", new CustomRecordPathChangedCallback(lastnameInputField), true);
Where the CustomRecordPathChangedCallback is just the following:
private class CustomRecordPathChangedCallback implements RecordPathChangedCallback {
private EditText field;
CustomRecordPathChangedCallback(EditText editTextField) {
this.field = editTextField;
}
@Override
public void onRecordPathChanged(String recordName, String path, final JsonElement data) {
runOnUiThread(new Runnable() {
@Override
public void run() {
if (data.isJsonNull()) {
return;
}
field.setText(data.getAsString());
// this line just moves the cursor to the end of the text
field.setSelection(field.getText().length());
}
});
}
}
Finally, we should have something that looks like this:
RPCs (request-response)
Remote Procedure Calls are deepstreamHub’s request-response mechanism. Clients and backend processes can register as “providers” for a given RPC, identified by a unique name. Other endpoints can request said RPC.
deepstreamHub will route requests to the right provider, load-balance between multiple providers for the same RPC, and handle data-serialisation and transport.
to-uppercase
, and then calling that method with some string.
We need a few elements for this to work in our app, namely:
-Button submitButton;
the button we click to call the RPC
-CheckBox provideCheckBox;
a check box to say whether we're providing the RPC
-EditText inputField;
the text field to enter our data
-TextView outputField;
the text field to display the result of our method
Our code for providing the method is simple, if the box is checked we want to provide the RPC, otherwise we'll unprovide it.
public void toggleProvide(View view) {
if (provideCheckBox.isChecked()) {
client.rpc.provide("to-uppercase", new RpcRequestedListener() {
@Override
public void onRPCRequested(String name, Object data, RpcResponse response) {
String uppercaseResult = data.toString().toUpperCase();
response.send(uppercaseResult);
}
});
} else {
client.rpc.unprovide("to-uppercase");
}
}
When we click the button, we'll just get whatever is in the EditText
and try make it upper case.
public void makeToUppercase(View view) {
String data = inputField.getText().toString();
final RpcResult result = client.rpc.make("to-uppercase", data);
if (result.success()) {
runOnUiThread(new Runnable() {
@Override
public void run() {
outputField.setText(result.getData().toString());
}
});
} else {
Toast.makeText(this, "Error making RPC", Toast.LENGTH_LONG).show();
}
}
Keep in mind that if there is no RPC provider, the RPC won't be able to be completed and will return a NO_RPC_PROVIDER
error. That being said, it should look like this:
Where to go next?
To learn how to use deepstreamHub with another backend language, head over to our Node tutorial, or if you'd like to learn how to build more extensive applications with deepstreamHub, take a look at our example apps tutorial section.