转载地址:http://blog.csdn.net/lancees/article/details/8951679
本例所采用的upnp框架是Platinum SDK
官方网址是http://www.plutinosoft.com/platinum
该库是一个跨平台的C++库,利用该库,可以很容易就构建出DLNA/UPnP控制点 (DLNA/UPnP Control Point)和DLNA/UPnP设备(DLNA/UPnP Device),其中包括有UPnP AV Media Server, Media Render & Control Point的例子
该库稳定强大,被很多知名产品所沿用,口碑较好自然也为楼主所青睐
关于该库如何编译,请参考这篇博文:NDK下 将Platinum SDK 编译成so库
下面给出运行效果图:
JNI接口文件:
- public class PlatinumJniProxy {
- static {
- System.loadLibrary("git-platinum");
- }
- public static native int startMediaRender(byte[] friendname ,byte[] uuid);
- public static native int stopMediaRender();
- public static native boolean responseGenaEvent(int cmd, byte[] value ,byte[] data);
- public static native boolean enableLogPrint(boolean flag);
- public static int startMediaRender(String friendname ,String uuid){
- if (friendname == null)friendname = "";
- if (uuid == null)uuid = "";
- int ret = -1;
- try {
- ret = startMediaRender(friendname.getBytes("utf-8"), uuid.getBytes("utf-8"));
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- return ret;
- }
- public static boolean responseGenaEvent(int cmd, String value, String data){
- if (value == null)value = "";
- if (data == null)data = "";
- boolean ret = false;
- try {
- ret = responseGenaEvent(cmd, value.getBytes("utf-8"), data.getBytes("utf-8"));
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- return ret;
- }
- }
反射类:
- public class PlatinumReflection {
- private static final CommonLog log = LogFactory.createLog();
- private static final int MEDIA_RENDER_CTL_MSG_BASE = 0x100;
- /*----------------------------------------------------------------*/
- public static final int MEDIA_RENDER_CTL_MSG_SET_AV_URL = (MEDIA_RENDER_CTL_MSG_BASE+0);
- public static final int MEDIA_RENDER_CTL_MSG_STOP = (MEDIA_RENDER_CTL_MSG_BASE+1);
- public static final int MEDIA_RENDER_CTL_MSG_PLAY = (MEDIA_RENDER_CTL_MSG_BASE+2);
- public static final int MEDIA_RENDER_CTL_MSG_PAUSE = (MEDIA_RENDER_CTL_MSG_BASE+3);
- public static final int MEDIA_RENDER_CTL_MSG_SEEK = (MEDIA_RENDER_CTL_MSG_BASE+4);
- public static final int MEDIA_RENDER_CTL_MSG_SETVOLUME = (MEDIA_RENDER_CTL_MSG_BASE+5);
- public static final int MEDIA_RENDER_CTL_MSG_SETMUTE = (MEDIA_RENDER_CTL_MSG_BASE+6);
- public static final int MEDIA_RENDER_CTL_MSG_SETPLAYMODE = (MEDIA_RENDER_CTL_MSG_BASE+7);
- public static final int MEDIA_RENDER_CTL_MSG_PRE = (MEDIA_RENDER_CTL_MSG_BASE+8);
- public static final int MEDIA_RENDER_CTL_MSG_NEXT = (MEDIA_RENDER_CTL_MSG_BASE+9);
- /*----------------------------------------------------------------*/
- /*----------------------------------------------------------------*/
- /*
- *
- *
- * */
- public static final int MEDIA_RENDER_TOCONTRPOINT_SET_MEDIA_DURATION = (MEDIA_RENDER_CTL_MSG_BASE+0);
- public static final int MEDIA_RENDER_TOCONTRPOINT_SET_MEDIA_POSITION = (MEDIA_RENDER_CTL_MSG_BASE+1);
- public static final int MEDIA_RENDER_TOCONTRPOINT_SET_MEDIA_PLAYINGSTATE = (MEDIA_RENDER_CTL_MSG_BASE+2);
- /*----------------------------------------------------------------*/
- public static final String RENDERER_TOCONTRPOINT_CMD_INTENT_NAME="com.geniusgithub.platinum.tocontrolpointer.cmd.intent";
- public static final String GET_RENDERER_TOCONTRPOINT_CMD="get_dlna_renderer_tocontrolpointer.cmd";
- public static final String GET_PARAM_MEDIA_DURATION="get_param_media_duration";
- public static final String GET_PARAM_MEDIA_POSITION="get_param_media_position";
- public static final String GET_PARAM_MEDIA_PLAYINGSTATE="get_param_media_playingstate";
- /*----------------------------------------------------------------*/
- public static final String MEDIA_PLAYINGSTATE_STOP="STOPPED";
- public static final String MEDIA_PLAYINGSTATE_PAUSE="PAUSED_PLAYBACK";
- public static final String MEDIA_PLAYINGSTATE_PLAYING="PLAYING";
- public static final String MEDIA_PLAYINGSTATE_TRANSTION="TRANSITIONING";
- public static final String MEDIA_PLAYINGSTATE_NOMEDIA="NO_MEDIA_PRESENT";
- /*----------------------------------------------------------------*/
- public static final String MEDIA_SEEK_TIME_TYPE_REL_TIME="REL_TIME";
- public static final String MEDIA_SEEK_TIME_TYPE_TRACK_NR="TRACK_NR";
- public static interface ActionReflectionListener{
- public void onActionInvoke(int cmd,String value,String data);
- }
- private static ActionReflectionListener mListener;
- public static void onActionReflection(int cmd,String value,String data){
- if (mListener != null){
- mListener.onActionInvoke(cmd, value, data);
- }
- }
- public static void setActionInvokeListener(ActionReflectionListener listener){
- mListener = listener;
- }
- }
工作线程 DMRWorkThread
- public class DMRWorkThread extends Thread implements IBaseEngine{
- private static final CommonLog log = LogFactory.createLog();
- private static final int CHECK_INTERVAL = 30 * 1000;
- private Context mContext = null;
- private boolean mStartSuccess = false;
- private boolean mExitFlag = false;
- private String mFriendName = "";
- private String mUUID = "";
- private RenderApplication mApplication;
- public DMRWorkThread(Context context){
- mContext = context;
- mApplication = RenderApplication.getInstance();
- }
- public void setFlag(boolean flag){
- mStartSuccess = flag;
- }
- public void setParam(String friendName, String uuid){
- mFriendName = friendName;
- mUUID = uuid;
- mApplication.updateDevInfo(mFriendName, mUUID);
- }
- public void awakeThread(){
- synchronized (this) {
- notifyAll();
- }
- }
- public void exit(){
- mExitFlag = true;
- awakeThread();
- }
- @Override
- public void run() {
- log.e("DMRWorkThread run...");
- while(true)
- {
- if (mExitFlag){
- stopEngine();
- break;
- }
- refreshNotify();
- synchronized(this)
- {
- try
- {
- wait(CHECK_INTERVAL);
- }
- catch(Exception e)
- {
- e.printStackTrace();
- }
- }
- if (mExitFlag){
- stopEngine();
- break;
- }
- }
- log.e("DMRWorkThread over...");
- }
- public void refreshNotify(){
- if (!CommonUtil.checkNetworkState(mContext)){
- return ;
- }
- if (!mStartSuccess){
- stopEngine();
- try {
- Thread.sleep(200);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- boolean ret = startEngine();
- if (ret){
- mStartSuccess = true;
- }
- }
- }
- @Override
- public boolean startEngine() {
- if (mFriendName.length() == 0){
- return false;
- }
- int ret = PlatinumJniProxy.startMediaRender(mFriendName, mUUID);
- boolean result = (ret == 0 ? true : false);
- mApplication.setDevStatus(result);
- return result;
- }
- @Override
- public boolean stopEngine() {
- PlatinumJniProxy.stopMediaRender();
- mApplication.setDevStatus(false);
- return true;
- }
- @Override
- public boolean restartEngine() {
- setFlag(false);
- awakeThread();
- return true;
- }
- }
通过startMediaRender开启设备后就可以被外界所发现,控制点发送控制信息后
动作action的回调通过反射类PlatinumReflection的静态方法onActionReflection执行
GENA事件则通过PlatinumJniProxy类的responseGenaEvent传递
详情大家down code去了解吧
Github下载页:https://github.com/geniusgithub/MediaRender
DLNA开发文档链接:http://download.csdn.net/detail/geniuseoe2012/4969961
关于SO库的具体C++实现可参考这篇博文:
http://blog.csdn.net/lancees/article/details/9178385
DMS的实现请参考这篇博文:基于Platinum库的DMS实现(android)
more brilliant,Please pay attention to my CSDN blog -->http://blog.csdn.net/geniuseoe2012