List of Examples
JUV RTMP Client (J2ME edition) (so-called J2ME RTMP client) is a lightweight library (200KB jar) that provides RTMP/RTMPT-enabled server access API for J2ME midlets.
Features:
Related:
JUV RTMP Client - J2SE RTMP client
JUV RTMP Researcher - RTMP debug tool
JUV RTMP Tester - RTMP functional/regression/load testing library
JUV RTMP Client (J2ME edition) library has a 2 jars: full version and lite version (no streaming support).
It requires the license key: either Evaluation Key (get it) or Developer Key (buy it).
JUV RTMP Client (J2ME edition) API is very similar to the API provided by Adobe® in the
ActionScript's flash.net.* package.
There are 3 core classes defined in com.smaxe.me.uv.client package:
Every method invoked by the server is processed by the IMethodInvoker instance. The default implementation (com.smaxe.me.uv.invoker.support.MethodInvoker) logs method invocation events to the System.out.
public interface IMethodInvoker { /** * Invokesmethod
with theargs
of the objecto
. * The result is returned through the {@link ICallback callback}. * * @param o object which method is invoked * @param method method to invoke * @param callback callback to receive invocation result * @param args method arguments */ public void invoke(final Object o, final String method, final ICallback callback, final Object[] args); }
Example 3.1. IMethodInvoker implementation example
public class MyMethodInvoker extends Object implements IMethodInvoker { // note: this method is invoked in the Dispatch-Thread public void invoke(final Object o, final String method, final ICallback callback, final Object[] args) { if (o instanceof NetConnectionCallback) { final NetConnectionCallback netConnectionCallback = (NetConnectionCallback) o; if ("test".equals(method)) { final boolean result = netConnectionCallback.test(); callback.onResult(new Boolean(result)); } } } }
Every custom Java object that is sent/received to/from the server must be presented as ClassObject, i.e. class name + {property : property value} hashtable. The IObjectCreator implementation is responsible for the such transformation.
public interface IObjectCreator { /** * Converts {@link ClassObject co} to the custom type object. * * @param coClassObject
instance * @return custom object */ public Object toObject(final ClassObject co); /** * Converts {@link Object o} to the {@link ClassObject} instance. * * @param o object to represent asClassObject
* @returnClassObject
instance */ public ClassObject toClassObject(final Object o); }
Example 3.2. IObjectCreator implementation example
public class CustomClass extends Object { public int field1; public String field2; } public class ObjectCreator implements IObjectCreator { public ClassObject toClassObject(final Object o) { if (o instanceof CustomClass) { final CustomClass cc = (CustomClass) o; Hashtable propertyValues = new Hashtable(); propertyValues.put("field1", cc.field1); propertyValues.put("field2", cc.field2); return new ClassObject("CustomClass", propertyValues); } } public Object toObject(final ClassObject co) { if ("CustomClass".equals(co.className)) { CustomClass cc = new CustomClass(); cc.field1 = (Integer) co.propertyValues.get("field1"); cc.field2 = (String) co.propertyValues.get("field2"); return cc; } } }
The library doesn't use any specific logging system. It provides a simple interface that lets you either integrate the library with any logging library or use ILogger implementations provided in the com.smaxe.me.logger.support package.
public interface ILogger
{
/**
* Logs the message.
*
* @param level message level
* @param message message to log
* @param t thrown exception, null
if the exception is not thrown
* @param args optional arguments
*/
public void log(final int level, final String message, final Throwable t, final Object[] args);
}
Cause of the asynchronous nature of client-server communication the methods invoked by the server are processed in the Dispatch-Thread (similar to the Event-Dispatch-Thread in Swing). This means that you have to process listener notifications in the separate executor thread.
Example 4.1. Set license key
com.smaxe.me.uv.client.License.setKey("00000-00000-00000-00000-00000");
Example 4.2. Create and configure NetConnection
NetConnection connection = new NetConnection(); // configure connection.configuration().put(NetConnection.Configuration.INACTIVITY_TIMEOUT, new Integer(10) /*seconds*/); connection.configuration().put(NetConnection.Configuration.PAGE_URL, "www.myhost.com/app"); // etc...
Example 4.3. Connect to the server and invoke server method
NetConnection connection = new NetConnection(); // configure connection (if necessary) // set callback object connection.client(new Object() { // note: this method is invoked in the Dispatch-Thread public boolean test() { System.out.println("NetConnectionCallback#test"); return true; } }); // add event listener to get notified about connection status change connection.addEventListener(new NetConnection.ListenerAdapter() { // note: this method is invoked in the Dispatch-Thread public void onNetStatus(final NetConnection source, final Hashtable info) { final Object code = info.get("code"); if (NetConnection.CONNECT_SUCCESS.equals(code)) { System.out.println("Connected to the server!"); } } }); connection.connect("rtmp://localhost:1935/app", new Object[] { "arg1", "arg2"} /*arguments*/); // wait till NetConnection.CONNECT_SUCCESS message is received // ... waiting ... // invoke server method connection.call("testConnection", new com.smaxe.me.uv.Responder() { // note: this method is invoked in the Dispatch-Thread public void onResult(final Object result) { System.out.println("Method testConnection result: " + result); } // note: this method is invoked in the Dispatch-Thread public void onStatus(final Hashtable status) { System.out.println("Method testConnection status: " + status); } }, new Object[] { "arg3", "arg4"} /*arguments*/);
Example 4.4. Connect to the remote shared object
NetConnection connection = new NetConnection(); // ... configure and connect ... SharedObject so = new SharedObject(name); so.addEventListener(new SharedObject.ListenerAdapter() { // note: this method is invoked in the Dispatch-Thread public void onSync(SharedObject source, final Vector changeList) { for (int i = 0, n = changeList.size(); i less n; i++) { final SharedObject.Change change = changeList.elementAt(i); switch (change.code) { case SharedObject.Change.CONNECT: { // connected to the remote shared object } break; case SharedObject.Change.CHANGE: { // change.attribute data was changed from the change.oldValue // to the change.newValue } break; case ISharedObject.Change.STATUS: { // shared object status notification } break; } } } }); so.connect(connection, name);
Example 4.5. Publish audio source as live stream
public final class MyMicrophone extends AbstractMicrophone { // starts microphone capture public void start() { new Thread(new Runnable() { while (true) { byte[] data = getAudioData(); // returns audio data captured from your source fireOnAudioData(new MediaDataByteArray(33 /*relative time*/, new ByteArray(data))); try { Thread.sleep(33); { catch (Exception e) {} } }).start(); } } NetConnection connection = new NetConnection(); // ... configure and connect ... NetStream stream = new NetStream(connection); stream.addEventListener(new NetStream.ListenerAdapter() { @Override public void onNetStatus(final NetStream source, final Map info) { final String code = (String) info.get("code"); if (NetStream.PUBLISH_START.equals(code)) { } else if (NetStream.UNPUBLISHED_SUCCESS.equals(code)) { } } }); MyMicrophone mic = new MyMicrophone(); stream.attachAudio(mic); stream.publish("streamName", NetStream.LIVE); mic.start();