Платформа J2ME состоит главным образом из конфигураций и профилей, которые вместе образуют завершенную Java среду для ограниченных в ресурсах устройств с различными дополнительными возможностями. Иногда имеет смысл выделить программный интерфейс приложения (API) в отдельный пакет. В J2ME такие дополнительные пакеты содержат наборы классов и других ресурсов, которые могут использоваться различными профилями.
Как и все другие компоненты J2ME, дополнительные пакеты определены как Java Specification Requests (JSR) через Java Community Process. Одним из самых используемых J2ME пакетов, несомненно, является JSR-120 - Wireless Messaging API (WMA) (Интерфейс радио сообщений). Он используется приложениями для отправки и получения коротких текстовых и бинарных сообщений (SMS).
WMA основан на Generic Connection Framework (GCF), которая в свою очередь является частью Connected Limited Device Configuration (CLDC). GCF обеспечивает абстрактную структуру для реализации процессов ввода и вывода. На основе этой структуры строится ввод/вывод соединений, реализованных в профилях и дополнительных пакетах. Основная часть этого документа предполагает, что Вы немного знакомы с GCF. Если это не так, прочитайте сначала статью "Реализация соединения в CLDC". GCF - это часть Connected Device Configuration (CDC), поэтому вы можете использовать WMA на любом устройстве, поддерживающем J2ME (конечно, если производитель устройства включил в него необходимые классы).
WMA осуществляет передачу и получение сообщений по GSM или CDMA беспроводным сетям. Интерфейс использует коммуникационные возможности телефона. WMA поддерживает сервисы SMS и CBS. Хотя WMA сообщения похожи на датаграммы, интерфейс датаграмм не используется (который тоже является частью GCF и предназначен для реализации UDP соединений). Вместо этого WMA определяет новый набор интерфейсов (пакет javax.wireless.messaging).
Для отправки или получения сообщений, приложение должен сначала получить экземпляр MessageConnection интерфейса, используя механизмы подключений GCF. URL, содержащий информацию об используемом протоколе (SMS или CBS), номере телефона и порте адресата, передается методу javax.microedition.io.Connector.open(). Ниже приведены несколько примеров URL:
sms://+417034967891
sms://+417034967891:5678
sms://:5678
cbs://:5678
В первых двух случаях URL открывает клиентские соединения, через которое приложение подключается к серверу на удаленном устройстве. Если порт не указан, применяется значение по умолчанию - порт текстовых сообщений. Третий URL открывает серверное соединение на локальном устройстве, и ожидает входящих сообщений от других устройств.
Последний URL позволяет приложению получать широковещательные сообщения оператора сети.
Ниже приведен пример, создающий клиентское SMS соединение.
import javax.microedition.io.*; import javax.wireless.messaging.*; ..... MessageConnection conn=null; String url="sms://+417034967891"; try{ conn=(MessageConnection) Connector.open( url); // делаем что-нибудь с соединением } catch( Exception e){ // Если произошла ошибка } finally{ if( conn!=null){ try{ conn.close();} catch( Exception e){} } }
Для отправки сообщения используется метод MessageConnection.newMessage(), который создает пустое сообщение, добавляет в него полезную информацию (текст или бинарные данные) и вызывает метод MessageConnection.send() для его отправки.
public void sendText( MessageConnection conn, String text) throws IOException, InterruptedIOException{ TextMessage msg= conn.newMessage( conn.TEXT_MESSAGE); msg.setPayloadText( text); conn.send( msg); }
Посылка бинарных данных практически идентична:
public void sendBinary( MessageConnection conn, byte[] data) throws IOException, InterruptedIOException{ BinaryMessage msg= conn.newMessage( conn.BINARY_MESSAGE); msg.setPayloadData( data); conn.send( msg); }
Объем данных, которые можно переслать за одно подключение ограничен. Обычно размер SMS не превышает 160-170 символов, а если используются не английские символы - то еще меньше. Бинарные сообщения ограничены 140 байтами. Если размер сообщения превышает максимально возможный, WMA требуется поддержка каскадирования сообщений, что фактически означает еще большее ограничение объема сообщения. Чтобы определить можно ли отправить сообщение за один раз или его нужно разбить на несколько более мелких, используется метод MessageConnection.numberOfSegments().
Получать сообщения проще чем отправлять. После открытия соединения, нужно вызывать метод receive() , который возвращает следующее доступное на указанном порте сообщение. Если доступных сообщений нет, метод блокируется до тех пор пока не поступит новое сообщение или пока соединение не будет закрыто.
import java.io.*; import javax.microedition.io.*; import javax.wireless.messaging.*; MessageConnection conn=null; String url="sms://:5678";// Здесь должен быть указан только порт! try{ conn=(MessageConnection) Connector.open( url); while(true){ Message msg= conn.receive();// блоки if( msg instanceof BinaryMessage){ byte[] data= ((BinaryMessage) msg).getPayloadData(); // что-нибудь делаем }else{ String text= ((TextMessage) msg).getPayloadText(); // что-нибудь делаем } } } catch( Exception e){ // ошибка } finally{ if( conn!=null){ try{ conn.close();} catch( Exception e){} } }
WMA отвечает только за отправку и получение сообщений и никак их не интерпретирует. Как правило, для обмена данными между приложениями используются бинарные сообщения. Значительно облегчают жизнь методы DataInputStream, DataOutputStream, ByteArrayInputStream и ByteArrayOutputStream, которые позволяют эффективно кодировать и декодировать любые данные в бинарные сообщения и обратно.
Вы можете ознакомиться с более полным описанием WMA здесь:
http://java.sun.com/products/wma/
http://jcp.org/aboutJava/communityprocess/final/jsr120/index.html.