接上篇博文:​​ 基于CyberGarage库的dlna开发(android)​

文章讲述了用CyberGarage库的DMP实现

部分童鞋想知道DMR是如何实现的

网上似乎也没看到相关的android code

在下不才,自个儿捣鼓了project并上传至github

今与诸君共赏

 

 


本例所采用的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去了解吧