基於CyberGarage庫的dlna開發(android)

轉載地址:http://blog.csdn.net/lancees/article/details/8477513

我們在做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的交互來執行相關操作

  1. public class DlnaService extends Service implements IBaseEngine,  
  2.                                                     DeviceChangeListener,  
  3.                                                     ControlCenterWorkThread.ISearchDeviceListener{  
  4.       
  5.     private static final CommonLog log = LogFactory.createLog();  
  6.       
  7.     public static final String SEARCH_DEVICES = "com.geniusgithub.allshare.search_device";  
  8.     public static final String RESET_SEARCH_DEVICES = "com.geniusgithub.allshare.reset_search_device";  
  9.       
  10.     private static final int NETWORK_CHANGE = 0x0001;  
  11.     private boolean firstReceiveNetworkChangeBR = true;  
  12.     private  NetworkStatusChangeBR mNetworkStatusChangeBR;  
  13.       
  14.       
  15.     private  ControlPoint mControlPoint;  
  16.     private  ControlCenterWorkThread mCenterWorkThread;  
  17.     private  AllShareProxy mAllShareProxy;  
  18.     private  Handler mHandler;  
  19.       
  20.   
  21.   
  22.     @Override  
  23.     public IBinder onBind(Intent intent) {  
  24.         return null;  
  25.     }  
  26.       
  27.     @Override  
  28.     public void onCreate() {  
  29.         super.onCreate();  
  30.         log.e("DlnaService onCreate");  
  31.         init();  
  32.     }  
  33.       
  34.   
  35.     @Override  
  36.     public int onStartCommand(Intent intent, int flags, int startId) {  
  37.           
  38.         if (intent != null && intent.getAction() != null){  
  39.             String action = intent.getAction();  
  40.             if (DlnaService.SEARCH_DEVICES.equals(action)) {  
  41.                 startEngine();  
  42.             }else if (DlnaService.RESET_SEARCH_DEVICES.equals(action)){  
  43.                 restartEngine();  
  44.             }  
  45.         }else{  
  46.             log.e("intent = " + intent);  
  47.         }  
  48.   
  49.         return super.onStartCommand(intent, flags, startId);  
  50.     }  
  51.   
  52.     @Override  
  53.     public void onDestroy() {  
  54.         log.e("DlnaService onDestroy");  
  55.         unInit();  
  56.         super.onDestroy();  
  57.     }  
  58.       
  59.       
  60.     private void init(){  
  61.         mAllShareProxy = AllShareProxy.getInstance(this);  
  62.           
  63.         mControlPoint = new ControlPoint();  
  64.         AllShareApplication.getInstance().setControlPoint(mControlPoint);  
  65.         mControlPoint.addDeviceChangeListener(this);  
  66.         mControlPoint.addSearchResponseListener(new SearchResponseListener() {        
  67.             public void deviceSearchResponseReceived(SSDPPacket ssdpPacket) {  
  68.             }  
  69.         });  
  70.       
  71.   
  72.         mCenterWorkThread = new ControlCenterWorkThread(this, mControlPoint);  
  73.         mCenterWorkThread.setSearchListener(this);  
  74.           
  75.         mHandler = new Handler(){  
  76.   
  77.             public void handleMessage(Message msg) {  
  78.                 switch(msg.what){  
  79.                     case NETWORK_CHANGE:  
  80.                         mAllShareProxy.resetSearch();  
  81.                         break;  
  82.                 }  
  83.             }  
  84.               
  85.         };  
  86.           
  87.         registerNetworkStatusBR();  
  88.     }  
  89.       
  90.     private void unInit(){  
  91.         unRegisterNetworkStatusBR();  
  92.         AllShareApplication.getInstance().setControlPoint(null);  
  93.         mCenterWorkThread.setSearchListener(null);  
  94.         mCenterWorkThread.exit();  
  95.     }  
  96.   
  97.       
  98.     @Override  
  99.     public boolean startEngine() {  
  100.         awakeWorkThread();  
  101.         return true;  
  102.     }  
  103.   
  104.   
  105.     @Override  
  106.     public boolean stopEngine() {  
  107.         exitWorkThread();  
  108.         return true;  
  109.     }  
  110.   
  111.   
  112.     @Override  
  113.     public boolean restartEngine() {  
  114.         mCenterWorkThread.reset();  
  115.         return true;  
  116.     }  
  117.   
  118.   
  119.   
  120.   
  121.     @Override  
  122.     public void deviceAdded(Device dev) {  
  123.         mAllShareProxy.addDevice(dev);  
  124.     }  
  125.   
  126.   
  127.     @Override  
  128.     public void deviceRemoved(Device dev) {  
  129.         mAllShareProxy.removeDevice(dev);  
  130.     }  
  131.       
  132.       
  133.     private void awakeWorkThread(){  
  134.   
  135.         if (mCenterWorkThread.isAlive()){  
  136.             mCenterWorkThread.awakeThread();  
  137.         }else{  
  138.             mCenterWorkThread.start();  
  139.         }  
  140.     }  
  141.       
  142.     private void exitWorkThread(){  
  143.         if (mCenterWorkThread != null && mCenterWorkThread.isAlive()){  
  144.             mCenterWorkThread.exit();  
  145.             long time1 = System.currentTimeMillis();  
  146.             while(mCenterWorkThread.isAlive()){  
  147.                 try {  
  148.                     Thread.sleep(100);  
  149.                 } catch (InterruptedException e) {  
  150.                     e.printStackTrace();  
  151.                 }  
  152.             }  
  153.             long time2 = System.currentTimeMillis();  
  154.             log.e("exitCenterWorkThread cost time:" + (time2 - time1));  
  155.             mCenterWorkThread = null;  
  156.         }  
  157.     }  
  158.       
  159.       
  160.     @Override  
  161.     public void onSearchComplete(boolean searchSuccess) {  
  162.   
  163.         if (!searchSuccess){  
  164.             sendSearchDeviceFailBrocast(this);  
  165.         }  
  166.     }  
  167.       
  168.     public static final String SEARCH_DEVICES_FAIL = "com.geniusgithub.allshare.search_devices_fail";  
  169.     public static void sendSearchDeviceFailBrocast(Context context){  
  170.         log.e("sendSearchDeviceFailBrocast");  
  171.         Intent intent = new Intent(SEARCH_DEVICES_FAIL);  
  172.         context.sendBroadcast(intent);  
  173.     }  
  174.       
  175.     private class NetworkStatusChangeBR extends BroadcastReceiver{  
  176.   
  177.         @Override  
  178.         public void onReceive(Context context, Intent intent) {  
  179.   
  180.             if (intent != null){  
  181.                 String action = intent.getAction();  
  182.                 if (action != null){  
  183.                     if (action.equalsIgnoreCase(ConnectivityManager.CONNECTIVITY_ACTION)){  
  184.                         sendNetworkChangeMessage();  
  185.                     }  
  186.                 }  
  187.             }  
  188.               
  189.         }  
  190.           
  191.     }  
  192.       
  193.     private void registerNetworkStatusBR(){  
  194.         if (mNetworkStatusChangeBR == null){  
  195.             mNetworkStatusChangeBR = new NetworkStatusChangeBR();  
  196.             registerReceiver(mNetworkStatusChangeBR, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));  
  197.         }  
  198.     }  
  199.       
  200.     private void unRegisterNetworkStatusBR(){  
  201.         if (mNetworkStatusChangeBR != null){  
  202.             unregisterReceiver(mNetworkStatusChangeBR);  
  203.         }  
  204.     }  
  205.       
  206.     private void sendNetworkChangeMessage(){  
  207.         if (firstReceiveNetworkChangeBR){  
  208.             log.e("first receive the NetworkChangeMessage, so drop it...");  
  209.             firstReceiveNetworkChangeBR = false;  
  210.             return ;  
  211.         }  
  212.           
  213.         mHandler.removeMessages(NETWORK_CHANGE);  
  214.         mHandler.sendEmptyMessageDelayed(NETWORK_CHANGE, 500);  
  215.     }  
  216.   
  217. }  


Service內部開啓一個線程來執行控制點的搜索,停止等命令 

  1. public class ControlCenterWorkThread extends Thread{  
  2.   
  3. private static final CommonLog log = LogFactory.createLog();  
  4.       
  5.     private static final int REFRESH_DEVICES_INTERVAL = 30 * 1000;   
  6.       
  7.     public static interface ISearchDeviceListener{  
  8.         public void onSearchComplete(boolean searchSuccess);  
  9.     }  
  10.       
  11.     private ControlPoint mCP = null;  
  12.     private Context mContext = null;  
  13.     private boolean mStartComplete = false;  
  14.     private boolean mIsExit = false;  
  15.     private ISearchDeviceListener mSearchDeviceListener;  
  16.       
  17.     public ControlCenterWorkThread(Context context, ControlPoint controlPoint){  
  18.         mContext = context;  
  19.         mCP = controlPoint;   
  20.     }  
  21.       
  22.     public void  setCompleteFlag(boolean flag){  
  23.         mStartComplete = flag;  
  24.     }  
  25.       
  26.     public void setSearchListener(ISearchDeviceListener listener){  
  27.         mSearchDeviceListener = listener;  
  28.     }  
  29.       
  30.     public void awakeThread(){  
  31.         synchronized (this) {  
  32.             notifyAll();  
  33.         }  
  34.     }  
  35.       
  36.       
  37.     public void reset(){  
  38.         setCompleteFlag(false);  
  39.         awakeThread();  
  40.     }  
  41.       
  42.     public void exit(){  
  43.         mIsExit = true;  
  44.         awakeThread();  
  45.     }  
  46.       
  47.       
  48.     @Override  
  49.     public void run() {  
  50.         log.e("ControlCenterWorkThread run...");          
  51.           
  52.         while(true)  
  53.         {  
  54.             if (mIsExit){  
  55.                 mCP.stop();  
  56.                 break;  
  57.             }  
  58.               
  59.             refreshDevices();  
  60.               
  61.             synchronized(this)  
  62.             {         
  63.                 try  
  64.                 {  
  65.                     wait(REFRESH_DEVICES_INTERVAL);  
  66.                 }  
  67.                 catch(Exception e)  
  68.                 {  
  69.                     e.printStackTrace();  
  70.                 }                 
  71.             }  
  72.         }  
  73.           
  74.         log.e("ControlCenterWorkThread over...");         
  75.     }  
  76.       
  77.     private void refreshDevices(){  
  78.         log.e("refreshDevices...");  
  79.         if (!CommonUtil.checkNetworkState(mContext)){  
  80.             return ;  
  81.         }  
  82.   
  83.         try {  
  84.             if (mStartComplete){  
  85.                 boolean searchRet = mCP.search();     
  86.                 log.e("mCP.search() ret = "  + searchRet);  
  87.                 if (mSearchDeviceListener != null){  
  88.                     mSearchDeviceListener.onSearchComplete(searchRet);  
  89.                 }  
  90.             }else{  
  91.                 boolean startRet = mCP.start();  
  92.                 log.e("mCP.start() ret = "  + startRet);  
  93.                 if (startRet){  
  94.                     mStartComplete = true;  
  95.                 }  
  96.             }  
  97.         } catch (Exception e) {  
  98.             e.printStackTrace();  
  99.         }  
  100.           
  101.           
  102.     }  
  103.   
  104.   
  105.   
  106. }  

外部類過濾DLNA設備信息保留DMS設備列表,併發出更新廣播通知UI

  1. public class AllShareProxy implements IDeviceOperator,  
  2.                                         IDeviceOperator.IDMSDeviceOperator{  
  3.   
  4.     private static final CommonLog log = LogFactory.createLog();  
  5.   
  6.       
  7.     private static  AllShareProxy instance;  
  8.     private Context mContext;  
  9.       
  10.     private AbstractMediaMng dmsMediaMng;  
  11.       
  12.     private AllShareProxy(Context context) {  
  13.         mContext = context;  
  14.         dmsMediaMng = new MediaServerMng(context);  
  15.   
  16.     }  
  17.   
  18.     public static synchronized AllShareProxy getInstance(Context context) {  
  19.         if (instance == null){  
  20.             instance  = new AllShareProxy(context);  
  21.         }  
  22.         return instance;  
  23.     }  
  24.   
  25.     public void startSearch(){  
  26.         mContext.startService(new Intent(DlnaService.SEARCH_DEVICES));  
  27.     }  
  28.       
  29.     public void resetSearch(){  
  30.   
  31.         mContext.startService(new Intent(DlnaService.RESET_SEARCH_DEVICES));  
  32.         clearDevice();  
  33.     }  
  34.       
  35.     public void exitSearch(){  
  36.   
  37.         mContext.stopService(new Intent(mContext, DlnaService.class));  
  38.         clearDevice();  
  39.     }  
  40.       
  41.       
  42.     @Override  
  43.     public void addDevice(Device d) {  
  44.         if (UpnpUtil.isMediaServerDevice(d)){  
  45.             dmsMediaMng.addDevice(d);  
  46.         }  
  47.     }  
  48.   
  49.     @Override  
  50.     public void removeDevice(Device d) {  
  51.         if (UpnpUtil.isMediaServerDevice(d)){  
  52.             dmsMediaMng.removeDevice(d);  
  53.         }  
  54.     }  
  55.   
  56.     @Override  
  57.     public void clearDevice() {  
  58.         dmsMediaMng.clear();  
  59.     }  
  60.   
  61.     @Override  
  62.     public List<Device> getDMSDeviceList() {  
  63.         return dmsMediaMng.getDeviceList();  
  64.     }  
  65.   
  66.   
  67.     @Override  
  68.     public void setDMSSelectedDevice(Device selectedDevice) {  
  69.         dmsMediaMng.setSelectedDevice(selectedDevice);  
  70.     }  
  71.   
  72.     @Override  
  73.     public Device getDMSSelectedDevice() {  
  74.         return dmsMediaMng.getSelectedDevice();  
  75.     }  
  76.   
  77. }<span style="color:#ff0000;">  
  78. </span>  

選中瀏覽設備後通過代理放送控制命令獲取xml文件描述並解析得到多媒體文件信息
  1. public class BrowseDMSProxy {  
  2.   
  3.     public static interface BrowseRequestCallback  
  4.     {  
  5.         public void onGetItems(final List<MediaItem> list);  
  6.     }  
  7.       
  8.     private static final CommonLog log = LogFactory.createLog();  
  9.       
  10.     public static  void syncGetDirectory(final Context context, final BrowseRequestCallback callback) {  
  11.         Thread thread = new Thread(new Runnable() {  
  12.               
  13.             @Override  
  14.             public void run() {  
  15.   
  16.                 List<MediaItem> list = null;  
  17.                 try {  
  18.                     list = getDirectory(context);  
  19.                 } catch (Exception e) {  
  20.                     e.printStackTrace();  
  21.                 }  
  22.                 if (callback != null){  
  23.                     callback.onGetItems(list);  
  24.                 }  
  25.             }  
  26.         });  
  27.           
  28.         thread.start();  
  29.     }  
  30.       
  31.     public static void syncGetItems(final Context context, final String id,final BrowseRequestCallback callback) {  
  32.         Thread thread = new Thread(new Runnable() {  
  33.               
  34.             @Override  
  35.             public void run() {  
  36.                 List<MediaItem> list = null;  
  37.                 try {  
  38.                     list = getItems(context, id);  
  39.                 } catch (Exception e) {  
  40.                     e.printStackTrace();  
  41.                 }  
  42.                 if (callback != null){  
  43.                     callback.onGetItems(list);  
  44.                 }  
  45.             }  
  46.         });  
  47.           
  48.         thread.start();  
  49.           
  50.   
  51.     }  
  52.       
  53.     public static List<MediaItem> getDirectory(Context context) throws Exception {  
  54.           
  55.         Device selDevice = AllShareProxy.getInstance(context).getDMSSelectedDevice();  
  56.         if (selDevice == null) {  
  57.             log.e("no selDevice!!!");  
  58.             return null;  
  59.         }  
  60.           
  61.           
  62.           
  63. //      Node selDevNode = selDevice.getDeviceNode();  
  64. //      if (selDevNode != null){  
  65. //          selDevNode.print();  
  66. //      }  
  67.           
  68.         org.cybergarage.upnp.Service service = selDevice  
  69.         .getService("urn:schemas-upnp-org:service:ContentDirectory:1");  
  70.         if (service == null)  
  71.         {  
  72.             log.e("no service for ContentDirectory!!!");  
  73.             return null;  
  74.         }  
  75.           
  76. //      Node serverNode = service.getServiceNode();  
  77. //      if (serverNode != null){  
  78. //          serverNode.print();  
  79. //      }  
  80.       
  81.         Action action = service.getAction("Browse");  
  82.         if(action == null)  
  83.         {  
  84.             log.e("action for Browse is null!!!");  
  85.             return null;  
  86.         }  
  87.         ArgumentList argumentList = action.getArgumentList();  
  88.         argumentList.getArgument("ObjectID").setValue(0);  
  89.         argumentList.getArgument("BrowseFlag").setValue("BrowseDirectChildren");  
  90.         argumentList.getArgument("StartingIndex").setValue("0");  
  91.         argumentList.getArgument("RequestedCount").setValue("0");  
  92.         argumentList.getArgument("Filter").setValue("*");  
  93.         argumentList.getArgument("SortCriteria").setValue("");  
  94.           
  95.         ArgumentList actionInputArgList = action.getInputArgumentList();      
  96. //      int size = actionInputArgList.size();  
  97. //      for(int i = 0; i < size; i++){  
  98. //          Argument argument =  (Argument) (actionInputArgList.get(i));  
  99. //          argument.getArgumentNode().print();  
  100. //      }  
  101.   
  102.         if (action.postControlAction()) {  
  103.             ArgumentList outArgList = action.getOutputArgumentList();  
  104.             Argument result = outArgList.getArgument("Result");  
  105.           
  106.             log.d("result value = \n" + result.getValue());   
  107.               
  108.               
  109.             List<MediaItem> items = ParseUtil.parseResult(result);  
  110.             return items;  
  111.         } else {  
  112.             UPnPStatus err = action.getControlStatus();  
  113.             log.e("Error Code = " + err.getCode());  
  114.             log.e("Error Desc = " + err.getDescription());  
  115.         }  
  116.         return null;  
  117.     }  
  118.       
  119.     public static List<MediaItem> getItems(Context context, String id) throws Exception{  
  120.           
  121.           
  122.         Device selDevice = AllShareProxy.getInstance(context).getDMSSelectedDevice();  
  123.         if (selDevice == null) {  
  124.             log.e("no selDevice!!!");  
  125.             return null;  
  126.         }  
  127.       
  128.         org.cybergarage.upnp.Service service = selDevice  
  129.         .getService("urn:schemas-upnp-org:service:ContentDirectory:1");  
  130.         if (selDevice == null)  
  131.         {  
  132.             log.e("no service for ContentDirectory!!!");  
  133.             return null;  
  134.         }  
  135.           
  136.         Action action = service.getAction("Browse");  
  137.         if(action == null)  
  138.         {  
  139.             log.e("action for Browse is null");  
  140.             return null;  
  141.         }  
  142.       
  143.     //  action.getActionNode().print();   
  144.           
  145.         ArgumentList argumentList = action.getArgumentList();  
  146.         argumentList.getArgument("ObjectID").setValue(id);  
  147.         argumentList.getArgument("BrowseFlag").setValue("BrowseDirectChildren");  
  148.         argumentList.getArgument("StartingIndex").setValue("0");  
  149.         argumentList.getArgument("RequestedCount").setValue("0");  
  150.         argumentList.getArgument("Filter").setValue("*");  
  151.         argumentList.getArgument("SortCriteria").setValue("");  
  152.   
  153.         if (action.postControlAction()) {  
  154.             ArgumentList outArgList = action.getOutputArgumentList();  
  155.             Argument result = outArgList.getArgument("Result");  
  156.             log.d("result value = \n" + result.getValue());   
  157.               
  158.             List<MediaItem> items = ParseUtil.parseResult(result);  
  159.             return items;  
  160.         } else {  
  161.             UPnPStatus err = action.getControlStatus();  
  162.             System.out.println("Error Code = " + err.getCode());  
  163.             System.out.println("Error Desc = " + err.getDescription());  
  164.         }  
  165.         return null;  
  166.     }  
  167. }  


最後遠程播放音視頻流,對於圖片先下載到本地再顯示
鑑於CyberGarage庫有些許bug,工程裏依賴的jar包dlna_framework.jar是經過修改過的
 
原版cyber庫下載地址:https://github.com/cybergarage/CyberLink4Java
dlna_framework下載地址:   https://github.com/geniusgithub/dlna_framework


具體詳細看demo吧

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

github下載鏈接:
https://github.com/geniusgithub/MediaPlayer

PS:建議大家上github下載,這樣可以更新到最新的代碼


文檔鏈接:
http://download.csdn.net/detail/geniuseoe2012/4969961

發佈了0 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章