This library manage all the complex connection process for you. You will find utility classes to simplify the processe of connecting to ZetaPush and calling services and macros.
Example of Android project that uses ZetaPush Android SDK
First of all, you have to create an account on ZetaPush
Add ZetaPush Nexus repository ('http://nexus.zpush.io:8080/repository/zetandroid/'
) to your main Gradle file (build.gradle
at root of your Android project):
...
allprojects {
repositories {
jcenter()
maven {
url "http://nexus.zpush.io:8080/repository/zetandroid/"
}
}
}
...
Then add the ZetaPush Android dependency 'compile com.zetapush:android-library:+'
to the application gradle file (app/build.gradle
):
...
dependencies {
...
compile 'compile com.zetapush:android-library:+'
}
...
Some dependencies embedded by ZetaPush SDK references classes that are not available in Android. The classes that are using missing classes are never used by ZetaPush SDK. The classes are mainly utilities provided by external libraries.
To disable lint checking, add lintOptions
section in android configuration (in app/build.gradle
file):
android {
...
lintOptions {
lintConfig file("lint.xml")
}
}
Creates a file named lint.xml
in app
directory with the following content:
<lint>
<issue id="InvalidPackage">
<ignore path="**/android-client*.jar"/>
</issue>
</lint>
To launch the connection to the ZetaPush platform, we need to have a ZetaPush Client. You need to create either a WeakClient or a SmartClient. The first one provides an anonymous authentication and the second one provides both an anonymous authentication and a simple authentication (we can choose during to connection).
WeakClient client = new WeakClient(MainActivity.this);
client.connect(SANDBOX_ID);
// or client.connect(SANDBOX_ID, DEPLOY_ID);
// or client.connect(SANDBOX_ID, DEPLOY_ID, resource);
The SANDBOX_ID
is the ID of your sandbox on the ZetaPush platform. Then, the DEPLOY_ID
is the id of your authentication service, by default this is weak_0. The resource
is a string to identify your application.
SmartClient client = new SmartClient(MainActivity.this);
client.connect(SANDBOX_ID);
// or client.connect(SANDBOX_ID, DEPLOY_ID);
// or client.connect(SANDBOX_ID, LOGIN, PASSWORD);
// or client.connect(SANDBOX_ID, LOGIN, PASSWORD, DEPLOY_ID);
// or client.connect(SANDBOX_ID, LOGIN, PASSWORD, DEPLOY_ID, resource);
The variables are the same that the WeakClient
. The LOGIN
and the PASSWORD
are the credentials for the user in his simple authentication. If you put credentials you will connect you as simple authentication, if not, as weak authentication.
client.disconnect();
To get the status connection, you need to create a BroadcastReceiver and listen on the differents events :
private ZetaPushConnectionReceiver zetaPushReceiver = new ZetaPushConnectionReceiver();
@Override
protected void onResume() {
super.onResume();
registerReceiver(zetaPushReceiver, new IntentFilter(ZetaPushService.FLAG_ACTION_BROADCAST));
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(zetaPushReceiver);
}
private class ZetaPushConnectionReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getStringExtra(ZetaPushService.FLAG_STATE_CONNECTION)) {
case ZetaPushService.FLAG_CONNECTION_ESTABLISHED:
Log.e("STATE CONNECTION", "Connection established");
break;
case ZetaPushService.FLAG_CONNECTION_CLOSED:
Log.e("STATE CONNECTION", "Connection closed");
break;
}
}
}
For example, here we only listen on the ConnectionEstablished
and ConnectionClosed
events. Here the list of connection events :
- SuccessfullHandshake
- FailedHandshake
- ConnectionEstablished
- ConnectionBroken
- ConnectionClosed
- MessageLost
To call macroscripts, you need to generate classes from your ZetaPush project. For this, you need to use the command line like this :
zms sdk -l java -i com.zetapush.monprojet -o /tmp/output_folder
// TODO : Provide the CLI and explain how to install it
Then you put the folder beside the package of your Activity in your Android code. When the classes are imported, you need to use a specific API to call macroscripts :
- Asynchrone API
- Synchrone API
- Future API
The name of your interfaces and classes are specifics to your project but you have an example for each case below. Because we use communication network you need to launch the macroscript calls outside the UI Thread.
To properly understand how to call macroscripts, we need to define some variables. First when we use "macro_0"
, this is the name of the macroscript service in your ZetaPush project. By default this is macro_0. The variable client
is your WeakClient
or SmartClient
object.
Then, the macroscript used to make our tests is named welcome
:
/**
* Takes a message as input, and returns it, with a server message
*/
macroscript welcome(/** message from the client */ string message = "Hello") {
// ...
} return {clientMessage : message, serverMessage : WELCOME_MESSAGE}
new Thread(new Runnable() {
@Override
public void run() {
try {
MacroSyncApi macroApi = MacroSyncApi.Factory.createService(client.getZetaPushClient(), "macro_0");
welcomeCompletion resultMacro = macroApi.welcome(new welcomeInput("test"));
Log.e("RESULT MACRO", resultMacro.getResult().toString());
}
}
}).start();
In this case, you need to create a listener that implements the AsyncApiListener.
private class MacroApiListener implements MacroAsyncApiListener {
@Override
public void welcome(welcomeCompletion notification) {
Log.e("RESULT WELCOME", notification.getResult().toString());
}
}
Then we can call our macroscripts :
new Thread(new Runnable() {
@Override
public void run() {
try {
MacroAsyncApi macroApi = MacroAsyncApi.Factory.createService(client.getZetaPushClient(), "macro_0");
MacroAsyncApiListener.Factory.registerListener(new MacroApiListener(), client.getZetaPushClient(), "macro_0");
macroApi.welcome(new welcomeInput("test"));
}
}
}).start();
private Future<welcomeCompletion> resultMacro;
...
new Thread(new Runnable() {
@Override
public void run() {
try {
MacroFutureApi macroApi = MacroFutureApi.Factory.createService(client.getZetaPushClient(), "macro_0");
resultMacro = macroApiFuture.welcome(new welcomeInput("test"));
}
}
}).start();
...
try {
welcomeCompletion output = resultMacro.get();
Log.e("RESULT MACRO", output.getResult().toString());
} catch (Exception e) {
e.printStackTrace();
}
For example if you don't want to save any data, you can use the NoTokenStorage
and NoCredentialsStorage
classes that implement the needed interfaces :
SmartClient client = new SmartClient(MainActivity.this, new NoTokenStorage(), new NoCredentialsStorage());
Of course you also can choose to implements yourself the methods to save, get and delete data. For example if you want to change the method to handle token :
SmartClient client = new SmartClient(MainActivity.this, new StorageTokenInterface() {
@Override
public void saveToken(String token) {
}
@Override
public String getToken() {
return null;
}
@Override
public void clearToken() {
}
});
The clients implements many other explicit methods. We list them :
- getUserKey()
- isConnected()
- canDoConnection()
- getSandboxId()
- getResource()
- setResource()
- getCredentials()
- hasCredentials()
- isStronglyAuthenticated()
- isWeaklyAuthenticated()
- getToken()
Here is a basic example with a button to launch the connection and another to call a macroscript. We use in our case the asynchrone API and a SmartClient.
public class MainActivity extends Activity {
private Button btnConnection;
private Button btnMacro;
private Thread threadMacro;
// ZetaPush variables
private SmartClient client;
private ZetaPushConnectionReceiver zetaPushReceiver = new ZetaPushConnectionReceiver();
private final String SANDBOX_ID = "nL_L8ZqL";
private final String LOGIN = "user";
private final String PASSWORD = "password";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create the ZetaPush Client
client = new SmartClient(MainActivity.this);
// UI
btnConnection = (Button) findViewById(R.id.btnConnection);
btnMacro = (Button) findViewById(R.id.btnMacro);
// buttons
btnConnection.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Launch the connection to the ZetaPush platform
client.connect(SANDBOX_ID, LOGIN, PASSWORD);
}
});
btnMacro.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// ZetaPush code to call macroscript (Asynchrone)
threadMacro = new Thread(new Runnable() {
@Override
public void run() {
MacroAsyncApi macroApi = MacroAsyncApi.Factory.createService(client.getZetaPushClient(), "macro_0");
MacroAsyncApiListener.Factory.registerListener(new MacroApiListener(), client.getZetaPushClient(), "macro_0");
macroApi.welcome(new welcomeInput("test"));
}
});
threadMacro.start();
}
});
}
@Override
protected void onResume() {
super.onResume();
registerReceiver(zetaPushReceiver, new IntentFilter(ZetaPushService.FLAG_ACTION_BROADCAST));
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(zetaPushReceiver);
}
@Override
protected void onDestroy() {
client.disconnect();
try {
threadMacro.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
super.onDestroy();
}
// BroadcastReceiver for the connection status of ZetaPush
private class ZetaPushConnectionReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getStringExtra(ZetaPushService.FLAG_STATE_CONNECTION)) {
case ZetaPushService.FLAG_CONNECTION_ESTABLISHED:
Log.e("STATE CONNECTION", "Connection established");
break;
case ZetaPushService.FLAG_CONNECTION_CLOSED:
Log.e("STATE CONNECTION", "Connection closed");
break;
}
}
}
private class MacroApiListener implements AndroidpreprodAsyncApiListener {
@Override
public void welcome(welcomeCompletion notification) {
Log.e("RESULT MACRO", notification.getResult().toString());
}
}
}
We have created an utility class call ZetaPushBaseActivity than you can use to help you share the ZetaPush service between your activities. If you have your main activity that create the WeakClient or SmarClient object, you can share the ZetaPushService by simply overiding onServiceAttached and onServiceDetached event.
If you have to create an API listener for your activity, don't forget to use a thread to instantiate it.
public class ChildActivity extends ZetaPushBaseActivity implements ZetaPushConnectionEvent {
private ZetapushClient zetapushClient;
private String userId;
private static final String TAG = ChildActivity.class.getSimpleName();
@Override
protected void onServiceAttached(ZetaPushService service) {
// do something necessary by its subclass.
Log.d(TAG, "onServiceAttached");
zetapushClient = service.getZetaPushClient();
//userId = zetapushClient.getUserId();
new Thread() {
public void run() {
try {
// Create here your futureAPI or API Listeners ?
//futureApi = VisioFutureApi.Factory.createService(zetapushClient, "macro_0");
//VisioAsyncApiListener.Factory.registerListener(ZetapushConnectActivity.this, zetapushClient, "macro_0");
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
@Override
protected void onServiceDetached() {
Log.d(TAG, "onServiceDetached");
new Thread() {
public void run() {
try {
// Unregister your API Listeners
//VisioAsyncApiListener.Factory.unregisterListener(ZetapushConnectActivity.this, zetapushClient);
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
@Override
public void successfulHandshake(Map<String, Object> map) {
Log.d(TAG, "successfulHandshake");
}
@Override
public void failedHandshake(Map<String, Object> map) {
Log.d(TAG, "failedHandshake");
}
@Override
public void connectionEstablished() {
Log.d(TAG, "connectionEstablished");
}
@Override
public void connectionBroken() {
Log.d(TAG, "connectionBroken");
}
@Override
public void connectionClosed() {
Log.d(TAG, "connectionClosed");
}
@Override
public void messageLost(String s, Object o) {
}
}