基于Platinum库的DMR实现(android)

接上篇博文: 基于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去了解吧

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 brilliantPlease pay attention to my CSDN blog -->http://blog.csdn.net/geniuseoe2012 

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页