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
{
/**
* Invokes method with the args of the object o.
* 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 co ClassObject instance
* @return custom object
*/
public Object toObject(final ClassObject co);
/**
* Converts {@link Object o} to the {@link ClassObject} instance.
*
* @param o object to represent as ClassObject
* @return ClassObject 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();