基于CyberGarage库的dlna开发(android)

xiaoxiao2021-02-28  64

关于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的交互来执行相关操作

[cpp]  view plain  copy 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内部开启一个线程来执行控制点的搜索,停止等命令 

[cpp]  view plain  copy 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

[cpp]  view plain  copy 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();       }      }<span style="color:#ff0000;">   </span>   选中浏览设备后通过代理放送控制命令获取xml文件描述并解析得到多媒体文件信息 [cpp]  view plain  copy 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 blog -->http://blog.csdn.Net/geniuseoe2012

转载请注明原文地址: https://www.6miu.com/read-52051.html

最新回复(0)