Android native
How to integrate the android native plugin.
You can use this plugin for all android games.
To obtain the plugin please connect with us.
It is very easy to integrate ESCS plugin into your game code
First you need to initialize your plugin.
To start using your plugin you need first initialize it:
Kotlin
Java
EscsService.invokeManaged(
EscsServiceConfig(
public_key, // String
base_url, // String
player_base_url // String
),
applicationContext, // Context,
invokeCallback // (status: String,
// gameId: String,
// tournamentId: String) -> Unit
) -> Unit
EscsService.INSTANCE.invokeManaged(
new EscsServiceConfig(
public_key, //String
base_url, //String
player_base_url //String
),
getApplicationContext(),
(status, gameId, tournamentId) -> {
//... process result
return Unit.INSTANCE;
}
);
where:
public_key
- a key that you've obtained in the step 1 of the integration guide, like"fee91a27-2b87-45f8-8ca4-0b317707806q"
player_base_url
- url for the player's ESCS service. It is https://player.escs.io for production environmentinvokeCallback
- callback when init is completed; you can omit it.
Callback lambda parameters are following:
status
- string "initialized" for fully initialized escs, or some error message, or empty stringgameId
- gameId string of configured game or empty stringtournamentId
- tournamentId string of current active tournament or empty string
Then you need to attach UI components into your activity (the button and the webview):
Kotlin
Java
val viewGroup =
window.decorView.findViewById(android.R.id.content) as ViewGroup
val btn = EscsButton(layoutInflater, viewGroup, applicationContext)
btn.attach()
val wv = EscsWebView(layoutInflater, viewGroup, applicationContext)
wv.attach()
ViewGroup viewGroup = getWindow()
.getDecorView()
.findViewById(android.R.id.content);
EscsWebView escsWebView = new EscsWebView(getLayoutInflater(),
viewGroup,
getApplicationContext());
escsWebView.attach();
EscsButton escsButton = new EscsButton(getLayoutInflater(),
viewGroup,
getApplicationContext());
escsButton.attach();
Don't forget to clean up on destroying your activity:
Kotlin
Java
override fun onDestroy() {
btn.detach()
wv.detach()
EscsService.finish()
super.onDestroy()
}
escsWebView.detach();
escsButton.detach();
EscsService.INSTANCE.finish();
After that you are all set and ready to use ESCS functionality. To start a game's round, just call
startGame()
method:Kotlin
Java
EscsService.startGame {
// process start round callback
Log.i("MyGame", it?.toString() ?: "no round received")
}
EscsService.INSTANCE.startGame(round -> {
Log.i("MyGame", round != null ? round.toString() : "no round received");
return Unit.INSTANCE;
});
where
- round - class instance with following fields:
_id
- roundId of just started game roundtournamentId
- tournamentId of active tournament for which the round was created forstatus
- round status. "active" for just created roundplayerId
- escs playerId
When the round of your game has ended, just call e
ndGame()
with score parameter:Kotlin
Java
EscsService.endGame( Score(
mapOf("points" to (count ?: 0.0), "points_extra" to (count1 ?: 0.0))
)
) { //Score takes map as parameter
Log.i("MyGame", it?.toString() ?: "no round received")
}
Map<String, Double> scoreMap = new HashMap<>();
scoreMap.put("score", 149.0);
scoreMap.put("score_extra", 3.0);
EscsService.INSTANCE.endGame(new Score(scoreMap), round -> {
Log.i("MyGame", round != null ? round.toString() : "no round received");
return Unit.INSTANCE;
});
where
score
- game score parameter - accepts a map of string key and double value; the names of keys should be defined in game dashboard at client.escs.ioround
- class instance with following fields:_id
- roundId of just ended game roundtournamentId
- tournamentId of active tournament for which the round was endedstatus
- round status. "ended" for just ended roundplayerId
- escs playerId
Most of the time you will not want to show the ESCS button during the actual game, to not mess with the gameplay, for example user can accidentally touch it and almost full-screen webview will show up. To hide or show button you can use following methods:
Kotlin
Java
escsButton.setVisible(View.GONE)
escsButton.setVisible(View.VISIBLE)
escsButton.setVisible(View.GONE);
escsButton.setVisible(View.VISIBLE);
There are situations, when ESCS needs to show announcements or notifications - for example to promote your game's upcoming championship, or ask user to add credit card, because his/her trial is about to expire. ESCS will open its full WebView automatically to show notification's content, if it's needed. To be able to show these, not interrupting your gameplay and at the times that are not interruptive for user, please call these methods:
Kotlin
Java
EscsService.maybeShowNotifications()
EscsService.maybeShowAnnouncements()
EscsService.INSTANCE.maybeShowNotifications();
EscsService.INSTANCE.maybeShowAnnouncements();
There's internal logic in the plugin to decide whether it needs to show actual notification and announcement, but you should place these calls whenever you feel that interruption with ESCS WebView window is okay for user experience.
Please note that it does not mean that user will see notification or announcement every time you call these methods. We are trying for those to be as subtle and fluent as possible for end user. Their names imply that notification/announcement just maybe will be shown.
There are situations when it is not suitable for your UI to have our ESCS button at default top center area. Then you can change that (remember, that user actually can drag the button anywhere on the screen he wants)
setDefaultPositionAbsolute()
will set button position in absolute coordinates from left upper corner of the app.Kotlin
Java
btn.setDefaultPositionAbsolute(50f, //x
50f) //y
escsButton.setDefaultPositionAbsolute(50f, //x
50f); //y
where
- x - x coordinate
- y - y coordinate
setDefaultPositionRelative()
will set button position in relative coordinates from center horizontally and top vertically of the app. That is, if you set 0, 0 coordinates the button will be shown in the x: (device width)/2 y: 0. The coordinate system here is from -0.5 to 0.5 for
xPart
: where -0.5 means most left side of device and 0.5 - right side and 0 is dead center. For yPart
it is from 0 to 1 where 0 is top of the screen and 1 is the bottom.Kotlin
Java
btn.setDefaultPositionRelative(0.5f, //xPart
0.5f) //yPart
escsButton.setDefaultPositionRelative(0.5f, //xPart
0.5f); //yPart
To receive the list of in-game rewards that particular player has (you can set those rewards as string fields in your game dashboard - for winning matches and so on) you can use the following method:
Kotlin
Java
EscsService.getInGameRewards {
Log.i("ESCS", "rewards: ${it.data.foldIndexed("") { index, acc, rewardPayload -> "${acc}\n ${index.toString()} ${rewardPayload?.rewardData}" }}");
}
where argument in the lambda is object of type InGameRewards:
count
- amount of rewards player has (integer)data
- list of RewardPayload objects:_id
- id of reward (string)rewardData
- string representation of rewards (which you set in the dashboard)tournamentId
- id of tournament it was received by player (string)
EscsService.INSTANCE.getInGameRewards(rewards -> {
Log.i("ESCS", "rewards " + (rewards != null ? rewards.toString() : " no rewards received"));
});
where argument in the lambda is object of type InGameRewards:
getCount()
- amount of rewards player has (integer)getData()
- list of RewardPayload objects:get_id()
- id of reward (string)getRewardData()
- string representation of rewards (which you set in the dashboard)getTournamentId()
- id of tournament it was received by player (string)
You can use our option for user game profile integration and allow your users to log in to our system without requiring them to manually create an escs account. Then the user will see an additional button "log in using %game_name% account" on the main escs screen. In order to support this, first, you need to follow the required steps in the client dashboard and set up the necessary fields as described in the corresponding docs section: Using escs oAuth for sign in. Note that you will also need to create an additional endpoint in your game's backend for the account system for verifying tokens. After this you will only need to implement one callback in your game:
Kotlin
Java
EscsService.registerGameUserProfilePermissionsCallback { list, respond ->
Log.i("ESCS", "requested profile permissions: ${list.toString()}")
//...
respond(token, acceptedPermissionList)
//...
}
where
list
- list of requested profile permissions (string), for example ["email", "id"]respond
- a function that is used to respond to this profile permissions request; you may want to ask the user to accept the requested permissions list in a dialog, or allow them to select only some of them; such dialog, if any, you should create and present to the user by yourself; when the user responded to it, you can use respond function to send user's choices to escs:token
- user access token, which will be used by escs backend to obtain profile information from your game's backend (string)acceptedPermissionList
- here you supply permissions that the user accepted, if any (list of strings)
EscsService.INSTANCE.registerGameUserProfilePermissionsCallback((list, respond) -> {
Log.i("ESCS", "requested profile permissions: " + String.join(", ", list));
//...
respond.invoke(token, acceptedPermissionList);
//...
return Unit.INSTANCE;
});
where
list
- list of requested profile permissions (string), for example ["email", "id"]respond
- a function that is used to respond to this profile permissions request; you may want to ask the user to accept requested permissions list in a dialog, or allow to select only some of them; such dialog, if any, you should create and present to user by yourself; when the user responded to it, you can use respond function to send user's choices to escs:token
- user access token, which will be used by escs backend to obtain profile information from your game's backend (string)acceptedPermissionList
- here you supply permissions that user accepted, if any (list of strings)
If you wish to perform certain actions when a user wants to join any tournament (i.e. show ads, etc.), you can use the following callback – the plugin will call it when the user presses the "I'm in" button on the main escs tournament page. To let the user join the tournament, you should call resolve(true) method, or resolve(false) to deny this possibility.
NOTE: in order for this callback to be activated, you should set up this option in the client dashboard as shown below
Kotlin
Java
EscsService.registerPlayerRequestJoinTournamentCallback { resolve ->
Log.i("ESCS", "player wants to join tournament")
//... perform showing ads or any other action
//... you may store resolve function for later use outside the callback
resolve(true) // allow the user to join the tournament
}
EscsService.INSTANCE.registerPlayerRequestJoinTournamentCallback ( (resolve) -> {
Log.i("ESCS", "player wants to join tournament");
//... perform showing ads or any other action
//... you may store resolve function for later use outside the callback
resolve.invoke(true); // allow the user to join the tournament
return Unit.INSTANCE;
});
When creating a tournament series for your game select the "Show Ads on "I'm in" checkbox as shown below to activate additional actions before the user can join a tournament.

To activate this option select the "Show Ads on "I'm in" checkbox.
If your app is recreating activity on config changes, then you don't need to do anything. If you are handling configuration changes by yourself, then you also have to pass config changes events to escs plugin. Here's how to do it:
Kotlin
Java
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
escsButton.onConfigurationChanged(newConfig)
escsWebView.onConfigurationChanged(newConfig)
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
escsButton.onConfigurationChanged(newConfig);
escsWebView.onConfigurationChanged(newConfig);
}
In order for your app to support escs' video chat and streaming capabilities you need to call back the plugin in some key lifecycle areas of your app. This is required so that plugin can receive audio and camera permission's result and also request screen recoding for streaming. If your app also overrides these methods, just add call the escs methods before your own processing.
Kotlin
Java
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>, grantResults: IntArray
) {
EscsService.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
data?.let {
EscsService.onActivityResult(requestCode, resultCode, data)
}
}
public static void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
EscsService.INSTANCE.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
public static void onActivityResult(int requestCode, int resultCode, Intent data) {
EscsService.INSTANCE.onActivityResult(requestCode, resultCode, data);
}
With API 29 and higher Android became more strict with permissions and background services. If your app targets compileSdkVersion 29 and/or targetSdkVersion 29 or higher you need to add the following to your AndroidManifest.xml inside Application node:
<service
android:name="androidx.work.impl.foreground.SystemForegroundService"
android:foregroundServiceType="mediaProjection"
tools:node="replace" />
This directive will register a foreground service for streaming integration. Note that otherwise the app will crash when user gives permission for screen recoding. If your app targets API less than 29, then you don't need anything.
We support multiplayer games with different types of matches, matchmaking and so on. To be able to use this feature, you need to follow these steps:
- Create multiplayer tournament in the game dashboard
- Implement several callbacks in you game, which will be called in response to player's engagement with multiplayer tournament
Currently we provide 4 such callbacks:
- OnGameSetStart callback - is called when a game set is started by escs backend. This is moment when you should start your game or create lobby and await for players to join it. What is a "set"? It's just one multiplayer game that several players are playing simultaneously. It can be real multiplayer (e.g. they, for example, race each other on track in a racing game or are participating in a deathmatch 1vs1 or 2vs2 and so on), or even "singleplayer", meaning that they all play their own singleplayer game (like solving puzzles and the one who solves it faster is the winner). In this callback you will receive information about players that are playing this set, teams that players are in (i.e. 2vs2 game), metadata that is supplied with the player (supplied by registerInGamePlayerId) and global metadata that is set in the game dashboard
- OnGameSetEnd callback - is called when each player in the set has finished their game. this might be not necessary the same moment you end your multiplayer game - it is called when the escs backend processed all game end events from each participating player and saved their corresponding scores. You will receive matchId and setId as parameters
- OnMatchStart callback - is called when multiplayer match has started. Usually you will get this event right before getting OnGameSetStart. Each match consists of several game sets. You will receive matchId as parameter of this callback.
- OnMatchEnd callback - is called when multiplayer match has ended. That is when all the sets in the match has been played or timeout occurred. You will receive matchId as parameter of this callback
The following diagram may be helpful for understanding about aforementioned events:
To utilize these events you can call methods described below.
Kotlin
Java
EscsService.registerInGamePlayerId(playerId, playerMetadata)
EscsService.INSTANCE.registerInGamePlayerId(playerId, ingameMetadata);
where:
- playerId - your ingame player id (string). It will be passed along with OnGameSetStart callback when the game set will start
- ingameMetadata - your ingame metadata for this player (string)
In order to create minimal trivial multiplayer setup, you will just need to register OnGameSetStart event. Starting a game in response to this event and it's parameters is enough to use multiplayer features of escs.
Kotlin
Java
EscsService.registerGameSetStartCallback { data ->
Log.i("ESCS", "Set started: ${data.setId}, round: ${data.roundId}, players: ${data.participants[0][0].username} ${data.participants[1][0].username}")
}
where data is GameSetStartData object:
- setId - setId of started set (string)
- tournamentId - tournamentId of the set (string)
- matchId - matchId of the set (string)
- roundId - roundId of the set (this is in fact id of the set "results") (string)
- globalMetadata - metadata string that can be set in the game dashboard (string)
- setEndTimeUnix - game's set max end time in unix time
- pariticipants - list of lists of Participant. Each sub-list is considered a "team". So if the game is 2vs2, then you will get list of 2 lists, each having 2 objects inside. Those 2 lists are 2 lists with 2 players each. In case of 1vs1 game, you will receive a list of 2 lists, each having 1 object inside - thus the team contains only one player. Participant object consists of:
- playerId - escs player id (string)
- ingamePlayerId - registered in-game player id via registerInGamePlayerId (string)
- username - user's escs username (string)
- firstName - user's escs first name (string)
- lastName - user's escs last name (string)
- avatar - user's escs avatar image url (string)
- ingameMetadata - in-game metadata that was registered via registerInGamePlayerId (string)
EscsService.INSTANCE.registerGameSetStartCallback(gameSetStartData -> {
Log.i("ESCS", "gameSetStartData " + (gameSetStartData != null ? gameSetStartData.toString() : " no gameSetStartData received"));
return Unit.INSTANCE;
});
where data is GameSetStartData object:
- getSetId() - setId of started set (string)
- getTournamentId() - tournamentId of the set (string)
- getMatchId() - matchId of the set (string)
- getRoundId() - roundId of the set (this is in fact id of the set "results") (string)
- getGlobalMetadata() - metadata string that can be set in the game dashboard (string)
- getSetEndTimeUnix() - game's set max end time in unix time (long)
- getPariticipants() - list of lists of Participant. Each sub-list is considered a "team". So if the game is 2vs2, then you will get list of 2 lists, each having 2 objects inside. Those 2 lists are 2 lists with 2 players each. In case of 1vs1 game, you will receive a list of 2 lists, each having 1 object inside - thus the team contains only one player. Participant object consists of:
- getPlayerId() - escs player id (string)
- getIngamePlayerId() - registered in-game player id via registerInGamePlayerId (string)
- getUsername() - user's escs username (string)
- getFirstName() - user's escs first name (string)
- getLastName() - user's escs last name (string)
- getAvatar() - user's escs avatar image url (string)
- getIngameMetadata() - in-game metadata that was registered via registerInGamePlayerId (string)
Kotlin
Java
EscsService.registerGameSetEndCallback {
Log.i("ESCS", "Set ended: ${it.setId} of match ${it.matchId}" )
}
where argument of lambda is GameSetEndData object:
- setId - setId of finished set (string)
- matchId - matchId of the set (string)
EscsService.INSTANCE.registerGameSetEndCallback(gameSetEndData -> {
Log.i("ESCS", "gameSetEndData " + (gameSetEndData != null ? gameSetEndData.toString() : " no gameSetEndData received"));
return Unit.INSTANCE;
});
where argument of lambda is GameSetEndData object:
- getSetId() - setId of finished set (string)
- getMatchId() - matchId of the set (string)
Kotlin
Java
EscsService.registerMatchStartCallback {
Log.i("ESCS", "Match started: ${it.matchId}" )
}
where argument of lambda is GameMatchStartData object:
- matchId - is matchId of the match that started (string)
EscsService.INSTANCE.registerMatchStartCallback(matchStartData -> {
Log.i("ESCS", "matchStartData " + (matchStartData != null ? matchStartData.toString() : " no matchStartData received"));
return Unit.INSTANCE;
});
where argument of lambda is GameMatchStartData object:
- getMatchId() - is matchId of the match that started (string)
Kotlin
Java
EscsService.registerMatchEndCallback {
Log.i("ESCS", "Match ended: ${it.matchId}" )
}
where argument of lambda is GameMatchStartData object:
- matchId - is matchId of the match that just ended(string)
EscsService.INSTANCE.registerMatchEndCallback(matchEndData -> {
Log.i("ESCS", "matchEndData " + (matchEndData != null ? matchEndData.toString() : " no matchEndData received"));
return Unit.INSTANCE;
});
where argument of lambda is GameMatchStartData object:
- getMatchId() - is matchId of the match that just ended(string)
Last modified 1yr ago