Version: 1.6
Copyright © 2012 Smaxe Ltd
Table of Contents
List of Examples
JUV RTMP Client is a lightweight library that provides RTMP/RTMPT-enabled server access API for Java applications.
Features:
Related:
JUV RTMP Client (J2ME edition) - J2ME RTMP client
JUV RTMP Researcher - RTMP protocol debugger application
JUV RTMP Tester - RTMP functional/regression/load testing library
JUV RTMP Client library consists of the only JAR file (no dependencies) that should be placed in the application's class path.
It requires the license key: either Evaluation Key (get it) or Developer Key (buy it).
Java RTMP Client 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.uv.client.rtmp package:
Every method invoked by the server is processed by the IMethodInvoker instance.
public interface IMethodInvoker { /** * InvokesThe default implementation is based on reflection (com.smaxe.uv.invoker.support.MethodInvoker).method
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); }
Every custom Java object that is sent/received to/from the server must be presented as ClassObject, i.e. class name + {property : property value} map. The IObjectCreator implementation is responsible for the such transformation.
public interface IObjectCreator { /** * Converts {@link ClassObject co} to the custom type object. * * @param coA simple implementation of IObjectCreator may look like: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 asClassObject
* @returnClassObject
instance */ public ClassObject toClassObject(final Object o); }
/** * Simple class we want to send to the RTMP server. */ public class CustomClass extends Object { public int field1; public String field2; } /** * IObjectCreator implementation. */ public class ObjectCreator implements IObjectCreator { public ClassObject toClassObject(final Object o) { if (o instanceof CustomClass) { final CustomClass cc = (CustomClass) o; Map propertyValues = new HashMap(); propertyValues.put("field1", cc.field1); propertyValues.put("field2", cc.field2); return new ClassObject("CustomClass", propertyValues); } else { // process other classes } } 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; } else { // process other classes } } // other methods necessary for amf3 serializing/deserializing }
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.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);
}
You can define proxy server to use. Proxy instance is used as Socket constructor parameter. The default value is Proxy.NO_PROXY.
Example 4.1. Set license key
com.smaxe.uv.client.rtmp.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, -1 /*seconds, -1 means indefinite timeout*/); 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 INetConnection source, final Map 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/live", "arg1", "arg2" /*arguments*/); // wait till NetConnection.CONNECT_SUCCESS message is received // ... waiting ... // invoke server method connection.call("testConnection", new com.smaxe.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 Map status) { System.out.println("Method testConnection status: " + status); } }, "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 ISharedObject.ListenerAdapter() { // note: this method is invoked in the Scheduler-Thread public void onSync(ISharedObject source, final List changeList) { for (ISharedObject.Change change : changeList) { switch (change.code) { case ISharedObject.Change.CONNECT: { // connected to the remote shared object } break; case ISharedObject.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 local FLV file as live stream
NetConnection connection = new NetConnection(); // ... configure and connect ... NetStream stream = new NetStream(connection); stream.addEventListener(new NetStream.ListenerAdapter() { @Override public void onNetStatus(final INetStream source, final Map info) { final String code = (String) info.get("code"); if (NetStream.PUBLISH_START.equals(code)) { } else if (NetStream.UNPUBLISHED_SUCCESS.equals(code)) { } } }); final MediaStreamController controller = new MediaStreamController(); stream.attachAudio(new MediaStreamMicrophone(controller)); stream.attachCamera(new MediaStreamCamera(controller), -1); stream.publish("streamName", NetStream.LIVE); controller.play(new FlvFileMediaStream("stream.flv"), -1 /*play the whole file*/);
Example 4.6. Publish audio source as live stream (ExRtmpVoicePublisher.java)
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 INetStream 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();