Communication Utils

Introduction

  • The Migration SDK provides a utility module for facilitating communication between M App and L App.

It's available in migration-client, migration-host SDK v0.9.3 or above.

  • Through this module, M App and L App will register each other as endpoints of the communication and the data will be passed back and forth in a secure way using a custom permission - protectionLevel="signature"

  • The module provides three kinds of communication methods tailored to its use case.

    • when a shared data storage is needed : DataStorage

    • when a one-way event posting is needed : EventHandler

    • when a complete server-client architecture is needed : RequestHandler

 

Choose an item below for more detailed guide.

DataStorage

  • DataStorage is useful when a shared data storage between L App and M App is needed.

  • Data is stored in a key-value structure.

Use case

The migration SDK uses DataStorage to determine whether the lock screen of the L app is active. The L app updates the value in the DataStorage whenever the lock screen is activated or deactivated, and the M app reads the value from the DataStorage when it wants to check the status of the L app.

How to use it

Access a DataStorage instance through MigrationXXX.getDataStorage()

1. Saving data

  • boolean put(String key, String value) : Stores value mapped to key.

    • Return true if successfully stored, or false if failed.

For one key, put must be called on one side only. Each app stores its data in its store when it calls put. It searches its store by calling get, and then searches the store of the other app if there is no value in its own store. If you put different values ​​for puts in both apps for the same key, they will be stored in their own repositories, so the values ​​will not be shared.

2. Data retrieval

  • String get(String key) : Synchronously retrieves the value mapped to the key and returns it.

  • void getAsync(String key, DataStorage.AsyncQueryListener listener) : Asynchronously retrieves the value mapped to key and passes it to AsyncQueryListener.

    • Parameters

      • AsyncQueryListener

        • void onQueryComplete(String value) : Invoked when the search is complete and value is passed as a parameter (null if none).

MigrationXXX.getDataStorage().put("SHARED_CONFIG_KEY", "config_value"); // Synchronous String value = MigrationXXX.getDataStorage().get("SHARED_CONFIG_KEY"); // Asynchronous MigrationXXX.getDataStorage().getAsync("SHARED_CONFIG_KEY", new DataStorage.AsyncQueryListener() { @Override public void onQueryComplete(String value) { } });

EventHandler

  • This is used when the event is forwarded from the Sender to the Receiver only in one direction.

    • The Sender and Receiver roles are not fixed for a specific app but depend on how it is used.

  • Since the name of each event is the key, both the Sender and the Receiver must use the same event name for one event.

  • Bundle is used to add additional information when delivering events.

How to use

Access an EventHandler instance through MigrationXXX.getEventHandler().

1. Sending events

  • void post(String eventName) : Send an event to a Receiver.

  • void post(String eventName, Bundle extras) : Sends an event to the Receiver with additional data in the form of a bundle.

2. Receiving events

  • void registerEventListener(String eventName, EventHandler.OnEventListener listener) : The logic for receiving a specific event is implemented in OnEventListener and registered by mapping it to eventName.

    • Parameters

      • OnEventListener

        • void onEvent(Bundle extras) : Invoked when an event is received, and additional data sent by the Sender is passed as a parameter (if additional data does not exist, an empty Bundle is passed instead of a null object).

// Sender Bundle eventData = new Bundle(); eventData.putString("extra_info", "extra_value"); MigrationXXX.getEventHandler().post("SAMPLE_EVENT", eventData); // Receiver MigrationXXX.getEventHandler().registerEventListener("SAMPLE_EVENT", new EventHandler.OnEventListener() { @Override public void onEvent(Bundle extras) { Log.d(TAG, "onReceive SAMPLE_EVENT"); String extraInfo = extras.getString("extra_info"); // "extra_value" returned ... } });

RequestHandler

  • Use when you need to organically process requests and responses between two apps, like a server-client structure.

    • The Server and Client roles are not fixed for a specific app but depend on how it is used.

  • Because each request-response pair is distinguished by a request code, both the server and the client must use the same request code.

  • Bundle is used for data exchanged between request and response.

How to use

Get a RequestHandler instance through MigrationXXX.getRequestHandler().

1. Server

  • void registerResponder(int requestCode, MsgRequestHandler.Responder responder) : Implement a response when a request comes from a client.

    • Parameters

      • requestCode : Unique code to distinguish requests

      • Responder

        • Bundle respond(Bundle parameters) : Called when a request comes from the client, and the parameters passed in are the additional parameters contained in the request. You must return the response in the Bundle.

2. Client

  • void request(int requestCode, Bundle params, Request.OnResponseListener listener): It sends a request to the server and implements a callback that handles the response.

    • Parameters

      • requestCode : Unique code to distinguish requests

      • params : If you need to pass parameters along with requests, pass it in bundle form.

      • OnResponseListener

        • void onResponse(Bundle response) : Invoked when communication with the server app is successful, and the server's response data is passed as a parameter (if response data does not exist, an empty Bundle is passed instead of a null object).

        • void onFail(Request.FailReason failReason) : Invoked when communication with the server app fails. The cause of the failure is passed as a parameter.

// Server MigrationXXX.getRequestHandler().registerResponder(1000, new MsgRequestHandler.Responder() { @Override public Bundle respond(Bundle parameters) { Bundle response = new Bundle(); response.putString("response_key", "response_sample"); return response; } }); // Client MigrationXXX.getRequestHandler().request(1000, null, new Request.OnResponseListener() { @Override public void onResponse(Bundle response) { String value = response.getString("response_key"); // "response_sample" returned ... } @Override public void onFail(Request.FailReason failReason) { } });