Overview
EMDK for Android 7.3 (and later) contains interfaces for controlling hardware that conforms to the Infrared Data Association (IrDA) specification, an infrared line-of-sight technology that's used for data transfer between small portable devices such as mobile computers, printers, handheld remote controls and some medical devices. IrDA also refers to the protocols used for wireless data transfer using IrDA-equipped devices.
Zebra's IrDA implementation supports the following protocols:
- TinyTP
- IrLMP
- IrLAP/ LSAP
- IrSIR
Zebra IrDA APIs operate through Android intents – specific commands that can be used by Android applications to control IrDA hardware on IrDA-equipped Zebra devices. This guide explains how to communicate wirelessly between IrDA devices using IrDA Intent APIs on Zebra mobile devices.
Requirements
Use of IrDA APIs requires experience with Java and Android app development, and familiarity with Android intents. For successful IrDA communication, target device(s) must contain:
- One or more IrDA-equipped Zebra devices
- DataWedge version 7.3.11 or later on the device
- IrDA transceivers in clear line of sight during data transmission
IrDA Intent APIs
IrDA intent APIs can be used in applications that require control of IrDA communication. Supported intent actions and commands are listed below.
IrDA Intents and Actions:
com.symbol.irda.api.ACTION_DO
:- Send data
- Send data
com.symbol.irda.api.ACTION_GET
:- Get server name
- Get driver version
- Get connection idle time
com.symbol.irda.api.ACTION_REGISTER
:- Register/Unregister callbacks
- Register/Unregister callbacks
com.symbol.irda.api.ACTION_UPDATE
:- Set server name
- Set connection idle time
Usage information for each command follows in the sections below.
Send Data
To send data over IrDA, data must be converted to byte arrays. Large data is broken into small chunks of bytes prior to delivery to the receiving device. The first SEND_DATA
command typically requires extra time to complete; SEND_DATA
commands sent within 30 seconds of the first complete more quickly. The 30-second time frame is adjustable; see Set Connection Idle Time section for details.
Sample Code
To send data via IrDA:
Intent intent = new Intent(); //Create new intent
//Specify the IrDA action
intent.setAction("com.symbol.irda.api.ACTION_DO");
//Set to run at foreground priority, with a shorter timeout interval
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
//Text to be sent over IrDA
String text = "Hello IrDA";
//Convert to byte array to be accepted by SEND_DATA
byte[] byteArray = text.getBytes();
//Supported value up to 1024 bytes
intent.putExtra("SEND_DATA", byteArray);
//Designate the broadcast receiver to receive the response
Intent responseIntent = new Intent(getApplicationContext(), MyBroadcastReceiver.class);
//Set to run at foreground priority, with a shorter timeout interval
responseIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
//Any extras are useful to identify feedback
responseIntent.putExtra("COMMAND", "SEND_DATA");
//Create pending intent
PendingIntent piResponse = PendingIntent.getBroadcast(getApplicationContext().getApplicationContext(), REQUEST_CODE, responseIntent, PendingIntent.FLAG_UPDATE_CURRENT);
//Send pending intent as CALLBACK_RESPONSE
//IrDA API responds to the pending intent specified here
intent.putExtra("CALLBACK_RESPONSE", piResponse);
//Send the broadcast
sendBroadcast(intent);
To determine command success, see Get Feedback for Commands.
Set Server Name
For IrDA communication, the Zebra device serves as the “client” and the device it communicates with is the “server." To identify the device it communicates with, set the server name of the device. If a server name is not specified, the default “IrDA:TinyTP” is used.
Sample Code
Set the server name:
//Create new intent
Intent intent = new Intent();
//Specify the IrDA action
intent.setAction("com.symbol.irda.api.ACTION_UPDATE");
//Set to run at foreground priority with a shorter timeout interval
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
//Server name to be used
intent.putExtra("SERVER_NAME", "<NEW SERVER NAME>");
//Mention the broadcast receiver to receive the response
Intent responseIntent = new Intent(getApplicationContext(), MyBroadcastReceiver.class);
//Set to run at foreground priority with a shorter timeout interval
responseIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
//Any extras are useful to identify feedback
responseIntent.putExtra("COMMAND", "SET_SERVER_NAME");
//Create pending intent
PendingIntent piResponse = PendingIntent.getBroadcast(getApplicationContext().getApplicationContext(), REQUEST_CODE, responseIntent, PendingIntent.FLAG_UPDATE_CURRENT);
//Send pending intent as CALLBACK_RESPONSE
//IrDA API responds to the pending intent specified here
intent.putExtra("CALLBACK_RESPONSE", piResponse);
//Send the broadcast
sendBroadcast(intent);
The new server name is kept in device memory until device restart, after which the server name is reset to the “IrDA:TinyTP” default server name. To determine command success, see Get Feedback for Commands.
Register Callbacks
The application must be registered for callbacks to receive messages or responses from the server. Once the callback is processed, the application can act accordingly depending on the response received.
Sample Code
Register and receive callbacks from the server:
//Create new intent
Intent intent = new Intent();
//Specify the IrDA action
intent.setAction("com.symbol.irda.api.ACTION_REGISTER");
//Set to run at foreground priority, with a shorter timeout interval
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
//Intent to be sent back with status (via explicit broadcast)
Intent responseIntent = new Intent(this, MyBroadcastReceiver.class);
//Cross-check the extras specified here vs the intent received to the broadcast receiver to identify the related response
responseIntent.putExtra("COMMAND", "REGISTER_CALLBACK_CALL");
//Set to run at foreground priority, with a shorter timeout interval
responseIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
PendingIntent piResponse = PendingIntent.getBroadcast(getApplicationContext(), REQUEST_CODE, responseIntent, PendingIntent.FLAG_UPDATE_CURRENT);
//Send pending intent as CALLBACK_RESPONSE
//IrDA API responds to the pending intent specified here
intent.putExtra("CALLBACK_RESPONSE", piResponse);
//Intent called whenever data is received from the server
int flags2 = 0;
int requestCode2 = 3;
Intent dataCallBackIntent = new Intent(this, MyBroadcastReceiver.class);
dataCallBackIntent.putExtra("COMMAND", "REGISTERED_CALLBACK_DATA");
//Set to run at foreground priority, with a shorter timeout interval
dataCallBackIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
PendingIntent piDataCallback = PendingIntent.getBroadcast(getApplicationContext(), requestCode2, dataCallBackIntent, flags2);
//Send pending intent as DATA_CALLBACK
//IrDA API responds to the pending intent specified here when a data is received from the server
intent.putExtra("DATA_CALLBACK", piDataCallback);
//Send the broadcast
sendBroadcast(intent);
After executing the code above, callbacks from the server are delivered to the broadcast receiver.
The extras specified for the dataCallBackIntent
versus the broadcast receiver intent can be cross-checked to identify the related response as follows:
Check the COMMAND parameter:
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String command = intent.getStringExtra("COMMAND");
String status = "";
if(command != null && command.equalsIgnoreCase("REGISTERED_CALLBACK_DATA")) {
byte[] data = intent.getByteArrayExtra("DATA_CALLBACK");
status += " "+ data.length + " bytes received!";
}
Log.d("TAG",status);
}
}
To receive the response from the server, extract the information from DATA_CALLBACK
.
Unregister Callbacks
For each callback that is registered, a corresponding call is needed to unregister the callback. Set the DATA_CALLBACK parameter to NULL to unregister the callback.
Sample Code
Unregister the callback:
//Create new intent
Intent intent = new Intent();
//Specify the IrDA action
intent.setAction("com.symbol.irda.api.ACTION_REGISTER");
//Set to run at foreground priority, with a shorter timeout interval
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
//Mention the broadcast receiver to receive the response
Intent responseIntent = new Intent(this, MyBroadcastReceiver.class);
/Any extras are useful
responseIntent.putExtra("COMMAND", "UNREGISTER_CALLBACK_CALL"); /
Identify the feedback at broadcast receiver
//Create pending intent
PendingIntent piResponse = PendingIntent.getBroadcast(getApplicationContext(), REQUEST_CODE, responseIntent, PendingIntent.FLAG_UPDATE_CURRENT);
//Send pending intent as CALLBACK_RESPONSE
//IrDA API responds to the pending intent specified here
intent.putExtra("CALLBACK_RESPONSE", piResponse);
//Send DATA_CALLBACK as null to stop receiving callbacks from the server
intent.putExtra("DATA_CALLBACK", (String)null);
//Send the broadcast
sendBroadcast(intent);
Set Connection Idle Time
The IrDA port is opened when the first SEND_DATA
command is received. The port is kept open for 30 seconds by default. Within this time frame, subsequent SEND_DATA
commands are not needed to open the port again. After 30 seconds from the last IrDA API call, the port is closed. This time frame is adjustable by setting the connection idle time.
Sample Code
Set connection idle time:
//Create new intent
Intent intent = new Intent();
//Specify the IrDA action
intent.setAction("com.symbol.irda.api.ACTION_UPDATE");
//Set to run at foreground priority, with a shorter timeout interval.
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
//Set idle time to 15 seconds
intent.putExtra("CONNECTION_IDLE_TIME", 15);
//Mention the broadcast receiver to receive the response
Intent responseIntent = new Intent(getApplicationContext(), MyBroadcastReceiver.class);
//Set to run at foreground priority, with a shorter timeout interval.
responseIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
//Any extras are useful to identify the feedback at the broadcast receiver
responseIntent.putExtra("COMMAND", "SET_CONNECTION_IDLE_TIME");
PendingIntent piResponse = PendingIntent.getBroadcast(getApplicationContext().getApplicationContext(), REQUEST_CODE, responseIntent, PendingIntent.FLAG_UPDATE_CURRENT);
//Send pending intent as CALLBACK_RESPONSE
//IrDA API responds to the pending intent specified here
intent.putExtra("CALLBACK_RESPONSE", piResponse);
//Send the broadcast
sendBroadcast(intent);
To determine command success, see Get Feedback for Commands.
Get Command
The Get command retrieves the following properties:
CONNECTION_IDLE_TIME
- Returns the time (in seconds) the connection remains open before automatically closing
SERVER_NAME
- Returns the current server name
DRIVER_VERSION
- Driver version
Sample Code
Get driver version:
//Create new intent
Intent intent = new Intent();
//Specify the IrDA action
intent.setAction("com.symbol.irda.api.ACTION_GET");
//Set to run at foreground priority, with a shorter timeout interval
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
//Mention the properties to Retrieve
String[] propertiesToRetrieve = {"DRIVER_VERSION", "CONNECTION_IDLE_TIME", "SERVER_NAME"};
//Assign the properties to retrieve to PROPERTIES_TO_GET extra
intent.putExtra("PROPERTIES_TO_GET", propertiesToRetrieve);
//Mention the broadcast receiver to receive the response
Intent responseIntent = new Intent(getApplicationContext(), MyBroadcastReceiver.class);
//Set to run at foreground priority, with a shorter timeout interval
responseIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
//Any extras are useful to identify the feedback at the broadcast receiver
responseIntent.putExtra("COMMAND", "GET_DRIVER_VERSION");
//Create pending intent
PendingIntent piResponse = PendingIntent.getBroadcast(getApplicationContext().getApplicationContext(), REQUEST_CODE, responseIntent, PendingIntent.FLAG_UPDATE_CURRENT);
//Send pending intent as CALLBACK_RESPONSE
//IrDA API responds to the pending intent specified here.
intent.putExtra("CALLBACK_RESPONSE", piResponse);
//Send the broadcast
sendBroadcast(intent);
Decode the Get command response
The Get command response is delivered to the broadcast receiver in the pending intent to retrieve the queried data.
Retrieve data from the Get command:
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String status = "";
String command = intent.getStringExtra("COMMAND");
if(command != null) {
switch (command) {
case "GET_SERVER_NAME":
status += " "+ intent.getStringExtra("SERVER_NAME");
break;
case "GET_CONNECTION_IDLE_TIME":
status += " "+ intent.getIntExtra("CONNECTION_IDLE_TIME",0);
break;
case "GET_DRIVER_VERSION":
status += " "+ intent.getStringExtra("DRIVER_VERSION");
break;
}
}
Log.d("TAG",status);
}
}
Get Feedback for Commands
The ACTION_DO
and ACTION_UPDATE
methods send a RESULT_CODE
and a RESULT_MESSAGE
back to the client app with feedback about whether the specified command succeeded. This response is delivered to the broadcast receiver and passed to the pending intent.
Sample Code
Get feedback from commands:
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String status = "";
String command = intent.getStringExtra("COMMAND");
String resultCode = intent.getStringExtra("RESULT_CODE");
String resultMessage = intent.getStringExtra("RESULT_MESSAGE");
if(command != null)
status += "" + command + ": ";
if(resultCode != null)
status += "" + resultCode;
if(resultMessage != null)
status += "\nMessage: " + resultMessage;
Log.d("TAG",status);
}
}