轉載地址:http://blog.csdn.net/lancees/article/details/8951679
本例所採用的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 brilliant,Please pay attention to my CSDN blog -->http://blog.csdn.net/geniuseoe2012