• 基于CyberGarage库的dlna开发(android)


    关于dlna的介绍就不多说了,具体可以看这篇博文http://blog.csdn.net/geniuseoe2012/article/details/8230877

    或者问百度谷歌

    Dlna通讯采用upnp协议,详看这篇博文:http://blog.csdn.net/geniuseoe2012/article/details/8132719

    或者问百度谷歌

    更多开发资料稍后再末尾附上

    我们在做DLNA开发的时候都是用现有的upnp开源框架,upnp官网地址是:

    http://upnp.org/

    相关SDK地址为http://upnp.org/sdcps-and-certification/resources/sdks/

    本文阐述的是基于CyberGarage库的DMP开发,ControlPoint是核心类

    关键方法有search();start(),stop(),addDeviceChangeListener(DeviceChangeListener listener)

    见名知意

     先上几张效果图:

     

    代码里将ControlPoint委托给service,外部通过与service的交互来执行相关操作

    public class DlnaService extends Service implements IBaseEngine,
    													DeviceChangeListener,
    													ControlCenterWorkThread.ISearchDeviceListener{
    	
    	private static final CommonLog log = LogFactory.createLog();
    	
    	public static final String SEARCH_DEVICES = "com.geniusgithub.allshare.search_device";
    	public static final String RESET_SEARCH_DEVICES = "com.geniusgithub.allshare.reset_search_device";
    	
    	private static final int NETWORK_CHANGE = 0x0001;
    	private boolean firstReceiveNetworkChangeBR = true;
    	private  NetworkStatusChangeBR mNetworkStatusChangeBR;
    	
    	
    	private  ControlPoint mControlPoint;
    	private  ControlCenterWorkThread mCenterWorkThread;
    	private  AllShareProxy mAllShareProxy;
    	private  Handler mHandler;
    	
    
    
    	@Override
    	public IBinder onBind(Intent intent) {
    		return null;
    	}
    	
    	@Override
    	public void onCreate() {
    		super.onCreate();
    		log.e("DlnaService onCreate");
    		init();
    	}
    	
    
    	@Override
    	public int onStartCommand(Intent intent, int flags, int startId) {
    		
    		if (intent != null && intent.getAction() != null){
    			String action = intent.getAction();
    			if (DlnaService.SEARCH_DEVICES.equals(action)) {
    				startEngine();
    			}else if (DlnaService.RESET_SEARCH_DEVICES.equals(action)){
    				restartEngine();
    			}
    		}else{
    			log.e("intent = " + intent);
    		}
    
    		return super.onStartCommand(intent, flags, startId);
    	}
    
    	@Override
    	public void onDestroy() {
    		log.e("DlnaService onDestroy");
    		unInit();
    		super.onDestroy();
    	}
    	
    	
    	private void init(){
    		mAllShareProxy = AllShareProxy.getInstance(this);
    		
    		mControlPoint = new ControlPoint();
    		AllShareApplication.getInstance().setControlPoint(mControlPoint);
    		mControlPoint.addDeviceChangeListener(this);
    		mControlPoint.addSearchResponseListener(new SearchResponseListener() {		
    			public void deviceSearchResponseReceived(SSDPPacket ssdpPacket) {
    			}
    		});
    	
    
    		mCenterWorkThread = new ControlCenterWorkThread(this, mControlPoint);
    		mCenterWorkThread.setSearchListener(this);
    		
    		mHandler = new Handler(){
    
    			public void handleMessage(Message msg) {
    				switch(msg.what){
    					case NETWORK_CHANGE:
    						mAllShareProxy.resetSearch();
    						break;
    				}
    			}
    			
    		};
    		
    		registerNetworkStatusBR();
    	}
    	
    	private void unInit(){
    		unRegisterNetworkStatusBR();
    		AllShareApplication.getInstance().setControlPoint(null);
    		mCenterWorkThread.setSearchListener(null);
    		mCenterWorkThread.exit();
    	}
    
    	
    	@Override
    	public boolean startEngine() {
    		awakeWorkThread();
    		return true;
    	}
    
    
    	@Override
    	public boolean stopEngine() {
    		exitWorkThread();
    		return true;
    	}
    
    
    	@Override
    	public boolean restartEngine() {
    		mCenterWorkThread.reset();
    		return true;
    	}
    
    
    
    
    	@Override
    	public void deviceAdded(Device dev) {
    		mAllShareProxy.addDevice(dev);
    	}
    
    
    	@Override
    	public void deviceRemoved(Device dev) {
    		mAllShareProxy.removeDevice(dev);
    	}
    	
    	
    	private void awakeWorkThread(){
    
    		if (mCenterWorkThread.isAlive()){
    			mCenterWorkThread.awakeThread();
    		}else{
    			mCenterWorkThread.start();
    		}
    	}
    	
    	private void exitWorkThread(){
    		if (mCenterWorkThread != null && mCenterWorkThread.isAlive()){
    			mCenterWorkThread.exit();
    			long time1 = System.currentTimeMillis();
    			while(mCenterWorkThread.isAlive()){
    				try {
    					Thread.sleep(100);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    			long time2 = System.currentTimeMillis();
    			log.e("exitCenterWorkThread cost time:" + (time2 - time1));
    			mCenterWorkThread = null;
    		}
    	}
    	
    	
    	@Override
    	public void onSearchComplete(boolean searchSuccess) {
    
    		if (!searchSuccess){
    			sendSearchDeviceFailBrocast(this);
    		}
    	}
    	
    	public static final String SEARCH_DEVICES_FAIL = "com.geniusgithub.allshare.search_devices_fail";
    	public static void sendSearchDeviceFailBrocast(Context context){
    		log.e("sendSearchDeviceFailBrocast");
    		Intent intent = new Intent(SEARCH_DEVICES_FAIL);
    		context.sendBroadcast(intent);
    	}
    	
    	private class NetworkStatusChangeBR extends BroadcastReceiver{
    
    		@Override
    		public void onReceive(Context context, Intent intent) {
    
    			if (intent != null){
    				String action = intent.getAction();
    				if (action != null){
    					if (action.equalsIgnoreCase(ConnectivityManager.CONNECTIVITY_ACTION)){
    						sendNetworkChangeMessage();
    					}
    				}
    			}
    			
    		}
    		
    	}
    	
    	private void registerNetworkStatusBR(){
    		if (mNetworkStatusChangeBR == null){
    			mNetworkStatusChangeBR = new NetworkStatusChangeBR();
    			registerReceiver(mNetworkStatusChangeBR, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
    		}
    	}
    	
    	private void unRegisterNetworkStatusBR(){
    		if (mNetworkStatusChangeBR != null){
    			unregisterReceiver(mNetworkStatusChangeBR);
    		}
    	}
    	
    	private void sendNetworkChangeMessage(){
    		if (firstReceiveNetworkChangeBR){
    			log.e("first receive the NetworkChangeMessage, so drop it...");
    			firstReceiveNetworkChangeBR = false;
    			return ;
    		}
    		
    		mHandler.removeMessages(NETWORK_CHANGE);
    		mHandler.sendEmptyMessageDelayed(NETWORK_CHANGE, 500);
    	}
    
    }



    Service内部开启一个线程来执行控制点的搜索,停止等命令 

    public class ControlCenterWorkThread extends Thread{
    
    private static final CommonLog log = LogFactory.createLog();
    	
    	private static final int REFRESH_DEVICES_INTERVAL = 30 * 1000; 
    	
    	public static interface ISearchDeviceListener{
    		public void onSearchComplete(boolean searchSuccess);
    	}
    	
    	private ControlPoint mCP = null;
    	private Context mContext = null;
    	private boolean mStartComplete = false;
    	private boolean mIsExit = false;
    	private ISearchDeviceListener mSearchDeviceListener;
    	
    	public ControlCenterWorkThread(Context context, ControlPoint controlPoint){
    		mContext = context;
    		mCP = controlPoint; 
    	}
    	
    	public void  setCompleteFlag(boolean flag){
    		mStartComplete = flag;
    	}
    	
    	public void setSearchListener(ISearchDeviceListener listener){
    		mSearchDeviceListener = listener;
    	}
    	
    	public void awakeThread(){
    		synchronized (this) {
    			notifyAll();
    		}
    	}
    	
    	
    	public void reset(){
    		setCompleteFlag(false);
    		awakeThread();
    	}
    	
    	public void exit(){
    		mIsExit = true;
    		awakeThread();
    	}
    	
    	
    	@Override
    	public void run() {
    		log.e("ControlCenterWorkThread run...");		
    		
    		while(true)
    		{
    			if (mIsExit){
    				mCP.stop();
    				break;
    			}
    			
    			refreshDevices();
    			
    			synchronized(this)
    			{		
    				try
    				{
    					wait(REFRESH_DEVICES_INTERVAL);
    				}
    				catch(Exception e)
    				{
    					e.printStackTrace();
    				}				
    			}
    		}
    		
    		log.e("ControlCenterWorkThread over...");		
    	}
    	
    	private void refreshDevices(){
    		log.e("refreshDevices...");
    		if (!CommonUtil.checkNetworkState(mContext)){
    			return ;
    		}
    
    		try {
    			if (mStartComplete){
    				boolean searchRet = mCP.search();	
    				log.e("mCP.search() ret = "  + searchRet);
    				if (mSearchDeviceListener != null){
    					mSearchDeviceListener.onSearchComplete(searchRet);
    				}
    			}else{
    				boolean startRet = mCP.start();
    				log.e("mCP.start() ret = "  + startRet);
    				if (startRet){
    					mStartComplete = true;
    				}
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		
    		
    	}
    
    
    
    }
    

    外部类过滤DLNA设备信息保留DMS设备列表,并发出更新广播通知UI

    public class AllShareProxy implements IDeviceOperator,
    										IDeviceOperator.IDMSDeviceOperator{
    
    	private static final CommonLog log = LogFactory.createLog();
    
    	
    	private static  AllShareProxy instance;
    	private Context mContext;
    	
    	private AbstractMediaMng dmsMediaMng;
    	
    	private AllShareProxy(Context context) {
    		mContext = context;
    		dmsMediaMng = new MediaServerMng(context);
    
    	}
    
    	public static synchronized AllShareProxy getInstance(Context context) {
    		if (instance == null){
    			instance  = new AllShareProxy(context);
    		}
    		return instance;
    	}
    
    	public void startSearch(){
    		mContext.startService(new Intent(DlnaService.SEARCH_DEVICES));
    	}
    	
    	public void resetSearch(){
    
    		mContext.startService(new Intent(DlnaService.RESET_SEARCH_DEVICES));
    		clearDevice();
    	}
    	
    	public void exitSearch(){
    
    		mContext.stopService(new Intent(mContext, DlnaService.class));
    		clearDevice();
    	}
    	
    	
    	@Override
    	public void addDevice(Device d) {
    	    if (UpnpUtil.isMediaServerDevice(d)){
    			dmsMediaMng.addDevice(d);
    		}
    	}
    
    	@Override
    	public void removeDevice(Device d) {
    		if (UpnpUtil.isMediaServerDevice(d)){
    			dmsMediaMng.removeDevice(d);
    		}
    	}
    
    	@Override
    	public void clearDevice() {
    		dmsMediaMng.clear();
    	}
    
    	@Override
    	public List<Device> getDMSDeviceList() {
    		return dmsMediaMng.getDeviceList();
    	}
    
    
    	@Override
    	public void setDMSSelectedDevice(Device selectedDevice) {
    		dmsMediaMng.setSelectedDevice(selectedDevice);
    	}
    
    	@Override
    	public Device getDMSSelectedDevice() {
    		return dmsMediaMng.getSelectedDevice();
    	}
    
    }
    


    选中浏览设备后通过代理放送控制命令获取xml文件描述并解析得到多媒体文件信息

    public class BrowseDMSProxy {
    
    	public static interface BrowseRequestCallback
    	{
    		public void onGetItems(final List<MediaItem> list);
    	}
    	
    	private static final CommonLog log = LogFactory.createLog();
    	
    	public static  void syncGetDirectory(final Context context, final BrowseRequestCallback callback) {
    		Thread thread = new Thread(new Runnable() {
    			
    			@Override
    			public void run() {
    
    				List<MediaItem> list = null;
    				try {
    					list = getDirectory(context);
    				} catch (Exception e) {
    					e.printStackTrace();
    				}
    				if (callback != null){
    					callback.onGetItems(list);
    				}
    			}
    		});
    		
    		thread.start();
    	}
    	
    	public static void syncGetItems(final Context context, final String id,final BrowseRequestCallback callback) {
    		Thread thread = new Thread(new Runnable() {
    			
    			@Override
    			public void run() {
    				List<MediaItem> list = null;
    				try {
    					list = getItems(context, id);
    				} catch (Exception e) {
    					e.printStackTrace();
    				}
    				if (callback != null){
    					callback.onGetItems(list);
    				}
    			}
    		});
    		
    		thread.start();
    		
    
    	}
    	
    	public static List<MediaItem> getDirectory(Context context) throws Exception {
    		
    		Device selDevice = AllShareProxy.getInstance(context).getDMSSelectedDevice();
    		if (selDevice == null) {
    			log.e("no selDevice!!!");
    			return null;
    		}
    		
    		
    		
    //		Node selDevNode = selDevice.getDeviceNode();
    //		if (selDevNode != null){
    //			selDevNode.print();
    //		}
    		
    		org.cybergarage.upnp.Service service = selDevice
    		.getService("urn:schemas-upnp-org:service:ContentDirectory:1");
    		if (service == null)
    		{
    			log.e("no service for ContentDirectory!!!");
    			return null;
    		}
    		
    //		Node serverNode = service.getServiceNode();
    //		if (serverNode != null){
    //			serverNode.print();
    //		}
    	
    		Action action = service.getAction("Browse");
    		if(action == null)
    		{
    			log.e("action for Browse is null!!!");
    			return null;
    		}
    		ArgumentList argumentList = action.getArgumentList();
    		argumentList.getArgument("ObjectID").setValue(0);
    		argumentList.getArgument("BrowseFlag").setValue("BrowseDirectChildren");
    		argumentList.getArgument("StartingIndex").setValue("0");
    		argumentList.getArgument("RequestedCount").setValue("0");
    		argumentList.getArgument("Filter").setValue("*");
    		argumentList.getArgument("SortCriteria").setValue("");
    		
    		ArgumentList actionInputArgList = action.getInputArgumentList();	
    //		int size = actionInputArgList.size();
    //		for(int i = 0; i < size; i++){
    //			Argument argument =  (Argument) (actionInputArgList.get(i));
    //			argument.getArgumentNode().print();
    //		}
    
    		if (action.postControlAction()) {
    			ArgumentList outArgList = action.getOutputArgumentList();
    			Argument result = outArgList.getArgument("Result");
    		
    			log.d("result value = \n" + result.getValue());	
    			
    			
    			List<MediaItem> items = ParseUtil.parseResult(result);
    			return items;
    		} else {
    			UPnPStatus err = action.getControlStatus();
    			log.e("Error Code = " + err.getCode());
    			log.e("Error Desc = " + err.getDescription());
    		}
    		return null;
    	}
    	
    	public static List<MediaItem> getItems(Context context, String id) throws Exception{
    		
    		
    		Device selDevice = AllShareProxy.getInstance(context).getDMSSelectedDevice();
    		if (selDevice == null) {
    			log.e("no selDevice!!!");
    			return null;
    		}
    	
    		org.cybergarage.upnp.Service service = selDevice
    		.getService("urn:schemas-upnp-org:service:ContentDirectory:1");
    		if (selDevice == null)
    		{
    			log.e("no service for ContentDirectory!!!");
    			return null;
    		}
    		
    		Action action = service.getAction("Browse");
    		if(action == null)
    		{
    			log.e("action for Browse is null");
    			return null;
    		}
    	
    	//	action.getActionNode().print();	
    		
    		ArgumentList argumentList = action.getArgumentList();
    		argumentList.getArgument("ObjectID").setValue(id);
    		argumentList.getArgument("BrowseFlag").setValue("BrowseDirectChildren");
    		argumentList.getArgument("StartingIndex").setValue("0");
    		argumentList.getArgument("RequestedCount").setValue("0");
    		argumentList.getArgument("Filter").setValue("*");
    		argumentList.getArgument("SortCriteria").setValue("");
    
    		if (action.postControlAction()) {
    			ArgumentList outArgList = action.getOutputArgumentList();
    			Argument result = outArgList.getArgument("Result");
    			log.d("result value = \n" + result.getValue());	
    			
    			List<MediaItem> items = ParseUtil.parseResult(result);
    			return items;
    		} else {
    			UPnPStatus err = action.getControlStatus();
    			System.out.println("Error Code = " + err.getCode());
    			System.out.println("Error Desc = " + err.getDescription());
    		}
    		return null;
    	}
    }



    最后远程播放音视频流,对于图片先下载到本地再显示


    具体详细看demo吧

    apk下载地址:

    https://raw.githubusercontent.com/geniusgithub/MediaPlayer/master/storage/mediaPlayer.apk

    附上工程链接:
    http://download.csdn.net/detail/geniuseoe2012/4970066(旧版)

    github下载链接:
    https://github.com/geniusgithub/MediaPlayer

    PS:建议大家上github下载,这样可以更新到最新的代码

    文档链接:
    http://download.csdn.net/detail/geniuseoe2012/4969961

    关于DMR和DMS的实现请参考这两篇博文:

    基于Platinum库的DMS实现(android)

    基于Platinum库的DMR实现(android)
     
    more brilliant,Please pay attention to my CSDN blog -->http://blog.csdn.net/geniuseoe2012

  • 相关阅读:
    Ajax beforeSend和complete 方法
    CLR Via CSharp读书笔记(17):委托
    linux上部署Django项目(Apache+mod_wsgi+django)
    用Apache+mod_wsgi部署python程序 作者:leven | 日期20101129 00:09:37
    VirtualBox桥接网络的简单配置,让虚拟机直接访问网络
    Django and mod_wsgi deploy example
    How to use Django with FastCGI, SCGI, or AJP¶
    Fedora 15 下编译安装apache
    Change Ubuntu Server from DHCP to a Static IP Address
    How to Verify a CentOS Linux Server is 32 Bit or 64 Bit
  • 原文地址:https://www.cnblogs.com/lance2016/p/5204247.html
Copyright © 2020-2023  润新知