基于CyberGarage库的dlna开发(android)

  • Post author:
  • Post category:其他


转载地址: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. private




    static


    final CommonLog log = LogFactory.createLog();




  5. public




    static


    final String SEARCH_DEVICES =


    “com.geniusgithub.allshare.search_device”


    ;



  6. public




    static


    final String RESET_SEARCH_DEVICES =


    “com.geniusgithub.allshare.reset_search_device”


    ;




  7. private




    static


    final


    int


    NETWORK_CHANGE = 0x0001;



  8. private


    boolean firstReceiveNetworkChangeBR =


    true


    ;



  9. private


    NetworkStatusChangeBR mNetworkStatusChangeBR;





  10. private


    ControlPoint mControlPoint;



  11. private


    ControlCenterWorkThread mCenterWorkThread;



  12. private


    AllShareProxy mAllShareProxy;



  13. private


    Handler mHandler;





  14. @Override


  15. public


    IBinder onBind(Intent intent) {



  16. return


    null;


  17. }


  18. @Override


  19. public




    void


    onCreate() {


  20. super.onCreate();

  21. log.e(

    “DlnaService onCreate”


    );


  22. init();

  23. }



  24. @Override


  25. public




    int


    onStartCommand(Intent intent,


    int


    flags,


    int


    startId) {




  26. if


    (intent != null && intent.getAction() != null){


  27. String action = intent.getAction();


  28. if


    (DlnaService.SEARCH_DEVICES.equals(action)) {


  29. startEngine();

  30. }

    else




    if


    (DlnaService.RESET_SEARCH_DEVICES.equals(action)){


  31. restartEngine();

  32. }

  33. }

    else


    {


  34. log.e(

    “intent = ”


    + intent);


  35. }



  36. return


    super.onStartCommand(intent, flags, startId);


  37. }


  38. @Override


  39. public




    void


    onDestroy() {


  40. log.e(

    “DlnaService onDestroy”


    );


  41. unInit();

  42. super.onDestroy();

  43. }




  44. private




    void


    init(){


  45. mAllShareProxy = AllShareProxy.getInstance(

    this


    );



  46. mControlPoint =

    new


    ControlPoint();


  47. AllShareApplication.getInstance().setControlPoint(mControlPoint);

  48. mControlPoint.addDeviceChangeListener(

    this


    );


  49. mControlPoint.addSearchResponseListener(

    new


    SearchResponseListener() {



  50. public




    void


    deviceSearchResponseReceived(SSDPPacket ssdpPacket) {


  51. }

  52. });



  53. mCenterWorkThread =

    new


    ControlCenterWorkThread(


    this


    , mControlPoint);


  54. mCenterWorkThread.setSearchListener(

    this


    );



  55. mHandler =

    new


    Handler(){




  56. public




    void


    handleMessage(Message msg) {



  57. switch


    (msg.what){



  58. case


    NETWORK_CHANGE:


  59. mAllShareProxy.resetSearch();


  60. break


    ;


  61. }

  62. }


  63. };


  64. registerNetworkStatusBR();

  65. }



  66. private




    void


    unInit(){


  67. unRegisterNetworkStatusBR();

  68. AllShareApplication.getInstance().setControlPoint(null);

  69. mCenterWorkThread.setSearchListener(null);

  70. mCenterWorkThread.exit();

  71. }



  72. @Override


  73. public


    boolean startEngine() {


  74. awakeWorkThread();


  75. return




    true


    ;


  76. }



  77. @Override


  78. public


    boolean stopEngine() {


  79. exitWorkThread();


  80. return




    true


    ;


  81. }



  82. @Override


  83. public


    boolean restartEngine() {


  84. mCenterWorkThread.reset();


  85. return




    true


    ;


  86. }





  87. @Override


  88. public




    void


    deviceAdded(Device dev) {


  89. mAllShareProxy.addDevice(dev);

  90. }



  91. @Override


  92. public




    void


    deviceRemoved(Device dev) {


  93. mAllShareProxy.removeDevice(dev);

  94. }




  95. private




    void


    awakeWorkThread(){




  96. if


    (mCenterWorkThread.isAlive()){


  97. mCenterWorkThread.awakeThread();

  98. }

    else


    {


  99. mCenterWorkThread.start();

  100. }

  101. }



  102. private




    void


    exitWorkThread(){



  103. if


    (mCenterWorkThread != null && mCenterWorkThread.isAlive()){


  104. mCenterWorkThread.exit();


  105. long


    time1 = System.currentTimeMillis();



  106. while


    (mCenterWorkThread.isAlive()){



  107. try


    {


  108. Thread.sleep(100);

  109. }

    catch


    (InterruptedException e) {


  110. e.printStackTrace();

  111. }

  112. }


  113. long


    time2 = System.currentTimeMillis();


  114. log.e(

    “exitCenterWorkThread cost time:”


    + (time2 – time1));


  115. mCenterWorkThread = null;

  116. }

  117. }



  118. @Override


  119. public




    void


    onSearchComplete(boolean searchSuccess) {




  120. if


    (!searchSuccess){


  121. sendSearchDeviceFailBrocast(

    this


    );


  122. }

  123. }



  124. public




    static


    final String SEARCH_DEVICES_FAIL =


    “com.geniusgithub.allshare.search_devices_fail”


    ;



  125. public




    static




    void


    sendSearchDeviceFailBrocast(Context context){


  126. log.e(

    “sendSearchDeviceFailBrocast”


    );


  127. Intent intent =

    new


    Intent(SEARCH_DEVICES_FAIL);


  128. context.sendBroadcast(intent);

  129. }



  130. private




    class


    NetworkStatusChangeBR extends BroadcastReceiver{



  131. @Override


  132. public




    void


    onReceive(Context context, Intent intent) {




  133. if


    (intent != null){


  134. String action = intent.getAction();


  135. if


    (action != null){



  136. if


    (action.equalsIgnoreCase(ConnectivityManager.CONNECTIVITY_ACTION)){


  137. sendNetworkChangeMessage();

  138. }

  139. }

  140. }


  141. }


  142. }



  143. private




    void


    registerNetworkStatusBR(){



  144. if


    (mNetworkStatusChangeBR == null){


  145. mNetworkStatusChangeBR =

    new


    NetworkStatusChangeBR();


  146. registerReceiver(mNetworkStatusChangeBR,

    new


    IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));


  147. }

  148. }



  149. private




    void


    unRegisterNetworkStatusBR(){



  150. if


    (mNetworkStatusChangeBR != null){


  151. unregisterReceiver(mNetworkStatusChangeBR);

  152. }

  153. }



  154. private




    void


    sendNetworkChangeMessage(){



  155. if


    (firstReceiveNetworkChangeBR){


  156. log.e(

    “first receive the NetworkChangeMessage, so drop it…”


    );


  157. firstReceiveNetworkChangeBR =

    false


    ;



  158. return


    ;


  159. }


  160. mHandler.removeMessages(NETWORK_CHANGE);

  161. mHandler.sendEmptyMessageDelayed(NETWORK_CHANGE, 500);

  162. }


  163. }






Service

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





  1. public




    class


    ControlCenterWorkThread extends Thread{




  2. private




    static


    final CommonLog log = LogFactory.createLog();




  3. private




    static


    final


    int


    REFRESH_DEVICES_INTERVAL = 30 * 1000;




  4. public




    static


    interface ISearchDeviceListener{



  5. public




    void


    onSearchComplete(boolean searchSuccess);


  6. }



  7. private


    ControlPoint mCP = null;



  8. private


    Context mContext = null;



  9. private


    boolean mStartComplete =


    false


    ;



  10. private


    boolean mIsExit =


    false


    ;



  11. private


    ISearchDeviceListener mSearchDeviceListener;




  12. public


    ControlCenterWorkThread(Context context, ControlPoint controlPoint){


  13. mContext = context;

  14. mCP = controlPoint;

  15. }



  16. public




    void


    setCompleteFlag(boolean flag){


  17. mStartComplete = flag;

  18. }



  19. public




    void


    setSearchListener(ISearchDeviceListener listener){


  20. mSearchDeviceListener = listener;

  21. }



  22. public




    void


    awakeThread(){


  23. synchronized (

    this


    ) {


  24. notifyAll();

  25. }

  26. }




  27. public




    void


    reset(){


  28. setCompleteFlag(

    false


    );


  29. awakeThread();

  30. }



  31. public




    void


    exit(){


  32. mIsExit =

    true


    ;


  33. awakeThread();

  34. }



  35. @Override


  36. public




    void


    run() {


  37. log.e(

    “ControlCenterWorkThread run…”


    );




  38. while


    (


    true


    )


  39. {


  40. if


    (mIsExit){


  41. mCP.stop();


  42. break


    ;


  43. }


  44. refreshDevices();


  45. synchronized(

    this


    )


  46. {


  47. try




  48. {

  49. wait(REFRESH_DEVICES_INTERVAL);

  50. }


  51. catch


    (Exception e)


  52. {

  53. e.printStackTrace();

  54. }

  55. }

  56. }


  57. log.e(

    “ControlCenterWorkThread over…”


    );


  58. }



  59. private




    void


    refreshDevices(){


  60. log.e(

    “refreshDevices…”


    );



  61. if


    (!CommonUtil.checkNetworkState(mContext)){



  62. return


    ;


  63. }



  64. try


    {



  65. if


    (mStartComplete){


  66. boolean searchRet = mCP.search();

  67. log.e(

    “mCP.search() ret = ”


    + searchRet);



  68. if


    (mSearchDeviceListener != null){


  69. mSearchDeviceListener.onSearchComplete(searchRet);

  70. }

  71. }

    else


    {


  72. boolean startRet = mCP.start();

  73. log.e(

    “mCP.start() ret = ”


    + startRet);



  74. if


    (startRet){


  75. mStartComplete =

    true


    ;


  76. }

  77. }

  78. }

    catch


    (Exception e) {


  79. e.printStackTrace();

  80. }



  81. }




  82. }



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



  1. public




    class


    AllShareProxy implements IDeviceOperator,


  2. IDeviceOperator.IDMSDeviceOperator{



  3. private




    static


    final CommonLog log = LogFactory.createLog();





  4. private




    static


    AllShareProxy instance;



  5. private


    Context mContext;




  6. private


    AbstractMediaMng dmsMediaMng;




  7. private


    AllShareProxy(Context context) {


  8. mContext = context;

  9. dmsMediaMng =

    new


    MediaServerMng(context);



  10. }



  11. public




    static


    synchronized AllShareProxy getInstance(Context context) {



  12. if


    (instance == null){


  13. instance  =

    new


    AllShareProxy(context);


  14. }


  15. return


    instance;


  16. }



  17. public




    void


    startSearch(){


  18. mContext.startService(

    new


    Intent(DlnaService.SEARCH_DEVICES));


  19. }



  20. public




    void


    resetSearch(){



  21. mContext.startService(

    new


    Intent(DlnaService.RESET_SEARCH_DEVICES));


  22. clearDevice();

  23. }



  24. public




    void


    exitSearch(){



  25. mContext.stopService(

    new


    Intent(mContext, DlnaService.


    class


    ));


  26. clearDevice();

  27. }



  28. @Override


  29. public




    void


    addDevice(Device d) {



  30. if


    (UpnpUtil.isMediaServerDevice(d)){


  31. dmsMediaMng.addDevice(d);

  32. }

  33. }


  34. @Override


  35. public




    void


    removeDevice(Device d) {



  36. if


    (UpnpUtil.isMediaServerDevice(d)){


  37. dmsMediaMng.removeDevice(d);

  38. }

  39. }


  40. @Override


  41. public




    void


    clearDevice() {


  42. dmsMediaMng.clear();

  43. }


  44. @Override


  45. public


    List<Device> getDMSDeviceList() {



  46. return


    dmsMediaMng.getDeviceList();


  47. }



  48. @Override


  49. public




    void


    setDMSSelectedDevice(Device selectedDevice) {


  50. dmsMediaMng.setSelectedDevice(selectedDevice);

  51. }


  52. @Override


  53. public


    Device getDMSSelectedDevice() {



  54. return


    dmsMediaMng.getSelectedDevice();


  55. }


  56. }<span style=

    “color:#ff0000;”


    >


  57. </span>




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




  1. public




    class


    BrowseDMSProxy {




  2. public




    static


    interface BrowseRequestCallback


  3. {


  4. public




    void


    onGetItems(final List<MediaItem> list);


  5. }



  6. private




    static


    final CommonLog log = LogFactory.createLog();




  7. public




    static




    void


    syncGetDirectory(final Context context, final BrowseRequestCallback callback) {


  8. Thread

    thread


    =


    new


    Thread(


    new


    Runnable() {



  9. @Override


  10. public




    void


    run() {



  11. List<MediaItem> list = null;


  12. try


    {


  13. list = getDirectory(context);

  14. }

    catch


    (Exception e) {


  15. e.printStackTrace();

  16. }


  17. if


    (callback != null){


  18. callback.onGetItems(list);

  19. }

  20. }

  21. });



  22. thread


    .start();


  23. }



  24. public




    static




    void


    syncGetItems(final Context context, final String id,final BrowseRequestCallback callback) {


  25. Thread

    thread


    =


    new


    Thread(


    new


    Runnable() {



  26. @Override


  27. public




    void


    run() {


  28. List<MediaItem> list = null;


  29. try


    {


  30. list = getItems(context, id);

  31. }

    catch


    (Exception e) {


  32. e.printStackTrace();

  33. }


  34. if


    (callback != null){


  35. callback.onGetItems(list);

  36. }

  37. }

  38. });



  39. thread


    .start();




  40. }



  41. public




    static


    List<MediaItem> getDirectory(Context context) throws Exception {



  42. Device selDevice = AllShareProxy.getInstance(context).getDMSSelectedDevice();


  43. if


    (selDevice == null) {


  44. log.e(

    “no selDevice!!!”


    );



  45. return


    null;


  46. }





  47. //      Node selDevNode = selDevice.getDeviceNode();





  48. //      if (selDevNode != null){






  49. //          selDevNode.print();





  50. //      }





  51. org.cybergarage.upnp.Service service = selDevice

  52. .getService(

    “urn:schemas-upnp-org:service:ContentDirectory:1”


    );



  53. if


    (service == null)


  54. {

  55. log.e(

    “no service for ContentDirectory!!!”


    );



  56. return


    null;


  57. }



  58. //      Node serverNode = service.getServiceNode();





  59. //      if (serverNode != null){






  60. //          serverNode.print();





  61. //      }





  62. Action action = service.getAction(

    “Browse”


    );



  63. if


    (action == null)


  64. {

  65. log.e(

    “action for Browse is null!!!”


    );



  66. return


    null;


  67. }

  68. ArgumentList argumentList = action.getArgumentList();

  69. argumentList.getArgument(

    “ObjectID”


    ).setValue(0);


  70. argumentList.getArgument(

    “BrowseFlag”


    ).setValue(


    “BrowseDirectChildren”


    );


  71. argumentList.getArgument(

    “StartingIndex”


    ).setValue(


    “0”


    );


  72. argumentList.getArgument(

    “RequestedCount”


    ).setValue(


    “0”


    );


  73. argumentList.getArgument(

    “Filter”


    ).setValue(


    “*”


    );


  74. argumentList.getArgument(

    “SortCriteria”


    ).setValue(


    “”


    );



  75. ArgumentList actionInputArgList = action.getInputArgumentList();


  76. //      int size = actionInputArgList.size();





  77. //      for(int i = 0; i < size; i++){






  78. //          Argument argument =  (Argument) (actionInputArgList.get(i));





  79. //          argument.getArgumentNode().print();





  80. //      }






  81. if


    (action.postControlAction()) {


  82. ArgumentList outArgList = action.getOutputArgumentList();

  83. Argument result = outArgList.getArgument(

    “Result”


    );



  84. log.d(

    “result value = \n”


    + result.getValue());




  85. List<MediaItem> items = ParseUtil.parseResult(result);


  86. return


    items;


  87. }

    else


    {


  88. UPnPStatus err = action.getControlStatus();

  89. log.e(

    “Error Code = ”


    + err.getCode());


  90. log.e(

    “Error Desc = ”


    + err.getDescription());


  91. }


  92. return


    null;


  93. }



  94. public




    static


    List<MediaItem> getItems(Context context, String id) throws Exception{




  95. Device selDevice = AllShareProxy.getInstance(context).getDMSSelectedDevice();


  96. if


    (selDevice == null) {


  97. log.e(

    “no selDevice!!!”


    );



  98. return


    null;


  99. }


  100. org.cybergarage.upnp.Service service = selDevice

  101. .getService(

    “urn:schemas-upnp-org:service:ContentDirectory:1”


    );



  102. if


    (selDevice == null)


  103. {

  104. log.e(

    “no service for ContentDirectory!!!”


    );



  105. return


    null;


  106. }


  107. Action action = service.getAction(

    “Browse”


    );



  108. if


    (action == null)


  109. {

  110. log.e(

    “action for Browse is null”


    );



  111. return


    null;


  112. }



  113. //  action.getActionNode().print();





  114. ArgumentList argumentList = action.getArgumentList();

  115. argumentList.getArgument(

    “ObjectID”


    ).setValue(id);


  116. argumentList.getArgument(

    “BrowseFlag”


    ).setValue(


    “BrowseDirectChildren”


    );


  117. argumentList.getArgument(

    “StartingIndex”


    ).setValue(


    “0”


    );


  118. argumentList.getArgument(

    “RequestedCount”


    ).setValue(


    “0”


    );


  119. argumentList.getArgument(

    “Filter”


    ).setValue(


    “*”


    );


  120. argumentList.getArgument(

    “SortCriteria”


    ).setValue(


    “”


    );




  121. if


    (action.postControlAction()) {


  122. ArgumentList outArgList = action.getOutputArgumentList();

  123. Argument result = outArgList.getArgument(

    “Result”


    );


  124. log.d(

    “result value = \n”


    + result.getValue());



  125. List<MediaItem> items = ParseUtil.parseResult(result);


  126. return


    items;


  127. }

    else


    {


  128. UPnPStatus err = action.getControlStatus();

  129. System.out.println(

    “Error Code = ”


    + err.getCode());


  130. System.out.println(

    “Error Desc = ”


    + err.getDescription());


  131. }


  132. return


    null;


  133. }

  134. }






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

鉴于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