導航:首頁 > 操作系統 > android發送udp廣播

android發送udp廣播

發布時間:2023-01-06 13:44:48

1. android udp接收不到數據

1、可先在oncreate()方法裡面實例化一個WifiManager.MulticastLock 對象lock;具體如下:
WifiManager manager = (WifiManager) this
.getSystemService(Context.WIFI_SERVICE);
WifiManager.MulticastLock lock= manager.createMulticastLock("test wifi");

2、在調用廣播發送、接收報文之前先調用lock.acquire()方法;
3、用完之後及時調用lock.release()釋放資源,否決多次調用lock.acquire()方法,程序可能會崩,詳情請見
Caused by: java.lang.UnsupportedOperationException: Exceeded maximum number of wifi locks
注;記得在配置文件裡面添加如下許可權:
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />

經過這樣處理後,多數手機都能正常發送接收到廣播報文。
本小點轉載自Android手機接收不到UDP報文
二、在UDP通信中,android端發送UDP廣播包沒有問題。至於接收的話,有時候不能接收到包。
在UDP通信中,android端發送UDP廣播包沒有問題。至於接收的話,有時候不能接收到包。但是如果UDP包中指定了目標主機的地址的話,那麼android端就能正常接收。
下面上一段代碼,大家可用這段代碼進行測試。
1、在一個Service裡面,我們創建一個線程

public void onCreate() {//用於創建線程
WifiManager manager = (WifiManager) this
.getSystemService(Context.WIFI_SERVICE);
udphelper = new UdpHelper(manager);

//傳遞WifiManager對象,以便在UDPHelper類裡面使用MulticastLock
udphelper.addObserver(MsgReceiveService.this);
tReceived = new Thread(udphelper);
tReceived.start();
super.onCreate();
}

2、弄一個UDP幫助類,這個類主要用於發送和接收數據

package com.example.com.ihome.bang.util;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Observable;
import com.example.com.ihome.bang.tool.SendThread;
import android.net.wifi.WifiManager;
import android.util.Log;

/**
*
* UdpHelper幫助類
*
* @author 陳喆榕
*
*/
public class UdpHelper implements Runnable {
public Boolean IsThreadDisable = false;//指示監聽線程是否終止
private static WifiManager.MulticastLock lock;
InetAddress mInetAddress;
public UdpHelper(WifiManager manager) {
this.lock= manager.createMulticastLock("UDPwifi");
}
public void StartListen() {
// UDP伺服器監聽的埠
Integer port = 8903;
// 接收的位元組大小,客戶端發送的數據不能超過這個大小
byte[] message = new byte[100];
try {
// 建立Socket連接
DatagramSocket datagramSocket = new DatagramSocket(port);
datagramSocket.setBroadcast(true);
DatagramPacket datagramPacket = new DatagramPacket(message,
message.length);
try {
while (!IsThreadDisable) {
// 准備接收數據
Log.d("UDP Demo", "准備接受");
this.lock.acquire();

datagramSocket.receive(datagramPacket);
String strMsg=new String(datagramPacket.getData()).trim();
Log.d("UDP Demo", datagramPacket.getAddress()
.getHostAddress().toString()
+ ":" +strMsg );this.lock.release();
}
} catch (IOException e) {//IOException
e.printStackTrace();
}
} catch (SocketException e) {
e.printStackTrace();
}

}
public static void send(String message) {
message = (message == null ? "Hello IdeasAndroid!" : message);
int server_port = 8904;
Log.d("UDP Demo", "UDP發送數據:"+message);
DatagramSocket s = null;
try {
s = new DatagramSocket();
} catch (SocketException e) {
e.printStackTrace();
}
InetAddress local = null;
try {
local = InetAddress.getByName("255.255.255.255");
} catch (UnknownHostException e) {
e.printStackTrace();
}
int msg_length = message.length();
byte[] messageByte = message.getBytes();
DatagramPacket p = new DatagramPacket(messageByte, msg_length, local,
server_port);
try {

s.send(p);
s.close();

} catch (IOException e) {
e.printStackTrace();
}
}

@Override
public void run() {
StartListen();
}
}

希望能幫到你。

2. android:udp廣播

首先手機作為終端 可以不必要知道終端的數量、 還有就是我建議你多學習下基礎,android的廣播機制不是把廣播在終端之間傳輸,廣播是在應用程序裡面發送,在應用程序進行接收。個人建議基礎才是王道。 對於你現在這個問題,不妨採用發送消息的方式 實現該功能。一個終端發送消息 其他終端接收消息,當然也相當於寫一個socket通信。通信建立之後 ,可以取得各個連接的終端的IP 然後怎麼邏輯就看你怎麼寫演算法了。還有就是,這個功能也可以用消息推送的方式(建議採用此方法)、android系統內置有消息推送,邏輯都和上述的差不多,至於具體用那些方法 那些內置類,個人建議多查API。軟體開發必須靠自學。。。。

3. (三)Android區域網內語音對講 基於UDP語音傳輸

之前研究了基於UDP的文字傳輸 點擊打開鏈接 ,以及Android端的語音錄制 點擊打開鏈接 ,這篇文章就記錄一下Android端區域網內的語音傳輸,簡單的實現語音對講,當然裡面還存在著很多問題,包括語音不清晰啊、雜音多啊,不管了,先聽見聲音就行了。測試的時候兩部手機,上圖:

程序寫了兩個線程,一個用於錄制AudioRecordThread,一個用於播放AudioTrackThread.

(一)錄制與發送

@Override

public void run() {

if (mSocket == null)

return;

try {

mStartTime = System.currentTimeMillis();

audioRec.startRecording();

while (flag) {

try {

byte[] bytes_pkg = buffer.clone();

if (mRecordQueue.size() >= 2) {

int length = audioRec.read(buffer, 0, minBufferSize);

//獲取音量大小

mVolume = getAudioColum(buffer);

System.out.println(TAG + "= " + mVolume);

Message message = mHandler.obtainMessage();

message.arg1 = (int) mVolume;

mHandler.sendMessage(message);

DatagramPacket writePacket;

InetAddress inet = InetAddress.getByName(inetAddressName);

writePacket = new DatagramPacket(buffer, length, inet, PORT);

writePacket.setLength(length);

System.out.println("AudioRTwritePacket = " + writePacket.getData().toString());

mSocket.send(writePacket);

}

mRecordQueue.add(bytes_pkg);

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

audioRec.stop();

} catch (Exception e) {

e.printStackTrace();

}

}

裡麵包含了獲取音量大小,便於在頁面上面展示,方法參考了 點擊打開鏈接

private double getAudioColum(byte[] buffer) {

double sumVolume = 0.0;

double avgVolume = 0.0;

double volume = 0.0;

for (int i = 0; i < buffer.length; i += 2) {

int v1 = buffer[i] & 0xFF;

int v2 = buffer[i + 1] & 0xFF;

int temp = v1 + (v2 << 8);// 小端

if (temp >= 0x8000) {

temp = 0xffff - temp;

}

sumVolume += Math.abs(temp);

}

avgVolume = sumVolume / buffer.length / 2;

volume = Math.log10(1 + avgVolume) * 10;

return volume;

}

(二)接收與播放

@Override

public void run() {

if (mSocket == null)

return;

//從文件流讀數據

audioTrk.play();

while (flag) {

DatagramPacket recevPacket;

try {

recevPacket = new DatagramPacket(buffer, 0, buffer.length);

mSocket.receive(recevPacket);

audioTrk.write(recevPacket.getData(), 0, recevPacket.getLength());

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

audioTrk.stop();

}

(三)主頁面 接收按鈕事件

@OnClick({R.id.btn_receive})

public void onViewClicked(View view) {

switch (view.getId()) {

case R.id.btn_receive:

if (btnReceive.getText().toString().equals("開始接收")) {

btnReceive.setText("停止接收");

try {

if (audioTrackThread == null) {

audioTrackThread = new AudioTrackThread();

}

new Thread(audioTrackThread).start();

} catch (SocketException e) {

e.printStackTrace();

}

} else {

btnReceive.setText("開始接收");

audioTrackThread.setFlag(false);

}

break;

}

}

(四)發送按鈕事件

ivSpeak.setOnTouchListener(new View.OnTouchListener() {

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)

@Override

public boolean onTouch(View v, MotionEvent event) {

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

//按下按鈕開始錄制

ivSpeak.setText("正在說話");

//顯示錄音提示

relativeLayout.setVisibility(View.VISIBLE);

try {

if (audioRecordThread == null) {

audioRecordThread = new AudioRecordThread(handler);

}

audioRecordThread.setInetAddressName(tvReceiveIp.getText().toString());

audioRecordThread.setFlag(true);

new Thread(audioRecordThread).start();

} catch (SocketException e) {

e.printStackTrace();

}

break;

case MotionEvent.ACTION_UP:

case MotionEvent.ACTION_CANCEL:

//松開按鈕結束錄制

ivSpeak.setText("按住說話");

relativeLayout.setVisibility(View.GONE);

audioRecordThread.setFlag(false);

mStopTime = audioRecordThread.getmStopTime();

mStartTime = audioRecordThread.getmStartTime();

creatMessageBean((mStopTime - mStartTime) / 1000, true);

break;

}

return true;

}

});

4. Android UDP通訊(簡單demo)

本章節 比較簡單
直接上code了
首先創建一個UDP class 構造方法如下
通過newFixedThreadPool 創建一個線程池

然後
一個startUdp scoket 重要步驟

startSocketThread是一個 接收消息的子線程
內部是一個接收消息的循環
BROADCAST_IP 是通信對方的地址

利用廣播 把接收到的消息列印到前台

再然後創建一個發送message的方法

文章所有code 地址---> github
https://github.com/hanjole/Udpscoket_demo

5. android 如何定時發udp

定時執行任務可以考慮使用AlarmManager配合BroadcastReceiver實現
AlarmManager定時發出intent,BroadCastReceiver收到這個intent後進行發送UDP的操作

6. Android 手機上能通過DatagramSocket收到PC端的UDP廣播嗎

在PC端直接用tcp調試助手發送數據,我另一台電腦能收到的,但是android的卻是有時可以收到有時收不到,平均幾十次收到10次左右,丟包不可能這么嚴重吧。,android的代碼如下,
ds = new DatagramSocket(1234, InetAddress.getByName(「192.168.1.3」));
dp = new DatagramPacket(content, content.length);
ds.receive(dp);
如果我在pc端發送綁定了IP的UDP數據包,android可以收到數據,但是PC端發送255的廣播UDP,android就收不到了。。查了一些資料,說是要加入許可權,加入以下的代碼,但實測發現效果一樣。

WifiManager manager = (WifiManager) this.getSystemService(Context.WIFI_SERVICE); WifiManager.MulticastLock lock= manager.createMulticastLock("localWifi");

7. (四)Android基於UDP的多客戶端語音通信

在前三篇得基礎上,這次研究了組播功能。非常感謝https://blog.csdn.net/jspping/article/details/64438515得貢獻!

組播也就是通過MulticastSocket來進行開發,與DatagramSocket比較相類似,這次依然是用兩個線程進行實現,發送線程MultiSendThread和接收線程MultiReceiveThread。廢話不多說,開始碼:

(一)MultiSendThread:

(1)初始化MuticastSocket

// 偵聽的埠

try {

    multicastSocket = new MulticastSocket(8082);

    // 使用D類地址,該地址為發起組播的那個ip段,即偵聽10001的套接字

    address = InetAddress.getByName("239.0.0.1");

} catch (IOException e) {

    e.printStackTrace();

}

(2)初始化AudioRecord

protected LinkedList<byte[]> mRecordQueue;

int minBufferSize;

private static AcousticEchoCanceler aec;

private static AutomaticGainControl agc;

private static NoiseSuppressor nc;

AudioRecord audioRec;

byte[] buffer;

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)

private void initAudio() {

    //播放的采樣頻率 和錄制的采樣頻率一樣

    int sampleRate = 44100;

    //和錄制的一樣的

    int audioFormat = AudioFormat.ENCODING_PCM_16BIT;

    //錄音用輸入單聲道  播放用輸出單聲道

    int channelConfig = AudioFormat.CHANNEL_IN_MONO;

    minBufferSize = AudioRecord.getMinBufferSize(

            sampleRate,

            channelConfig, AudioFormat.ENCODING_PCM_16BIT);

    System.out.println("****RecordMinBufferSize = " + minBufferSize);

    audioRec = new AudioRecord(

            MediaRecorder.AudioSource.MIC,

            sampleRate,

            channelConfig,

            audioFormat,

            minBufferSize);

    buffer = new byte[minBufferSize];

    if (audioRec == null) {

        return;

    }

    //聲學回聲消除器 AcousticEchoCanceler 消除了從遠程捕捉到音頻信號上的信號的作用

    if (AcousticEchoCanceler.isAvailable()) {

        aec = AcousticEchoCanceler.create(audioRec.getAudioSessionId());

        if (aec != null) {

            aec.setEnabled(true);

        }

    }

    //自動增益控制 AutomaticGainControl 自動恢復正常捕獲的信號輸出

    if (AutomaticGainControl.isAvailable()) {

        agc = AutomaticGainControl.create(audioRec.getAudioSessionId());

        if (agc != null) {

            agc.setEnabled(true);

        }

    }

    //雜訊抑制器 NoiseSuppressor 可以消除被捕獲信號的背景噪音

    if (NoiseSuppressor.isAvailable()) {

        nc = NoiseSuppressor.create(audioRec.getAudioSessionId());

        if (nc != null) {

            nc.setEnabled(true);

        }

    }

    mRecordQueue = new LinkedList<byte[]>();

}

(3)開始錄制,並實時發送出去

@Override

public void run() {

    if (multicastSocket == null)

        return;

    try {

        audioRec.startRecording();

        while (true) {

            try {

                byte[] bytes_pkg = buffer.clone();

                if (mRecordQueue.size() >= 2) {

                    int length = audioRec.read(buffer, 0, minBufferSize);

                    // 組報

                    DatagramPacket datagramPacket = new DatagramPacket(buffer, length);

                    // 向組播ID,即接收group /239.0.0.1  埠 10001

                    datagramPacket.setAddress(address);

                    // 發送的埠號

                    datagramPacket.setPort(10001);

                    System.out.println("AudioRTwritePacket = " + datagramPacket.getData().toString());

                    multicastSocket.send(datagramPacket);

                }

                mRecordQueue.add(bytes_pkg);

            } catch (Exception e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            }

        }

    } catch (Exception e) {

        e.printStackTrace();

    }

}

(二)MultiReceiveThread

(1)初始化MulticastSocket

// 接收數據時需要指定監聽的埠號

try {

    multicastSocket = new MulticastSocket(10001);

    // 創建組播ID地址

    InetAddress address = InetAddress.getByName("239.0.0.1");

    // 加入地址

    multicastSocket.joinGroup(address);

} catch (IOException e) {

    e.printStackTrace();

}

(2)初始化AudioTrack

byte[] buffer;

AudioTrack audioTrk;

private void initAudioTracker() {

    //揚聲器播放

    int streamType = AudioManager.STREAM_MUSIC;

    //播放的采樣頻率 和錄制的采樣頻率一樣

    int sampleRate = 44100;

    //和錄制的一樣的

    int audioFormat = AudioFormat.ENCODING_PCM_16BIT;

    //流模式

    int mode = AudioTrack.MODE_STREAM;

    //錄音用輸入單聲道  播放用輸出單聲道

    int channelConfig = AudioFormat.CHANNEL_OUT_MONO;

    int recBufSize = AudioTrack.getMinBufferSize(

            sampleRate,

            channelConfig,

            audioFormat);

    System.out.println("****playRecBufSize = " + recBufSize);

    audioTrk = new AudioTrack(

            streamType,

            sampleRate,

            channelConfig,

            audioFormat,

            recBufSize,

            mode);

    audioTrk.setStereoVolume(AudioTrack.getMaxVolume(),

            AudioTrack.getMaxVolume());

    buffer = new byte[recBufSize];

}

(3)開始接收,並進行實時播放

@Override

public void run() {

    if (multicastSocket == null)

        return;

    //從文件流讀數據

    audioTrk.play();

    // 包長

    while (true) {

        try {

            // 數據報

            DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length);

            // 接收數據,同樣會進入阻塞狀態

            multicastSocket.receive(datagramPacket);

          audioTrk.write(datagramPacket.getData(), 0, datagramPacket.getLength());

        } catch (IOException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

    }

}

(三)開始測試

MultiSendThread multiSendThread;

MultiReceiverThread multiReceiverThread;

@OnClick({R.id.btnSend, R.id.btnReceive})

public void onViewClicked(View view) {

    switch (view.getId()) {

        case R.id.btnSend:

            if (multiSendThread == null) {

                multiSendThread = new MultiSendThread();

            }

            new Thread(multiSendThread).start();

            break;

        case R.id.btnReceive:

            if (multiReceiverThread == null) {

                multiReceiverThread = new MultiReceiverThread();

            }

            new Thread(multiReceiverThread).start();

            break;

    }

}

8. android接收不到udp包嗎

1、有的手機不能直接接收UDP包,可能是手機廠商在定製Rom的時候把這個功能給關掉了。
2、在UDP通信中,android端發送UDP廣播包沒有問題。至於接收的話,有時候不能接收到包。

9. Android 使用udp發送廣播

最近做項目時,遇到一個對新人我來說稍微有點麻煩的事情!

那就是使用udp協議發送廣播獲取伺服器地址

http都好說,github開源項目不知道有多少。

可是再難的問題也要去解決!

發送廣播需要許可權!

AndroidManifest.xml 中添加:

最少這三個是必須的,多的也忘了!
原因後面會講到

使用到RxJava:

udp發送與接受都需指定埠號
廣播地址是255.255.255.255

在之前添加許可權的時候CHANGE_WIFI_MULTICAST_STATE有添加這個
往下面看

接下來我們開啟接收udp信息

發送消息?

謝謝該作者的文章讓我學會udp發送
https://blog.csdn.net/tanghongchang123/article/details/53609237

10. Android 基於UDP的Socket通信

1、連接DatagramSocket的服務端(ip和port):開啟非同步線程和socket
2、發送數據(DatagramPacket):非同步
3、接收數據(DatagramPacket):注意連接狀態,非同步讀取
4、關閉連接:關閉DatagramSocket和對應線程

1、異常:android.os.NetworkOnMainThreadException。 socket需要在線程中使用
2、前後端統一傳輸或者接收協議 [requestcode size d1 d2 d3 ... ],在解析時候用得到
3、實施監控socket的連接狀態,還是用心跳包發過去,然後返回數據,一段時間沒有的話則代表socket連接失敗。
4、注意receive接收數據後的有效長度(一個是預存的buffer,一個是有效結果buffer)
5、客戶端連上去後不知道為何一定要先發送一次,才能接收?
6、UDP不安全,有長度限制64K

2019 (* ̄(oo) ̄) 諸事順利!

閱讀全文

與android發送udp廣播相關的資料

熱點內容
吉安程序員招聘 瀏覽:166
不能下載的單片機 瀏覽:940
程序員子女昌平二中考出來的名校 瀏覽:677
令牌桶演算法實現 瀏覽:74
tc腳本文件夾 瀏覽:732
學會繪畫pdf 瀏覽:954
隱身俠加密寶手機版 瀏覽:135
農行app怎麼辦理簽約手續 瀏覽:185
汽車壓力解壓神器 瀏覽:307
家用冰箱壓縮機有風扇嗎 瀏覽:647
安卓qq年齡怎麼看 瀏覽:839
屏幕跳屏亂點app怎麼解決 瀏覽:414
turbo加速器android 瀏覽:432
洪尚秀的電影哪裡哪個app能看 瀏覽:151
百度網站加密視頻怎麼下載 瀏覽:135
台州ug產品編程培訓班 瀏覽:866
Javalinux字體 瀏覽:520
77萬年會程序員補貼 瀏覽:610
滅火是由近及源碼 瀏覽:158
資料伺服器地址 瀏覽:8