关于dlna开发使用的若干故障排除

article/2025/9/28 23:33:09

鉴于此前博主发表过dlna开发的相关文章并在github上传了相关工程

github主页-->https://github.com/geniusgithub

亦有不少网友也下载使用了,其中不乏网友反馈说设备找不到或是搜索不稳定云云。。

这里可能原因有很多,下面就博主亲身经历简单阐述下几种可能的原因以及如何排查问题


1.路由环境问题(这种情况较少)

检测手段:下载bubbleupnp(一个很稳定的第三方客户端)

http://www.wandoujia.com/apps/com.bubblesoft.android.bubbleupnp

找两个手机安装下并接入路由器,如果搜索正常则排除此项

否则就是路由器问题,最简单的解决方法就是重启路由器

应该就可以了,如果始终不行就要检查下配置看看是不是设置了防火墙什么的(upnp组播禁用)

 

2.手机问题

很多手机平板类的移动设备上android系统默认是不打开组播锁的(应用接受组播消息会很耗电),所以需要额外在软件代码里额外加上打开关闭的操作


1)打开权限

<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />

<uses-permission android:name="android.permission.INTERNET"/>


2.)打开组播锁

WifiManager wifiManager=(WifiManager)context.getSystemService(Context.WIFI_SERVICE);
MulticastLock  multicastLock=wifiManager.createMulticastLock("MediaRender");
if (multicastLock != null){
multicastLock.acquire();
}


3)关闭组播锁

在退出软件的时候记得关闭

       if (mMulticastLock != null){
mMulticastLock.release();
mMulticastLock = null;
}


很多不稳定的原因都是因此造成的,在有些设备上甚至会影响到udp单播的接收

对于dmrdms如果无法接收组播消息则意味着无法响应客户端的searh消息

对于dmpdmc如果无法接收组播则得不得dmrdms的上线下线消息,如果连udp单播接收都有问题,那么发出去的search消息即便对方有回应也接收不到,这些都会造成设备找不到或是搜索不稳定的问题

(当然同一个设备上的两个应用之间通讯不存在上述问题)

 

3.丢包问题

不论是udp组播还是udp单播,在路由器传输过程中都有可能丢包,所以为了尽量避免这种情况,可以在进行组播通知或是搜索的时候多发几次包(比如三次)

当然也不宜过多,否则会造成网络拥塞影响性能,这也引申出另一个问题,若是在网络环境较为复杂的路由器下测试dlna性能是很不理想的(丢包严重)

 

4.人品问题

         简单来说就是丫的两个设备明明没在一个局域网,还嚷嚷着为什么设备找不到

尤其是设备在使用wifi接入条件下,如果wifi不稳定断开了,很可能就连上另一个wifi网了,再说博主的代码有问题LZ就要骂人了发火


基本上第二点是需要大家注意的,不论是服务端应用还是客户端应用

早些时候可能因为没加上组播锁的缘故,所以会有类似问题,不过写这篇文章的时候

相关code已经commit修改了,请大家下载更新

在反编译了诸如搜狐视频,网易视频等APK发现它们并未添加组播锁,作为dmc就可能导致无法收到dmrnotify组播消息,只能依赖search机制,正如前面所说,部分手机甚至连udp单播都会受影响,那么搜索不到设备也就不奇怪了。

这时候又想使用这些软件怎么办?刚刚给大家推荐了一款软件bubbleupnp,它有一种神奇的魔力,可以打开系统组播锁,让其他应用也能正常接收到组播(LZ至今尚不明白它是怎么做到的,有知道的麻烦告知)


另外附上一个用于组播测试的demo

下载地址:http://download.csdn.net/detail/geniuseoe2012/6847963


截图:



代码片段

public class MulSocketMng {public static interface RecDataCallback{public void onDataReceive(String hostIP, int port, final String data);}private static final CommonLog log = LogFactory.createLog();private final static int RECDATA_MSG_ID = 0x0001;private MulticastSocket multicastSocket; private InetAddress mGroup;private int mLocalPort;private boolean isInit = false;private HandlerThread mHandlerThread;private Handler mRecHandler;private RecDataCallback mCallback;public MulSocketMng(){}public boolean openSokcet(String groupIP, int localPort){if (isInit){return true;}try {mLocalPort = localPort;multicastSocket = new MulticastSocket(mLocalPort);multicastSocket.setLoopbackMode(true);mGroup = InetAddress.getByName(groupIP);multicastSocket.joinGroup(mGroup);isInit = true;} catch (Exception e) {e.printStackTrace();}return isInit;}public void closeSocket(){if (!isInit){return ;}try {multicastSocket.leaveGroup(mGroup);multicastSocket.close();} catch (Exception e) {e.printStackTrace();}stopListenThead();isInit = false;}public boolean syncSendData(String data, String targetIP, int targetPort){if (!isInit){return false;}SendTask task = new SendTask(data, targetIP, targetPort);Thread thread = new Thread(task);thread.start();return true;}public boolean startListenThread(RecDataCallback callback){if (!isInit){return false;}if (mHandlerThread == null){startRevThread();mRecHandler.sendEmptyMessage(RECDATA_MSG_ID);	mCallback = callback;}return true;}public void stopListenThead(){closeRecThread();}private class SendTask implements Runnable{private String mData;private String mTargetIP;private int mTargetPort;public SendTask(String data, String targetIP, int targetPort){mData = data;mTargetIP = targetIP;mTargetPort = targetPort;}@Overridepublic void run() {try {byte []data = mData.getBytes("utf-8");InetAddress targetAddress = InetAddress.getByName(mTargetIP);DatagramPacket outPacket = new DatagramPacket(data, data.length, targetAddress, mTargetPort);MulticastSocket socket = new MulticastSocket();log.e("syncSendData mTargetIP = " + mTargetIP + ", TARGET_PORT = " + mTargetPort + "\ncontent --> " + mData);socket.send(outPacket);			  socket.close();} catch (Exception e) {e.printStackTrace();}}private void sendUDP(String data, String ip, int port) {try {byte[] datas = data.getBytes("utf-8");InetAddress targetAddress = InetAddress.getByName(ip);DatagramPacket packet = new DatagramPacket(datas, datas.length, targetAddress, port);} catch (Exception e) {e.printStackTrace();}			}}private boolean startRevThread(){if (mHandlerThread != null){return true;}mHandlerThread = new HandlerThread("");	mHandlerThread.start();mRecHandler = new Handler(mHandlerThread.getLooper()){@Overridepublic void handleMessage(Message msg) {switch(msg.what){case RECDATA_MSG_ID:try {while(true){revData();}							} catch (IOException e) {e.printStackTrace();}break;}}};return true;}private void closeRecThread(){if (mHandlerThread == null){return ;}mHandlerThread.quit();mHandlerThread = null;}private boolean revData() throws IOException {	byte[] receiveData = new byte[1024]; DatagramPacket packet = new DatagramPacket(receiveData, receiveData.length); log.e("block to receive packet!!!groupIp = " + mGroup.getHostAddress() + ", port = " + mLocalPort);	multicastSocket.receive(packet); String packetIpAddress = packet.getAddress().toString();packetIpAddress = packetIpAddress.substring(1, packetIpAddress.length()); log.e("rec packet from --> ip: " + packetIpAddress + ", port = " + packet.getPort());String content = new String(receiveData, "utf-8");content = content.trim();log.e("content -->  " + content); if (mCallback != null){mCallback.onDataReceive(packetIpAddress, packet.getPort(), content);}return true;}
}

public class MainActivity extends Activity implements OnClickListener,MulSocketMng.RecDataCallback,OnCheckedChangeListener{private static final CommonLog log = LogFactory.createLog();private static final String GROUP_IP = "239.255.255.250";private TextView mTextView;private Button mButtonSend;private Button mButtonOpen;private Button mButtonClose;private Button mButtonClear;private TextView mTVContent;private ScrollView mScrollView;private RadioGroup mRadioGroup;private MulSocketMng mSocketMng;private MulticastLock mMulticastLock;private StringBuffer mDataBuffer = new StringBuffer();private UnickSocketMng mUnickSocketMng;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);setupViews();initData();}@Overrideprotected void onDestroy() {closeWifiBrocast();super.onDestroy();}private void setupViews(){mTextView = (TextView) findViewById(R.id.textview);mButtonSend = (Button) findViewById(R.id.btnSend);mButtonOpen = (Button) findViewById(R.id.btnOpen);mButtonClose = (Button) findViewById(R.id.btnClose);mButtonClear = (Button) findViewById(R.id.btnClear);mButtonClose.setOnClickListener(this);mButtonOpen.setOnClickListener(this);mButtonSend.setOnClickListener(this);mButtonClear.setOnClickListener(this);mTVContent = (TextView) findViewById(R.id.tv_content);mScrollView = (ScrollView) findViewById(R.id.sv_view);mRadioGroup = (RadioGroup) findViewById(R.id.rg_group);mRadioGroup.setOnCheckedChangeListener(this);}private void initData(){		mSocketMng = new MulSocketMng();mUnickSocketMng = new UnickSocketMng();}private void updateText(String groupIP, int port){StringBuffer sBuffer = new StringBuffer();sBuffer.append("Socket Bind --> groupIP = " + groupIP + ", port = " + port);mTextView.setText(sBuffer.toString());}private void clearText(){mTextView.setText("socket close...");clearContent();}private void updateContent(String hostIP, int port, final String data){mDataBuffer.append("rec from ip:" + hostIP + ", port = " + port);mDataBuffer.append("\n" + data + "\n-----------------\n");mTVContent.setText(mDataBuffer.toString());mScrollView.scrollTo(0, 1024 * 1024);}private void clearContent(){mDataBuffer = new StringBuffer();mTVContent.setText("");}@Overridepublic void onClick(View v) {switch(v.getId()){case R.id.btnClose:close();break;case R.id.btnOpen:open();break;case R.id.btnSend:send();break;case R.id.btnClear:clearContent();break;}}private static final int TARGET_PORT = 1900;private void send(){String value = "test mulbrocast!!!";boolean ret = mSocketMng.syncSendData(value, GROUP_IP, TARGET_PORT);mUnickSocketMng.syncSendData("udpdata..", "192.168.11.3", 12345);}private static final int LOCAL_PORT = 1900;private void open(){boolean ret = mSocketMng.openSokcet(GROUP_IP, LOCAL_PORT);log.e("openSokcet GROUP_IP = " + GROUP_IP + ", LOCAL_PORT = " + LOCAL_PORT + ", ret = " + ret);mSocketMng.startListenThread(this);updateText(GROUP_IP, LOCAL_PORT);mUnickSocketMng.openSokcet(12345);mUnickSocketMng.startListenThread();}private void close(){mSocketMng.closeSocket();log.e("closeSocket");clearText();mUnickSocketMng.closeSocket();}@Overridepublic void onDataReceive(final String hostIP,final int port, final String data) {runOnUiThread(new Runnable() {@Overridepublic void run() {updateContent(hostIP, port, data);}});}@Overridepublic void onCheckedChanged(RadioGroup group, int checkedId) {switch(checkedId){case R.id.rb_open:openWifiBrocast();break;case R.id.rb_close:closeWifiBrocast();break;}}private void openWifiBrocast(){if (mMulticastLock == null){WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);  mMulticastLock = wifiManager.createMulticastLock("multicast.test");  if (mMulticastLock != null){mMulticastLock.acquire();  log.e("openWifiBrocast");}}	}private void closeWifiBrocast(){if (mMulticastLock != null){mMulticastLock.release();mMulticastLock = null;log.e("closeWifiBrocast");}}
}

绑定和发送的组播地址是239.255.255.250:1900,正是upnp组播地址

测试的时候软件要装两个手机上,测udp单播的话改下目标IP即可


Ok本文到此为止~-~

more brilliant,Please pay attention to my CSDN blog -->http://blog.csdn.net/geniuseoe2012 



http://chatgpt.dhexx.cn/article/l5hZ1e9g.shtml

相关文章

linux下实现dlna识别当前音频格式,通过 PulseAudio 实现局域网音乐播放

PulseAudio 的一大特点就是支持网络音频流。经过几年的发展&#xff0c;现在通过简单的鼠标点击&#xff0c;即可实现局域网内远程音乐播放&#xff0c;甚至支持 Android 手机。 PulseAudio 服务器配置 恕我愚钝&#xff0c;通过这篇报道才知道有了 paprefs 这样便捷的图形化配…

DLNA, PulseAudio, diffpatch, bash

http://antkillerfarm.github.io/ 参考资料 http://www.miui.com/thread-647727-1-1.html http://pie.pconline.com.cn/443/4434846.html 这两篇文章从用户的角度分析DLNA设备的使用方法。 http://en.wikipedia.org/wiki/List_of_UPnP_AV_media_servers_and_clients 这个…

Cling源码解析

项目地址&#xff1a;cling&#xff0c;分析的版本&#xff1a;5fd60eb&#xff0c;Demo 地址&#xff1a;BeyondUPnP 1 功能介绍 1.1 Cling Cling类库是由java实现的DLNA/UPnP协议栈。基于DLNA/UPnP可以开发出类似多屏互动、资源共享、远程控制等功能的应用&#xff0c;通过…

树莓派python蓝牙_在树莓派3B上做蓝牙音频

无损播放器无线音频方案设计 1. 音频流程简介 暂缺。 2. 关键库和应用简介 2.1 pulseaudio 2.2 bluez 2.3 gstreamer 3. 无线音频方案实施方案 3.1 主要参考材料 3.2 树莓派和R16方案设计 ( 工具&#xff0c;具体位置在&#xff1a;tina/staging_dir/toolchain-arm_c…

cantata测试工具_我如何构建和维护开源音乐播放器Cantata

cantata测试工具 这是与开发和维护开源音乐播放器的开发人员进行的一系列对话的第三部分。 Craig Drummond是Cantata的开发者和维护者&#xff0c; Cantata是一种开源音乐播放器&#xff0c;充当Music Player Daemon&#xff08;MPD&#xff09;音乐服务器的前端&#xff08;客…

sd卡烧写linux内核,linux下怎样烧写sd卡

广告 提供包含云服务器,云在内的50+款云计算产品。打造一站式的云产品试用服务,助力开发者和企业零门槛上云。 就像用硬盘装windows平台一样,将sd启动卡插入板子的sd卡插槽,然后将启动顺序拨码开关拨到sd卡启动处,开机启动即可手动把sd卡中加装好的平台烧写到板子上...如下…

linux下实现dlna识别当前音频格式,如何将实时音频流设置为DLNA兼容设备?

问题描述 有没有办法将声卡的实时输出从我们的12.04.1 LTS amd64桌面流式传输到我们网络中的DLNA-compliant外部设备&#xff1f;使用Rygel&#xff0c;miniDLNA和uShare选择共享目录中的媒体内容总是很好 – 但到目前为止&#xff0c;我们完全无法通过DLNA向客户端获取实时音频…

IOS版aplayer使用教程_享声数播APP使用指南【ios版】

享声数播的内容播放是支持APP操作的,现在我们简单介绍一下相关的操作指南。 关于享声APP,官方推荐安卓手机用户使用bubbleupnp ,苹果ios用户使用8player 举例设备:享声A1 软件:8player 操作顺序 【数播端操作】 ①享声数播用网线连接到路由器 ②在享声主屏幕上切换到【通用…

打开方式中选择默认方式无反映_「全民标签」论享声A1的APP打开方式以及与树莓派的使用对比...

​ 大家好&#xff0c;我是流氓才子。 说在前面&#xff1a;今天的推送&#xff0c;末尾没有福利&#xff0c;因为个人觉得文章的主角就是最大的福利。。。先别急着说这句广告很硬&#xff0c;往下翻翻试试&#xff1f; 近一个月来论坛最火的机器是啥&#xff1f;没猜错的话应该…

Android上好用的DLNA播放器BubbleUPnP

BubbleUPnP的厉害之处在于&#xff1a;实现在手机上听电脑上的歌&#xff0c;或者控制电脑上的播放器当遥控器用。用foobar2000只需要添加一个叫foo_upnp的插件即可&#xff0c;XMBC或者别的支持UPNP的播放器也可以。 BubbleUPnP播放器能够轻松播放手机中的音视频及网络上的UPn…

BubbleUPnP多屏互动

一&#xff0c;相关简介 1、 DLAN简介&#xff08;百度百科&#xff09; DLNA的全称是DIGITAL LIVING NETWORK ALLIANCE&#xff0c;其宗旨是Enjoy your music, photos and videos, anywhere anytime&#xff0c; DLNA(Digital Living Network Alliance)由索尼、英特尔、微软等…

WebDAV之葫芦儿·派盘+BubbleUPnP

BubbleUPnP 支持WebDAV方式连接葫芦儿派盘。 推荐一款投屏神器,它将手机内容分享到电视大屏上与家人好友一起共享,软件还提供了丰富的音乐及影视资源,喜欢的内容在线搜索就能播放。支持连接葫芦儿派盘WebDAV服务站,可以直接播放派盘内的影视资源。 BubbleUPnP是一款支持U…

数据结构和算法——Huffman树和Huffman编码

Huffman树是一种特殊结构的二叉树&#xff0c;由Huffman树设计的二进制前缀编码&#xff0c;也称为Huffman编码在通信领域有着广泛的应用。在word2vec模型中&#xff0c;在构建层次Softmax的过程中&#xff0c;也使用到了Huffman树的知识。 在通信中&#xff0c;需要将传输的文…

Huffman编码压缩文件

文章目录 前言一、Huffman编码是什么&#xff1f;二、Huffman编码的实现方法三、Huffman压缩文件1.统计文件个字符出现的次数2.生成Huffman树3.生成码表4.对文件进行压缩 四、Huffman解压文件五、实验结果总结 前言 这个实验是我在学习信息论与编码时所做的课程实验&#xff0…

自适应Huffman编码

自适应Huffman编码&#xff0c;可用初始编码表&#xff08;数字音视频技术&#xff0c;实验二&#xff09; 如果你已经理解了 自适应Huffman编码 &#xff0c;那么你不应该浪费时间在无聊的实验上 实验目的 1、深入掌握自适应Huffman编码的原理 2、掌握自适应Huffman编码算法…

huffman python,哈夫曼(Huffman)编码python代码实现

首先看定义 哈夫曼编码(Huffman Coding)&#xff0c;又称霍夫曼编码&#xff0c;是一种编码方式&#xff0c;哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法&#xff0c;该方法完全依据字符出现概率来构造异字头的平均长度最短的码字&#xff0c;有时称…

Huffman Tree

Huffman Tree 哈夫曼树&#xff1b;哈夫曼编码&#xff1b;最优二叉树 自底向上 变长编码&#xff1b;前缀编码&#xff1b;熵编码 数据无损压缩&#xff1b;最短编码&#xff1b;最佳判定树 一、基本概念 Huffman Tree&#xff0c;又称最优二叉树&#xff0c;是带权路径长度最…

Huffman Codes

题目 In 1953, David A. Huffman published his paper “A Method for the Construction of Minimum-Redundancy Codes”,and hence printed his name in the history of computer science. As a professor who gives the final exam problem on Huffman codes, I am encounte…

HuffmanTree

#include "stdafx.h" #include "stdio.h" #include "stdlib.h" #include "string.h"typedef int ELEMTYPE;//哈弗曼树节点结构体 typedef struct HuffmanTree {ELEMTYPE weight;ELEMTYPE id;//区分权值相同的节点struct HuffmanTree* …

JPEG中Huffman解码实例讲解

DHT Huffuman表格式 -------------------------------------------------------------------------- 名称 字节数 值 说明 -------------------------------------------------------------------------- 段标识 1 FF 段类型 1 C4 段…