I am working on a peer to peer to voice call application in Android for my college project. I found sample code for streaming the mic audio through UDP. That code will help me to stream the WAV file through UDP. But it doesn't play some files properly. And also that code doesn't stream mic audio.
Please help me.
public class UdpStream extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.udpstream);
Button btnSend = (Button)findViewById(R.id.btnSend);
btnSend.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.d(LOG_TAG, "btnSend clicked");
SendAudio();
}
});
Button btnRecv = (Button)findViewById(R.id.btnRecv);
btnRecv.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.d(LOG_TAG, "btnRecv clicked");
RecvAudio();
}
});
Button btnStrmic = (Button)findViewById(R.id.btnStrmic);
btnStrmic.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.d(LOG_TAG, "btnStrmic clicked");
SendMicAudio();
}
});
}
static final String LOG_TAG = "UdpStream";
static final String AUDIO_FILE_PATH = "/sdcard/1.wav";
static final int AUDIO_PORT = 2048;
static final int SAMPLE_RATE = 8000;
static final int SAMPLE_INTERVAL = 20; // milliseconds
static final int SAMPLE_SIZE = 2; // bytes per sample
static final int BUF_SIZE = SAMPLE_INTERVAL*SAMPLE_INTERVAL*SAMPLE_SIZE*2;
protected String host="localhost";
public void RecvAudio()
{
Thread thrd = new Thread(new Runnable() {
#Override
public void run()
{
Log.e(LOG_TAG, "start recv thread, thread id: "
+ Thread.currentThread().getId());
AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC,
SAMPLE_RATE, AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT, BUF_SIZE,
AudioTrack.MODE_STREAM);
track.play();
try
{
DatagramSocket sock = new DatagramSocket(AUDIO_PORT);
byte[] buf = new byte[BUF_SIZE];
while(true)
{
DatagramPacket pack = new DatagramPacket(buf, BUF_SIZE);
sock.receive(pack);
Log.d(LOG_TAG, "recv pack: " + pack.getLength());
track.write(pack.getData(), 0, pack.getLength());
}
}
catch (SocketException se)
{
Log.e(LOG_TAG, "SocketException: " + se.toString());
}
catch (IOException ie)
{
Log.e(LOG_TAG, "IOException" + ie.toString());
}
} // end run
});
thrd.start();
}
Toast toast;
int port=3008;
public void SendAudio()
{
toast=Toast.makeText(getApplicationContext(), port + " : " + host , Toast.LENGTH_SHORT);
Thread thrd = new Thread(new Runnable() {
#Override
public void run()
{
Log.e(LOG_TAG, "start send thread, thread id: "
+ Thread.currentThread().getId());
long file_size = 0;
int bytes_read = 0;
int bytes_count = 0;
File audio = new File(AUDIO_FILE_PATH);
FileInputStream audio_stream = null;
file_size = audio.length();
byte[] buf = new byte[BUF_SIZE];
try
{
EditText d= (EditText) findViewById(R.id.txttohost);
host=d.getText().toString();
if(host=="")
{
port=2048;
host="localhost";
}
port=2048;
InetAddress addr = InetAddress.getByName(host);
toast.setText(port + " : " + addr.toString());
toast.show();
DatagramSocket sock = new DatagramSocket();
audio_stream = new FileInputStream(audio);
while(bytes_count < file_size)
{
bytes_read = audio_stream.read(buf, 0, BUF_SIZE);
DatagramPacket pack = new DatagramPacket(buf, bytes_read,
addr, port);
sock.send(pack);
bytes_count += bytes_read;
Log.d(LOG_TAG, "bytes_count : " + bytes_count);
Thread.sleep(SAMPLE_INTERVAL, 0);
}
}
catch (InterruptedException ie)
{
Log.e(LOG_TAG, "InterruptedException");
}
catch (FileNotFoundException fnfe)
{
Log.e(LOG_TAG, "FileNotFoundException");
}
catch (SocketException se)
{
Log.e(LOG_TAG, "SocketException");
}
catch (UnknownHostException uhe)
{
Log.e(LOG_TAG, "UnknownHostException");
}
catch (IOException ie)
{
Log.e(LOG_TAG, "IOException");
}
} // end run
});
thrd.start();
}
public void SendMicAudio()
{
Thread thrd = new Thread(new Runnable() {
#Override
public void run()
{
Log.e(LOG_TAG, "start SendMicAudio thread, thread id: "
+ Thread.currentThread().getId());
AudioRecord audio_recorder = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, SAMPLE_RATE,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT,
AudioRecord.getMinBufferSize(SAMPLE_RATE,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT) * 10);
int bytes_read = 0;
int bytes_count = 0;
byte[] buf = new byte[BUF_SIZE];
try
{
InetAddress addr = InetAddress.getLocalHost();
DatagramSocket sock = new DatagramSocket();
while(true)
{
bytes_read = audio_recorder.read(buf, 0, BUF_SIZE);
DatagramPacket pack = new DatagramPacket(buf, bytes_read,
addr, AUDIO_PORT);
sock.send(pack);
bytes_count += bytes_read;
Log.d(LOG_TAG, "bytes_count : " + bytes_count);
Thread.sleep(SAMPLE_INTERVAL, 0);
}
}
catch (InterruptedException ie)
{
Log.e(LOG_TAG, "InterruptedException");
}
// catch (FileNotFoundException fnfe)
// {
// Log.e(LOG_TAG, "FileNotFoundException");
// }
catch (SocketException se)
{
Log.e(LOG_TAG, "SocketException");
}
catch (UnknownHostException uhe)
{
Log.e(LOG_TAG, "UnknownHostException");
}
catch (IOException ie)
{
Log.e(LOG_TAG, "IOException");
}
} // end run
});
thrd.start();
}
}
As for as concern with my question....
The Solution is Always while playing the Audio through out speaker will cause Some noise....
So i found the following two solution to fix that...
1) Play the audio through ear piece
audio_service.setSpeakerphoneOn(false);
audio_service.setMode(AudioManager.MODE_IN_CALL);
audio_service.setRouting(AudioManager.MODE_NORMAL,AudioManager.ROUTE_EARPIECE,
AudioManager.ROUTE_ALL);
2) Next way to do use Some Audio Codec for encoding and Decoding Your Audio to play that in noiseless..
Related
Server side code
public class MainActivity extends AppCompatActivity {
TextView infoIp, infoPort;
static final int SocketServerPORT = 8080;
ServerSocket serverSocket;
ServerSocketThread serverSocketThread;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
infoIp = (TextView) findViewById(R.id.infoip);
infoPort = (TextView) findViewById(R.id.infoport);
infoIp.setText(getIpAddress());
serverSocketThread = new ServerSocketThread();
serverSocketThread.start();
}
#Override
protected void onDestroy() {
super.onDestroy();
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private String getIpAddress() {
String ip = "";
try {
Enumeration<NetworkInterface> enumNetworkInterfaces = NetworkInterface
.getNetworkInterfaces();
while (enumNetworkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = enumNetworkInterfaces
.nextElement();
Enumeration<InetAddress> enumInetAddress = networkInterface
.getInetAddresses();
while (enumInetAddress.hasMoreElements()) {
InetAddress inetAddress = enumInetAddress.nextElement();
if (inetAddress.isSiteLocalAddress()) {
ip += "SiteLocalAddress: "
+ inetAddress.getHostAddress() + "\n";
}
}
}
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
ip += "Something Wrong! " + e.toString() + "\n";
}
return ip;
}
public class ServerSocketThread extends Thread {
#Override
public void run() {
Socket socket = null;
try {
serverSocket = new ServerSocket(SocketServerPORT);
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
infoPort.setText("I'm waiting here: "
+ serverSocket.getLocalPort());
}});
while (true) {
socket = serverSocket.accept();
FileTxThread fileTxThread = new FileTxThread(socket);
fileTxThread.start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
public class FileTxThread extends Thread {
Socket socket;
FileTxThread(Socket socket){
this.socket= socket;
}
#Override
public void run() {
File file = new File(
Environment.getExternalStorageDirectory(),
"graphs.txt");
byte[] bytes = new byte[(int) file.length()];
BufferedInputStream bis;
try {
bis = new BufferedInputStream(new FileInputStream(file));
bis.read(bytes, 0, bytes.length);
OutputStream os = socket.getOutputStream();
os.write(bytes, 0, bytes.length);
os.flush();
socket.close();
final String sentMsg = "File sent to: " + socket.getInetAddress();
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this,
sentMsg,
Toast.LENGTH_LONG).show();
}});
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
Client Side Code :
public class MainActivity extends AppCompatActivity {
EditText editTextAddress;
Button buttonConnect;
TextView textPort;
static final int SocketServerPORT = 8080;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editTextAddress = (EditText) findViewById(R.id.address);
textPort = (TextView) findViewById(R.id.port);
textPort.setText("port: " + SocketServerPORT);
buttonConnect = (Button) findViewById(R.id.connect);
buttonConnect.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
ClientRxThread clientRxThread =new ClientRxThread(editTextAddress.getText().toString(),SocketServerPORT);
clientRxThread.start();
}});
}
private class ClientRxThread extends Thread {
String dstAddress;
int dstPort;
ClientRxThread(String address, int port) {
dstAddress = address;
dstPort = port;
}
#Override
public void run() {
Socket socket = null;
try {
socket = new Socket(dstAddress, dstPort);
File file = new File(Environment.getExternalStorageDirectory(),"graphs.txt");
byte[] bytes = new byte[8192];
InputStream is = socket.getInputStream();
FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int bytesRead = is.read(bytes, 0, bytes.length);
bos.write(bytes, 0, bytesRead);
bos.close();
socket.close();
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this,
"Finished",
Toast.LENGTH_LONG).show();
}});
} catch (IOException e) {
e.printStackTrace();
final String eMsg = "Something wrong: " + e.getMessage();
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this,
eMsg,
Toast.LENGTH_LONG).show();
}});
} finally {
if(socket != null){
try {
System.out.println("socket not null "+socket);
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
Error shoews in client side :
E/AndroidRuntime: FATAL EXCEPTION: Thread-2648
Process: com.example.moraya.socketfileserverside1, PID: 30793
java.lang.ArrayIndexOutOfBoundsException: length=8192; regionStart=0; regionLength=-1
at java.util.Arrays.checkOffsetAndCount(Arrays.java:1719)
at java.io.BufferedOutputStream.write(BufferedOutputStream.java:135)
hi sir, i am trying to transfer file client to server by using socket, but after click on connect button client side application says unfortunately application has stopped and also the empty text file send into the sdcard.
please help me what is the error and how to solve it.
I am trying to transmit a continuous stream of data to multiple devices over a portable hotspot connection using sockets.
I am facing two problems:
The message only gets displayed to the client AFTER all the messages are displayed in msg TextView on the server end. So if I use an infinite while(true) loop instead of for(int i = 0; i < 1000; i++), in ServerSocketReplyThread, the message never gets transmitted, and the client eventually crashes
I am unable to connect another client to the server until all the messages have been transmitted to the first client.
How do I structure the code to ensure simultaneous, real-time transmission to multiple clients?
Here's what the code looks like:
I am using an activity called Transmit activity, where I am instantiating the msg Textview, which replays the sent messages, and a server object.
msg = (TextView) findViewById(R.id.server_replayed_messages);
Server server = new Server(this);
The Server class is as follows:
public class Server {
TransmitActivity activity;
ServerSocket serverSocket;
String message = "";
static final int socketServerPORT = 8080;
ArrayList<Socket> socketList = new ArrayList<Socket>();
public Server(TransmitActivity a) {
this.activity = a;
Thread socketServerThread = new Thread(new SocketServerThread());
socketServerThread.start();
}
public int getPort() {
return socketServerPORT;
}
public void onDestroy() {
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private class SocketServerThread extends Thread {
int count = 0;
#Override
public void run() {
try {
// create ServerSocket using specified port
serverSocket = new ServerSocket(socketServerPORT);
while (true) {
// block the call until connection is created and return
// Socket object
Socket socket = serverSocket.accept();
count++;
message += "#" + count + " from "
+ socket.getInetAddress() + ":"
+ socket.getPort() + "\n";
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
activity.msg.setText(message);
}
});
SocketServerReplyThread socketServerReplyThread =
new SocketServerReplyThread(socket, count);
socketServerReplyThread.run();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private class SocketServerReplyThread extends Thread {
private Socket hostThreadSocket;
int cnt;
SocketServerReplyThread(Socket socket, int c) {
hostThreadSocket = socket;
cnt = c;
}
#Override
public void run() {
OutputStream outputStream;
for(int i = 0; i < 1000; i++) {
String msgReply = DateFormat.getDateTimeInstance().format(new Date());
try {
outputStream = hostThreadSocket.getOutputStream();
PrintStream printStream = new PrintStream(outputStream);
printStream.print(msgReply);
printStream.flush();
message += "replayed: " + msgReply + "\n";
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
activity.msg.setText(message);
}
});
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
message += "Something wrong in SocketServerReplyThread! " + e.toString() + "\n";
}
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
activity.msg.setText(message);
}
});
}
}
}
}
On the client side I have a ReceiveActivity, where I am using the following code when a "Connect" button is clicked:
Client myClient = new Client(editTextAddress.getText()
.toString(), Integer.parseInt(editTextPort
.getText().toString()), response);
myClient.execute();
The Client class is as follows:
public class Client extends AsyncTask<Void, Void, Void> {
String dstAddress;
int dstPort;
String response = "";
TextView textResponse;
Client(String addr, int port, TextView textResponse) {
dstAddress = addr;
dstPort = port;
this.textResponse = textResponse;
}
#Override
protected Void doInBackground(Void... arg0) {
Socket socket = null;
try {
socket = new Socket(dstAddress, dstPort);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(1024);
byte[] buffer = new byte[1024];
int bytesRead;
InputStream inputStream = socket.getInputStream();
/*
* notice: inputStream.read() will block if no data return
*/
while ((bytesRead = inputStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, bytesRead);
response += byteArrayOutputStream.toString("UTF-8");
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
response = "UnknownHostException: " + e.toString();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
response = "IOException: " + e.toString();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return null;
}
#Override
protected void onPostExecute(Void result) {
textResponse.setText(response);
super.onPostExecute(result);
}
}
Any help would be much appreciated.
Following options resulting shown error
Android App + Multicast + Tethering On + Cell Data Off
If I connected to wifi router, no errors happen. What do I wrong or is android+multicast+tethering impossible?
public class Multicast {
final static String INET_ADDR = "224.0.0.1";
final static int PORT = 8888;
private Context mContext;
public Multicast(Context context) {
mContext = context;
}
public static NetworkInterface getWlanEth() {
final String TAG = "NetworkInterface";
Enumeration<NetworkInterface> enumeration = null;
try {
enumeration = NetworkInterface.getNetworkInterfaces();
} catch (SocketException e) {
e.printStackTrace();
}
NetworkInterface wlan0 = null;
StringBuilder sb = new StringBuilder();
while (enumeration.hasMoreElements()) {
wlan0 = enumeration.nextElement();
sb.append(wlan0.getName() + " ");
if (wlan0.getName().equals("wlan0")) {
return wlan0;
}
}
return null;
}
#TargetApi(Build.VERSION_CODES.KITKAT)
public void startMulticastServer() {
Thread sendThread = new Thread(new Runnable() {
DatagramSocket serverSocket;
#Override
public void run() {
try {
if (serverSocket == null) {
serverSocket = new DatagramSocket(null);
serverSocket.setReuseAddress(true);
serverSocket.setBroadcast(true);
serverSocket.bind(new InetSocketAddress(PORT));
serverSocket.setSoTimeout(15000);
}
for (int i = 0; i < 5; i++) {
String msg = "Sent message no " + i;
InetAddress group = InetAddress.getByName(INET_ADDR);
DatagramPacket msgPacket = new DatagramPacket(msg.getBytes(),
msg.getBytes().length, group, PORT);
serverSocket.send(msgPacket);
String TAG = "Multicast-send";
Log.i(TAG, "Socket 1 send msg: " + msg);
Thread.sleep(500);
}
} catch (IOException ex) {
ex.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
serverSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
});
sendThread.start();
}
public void startMulticastClient() {
Thread getThread = new Thread(new Runnable() {
byte[] buf = new byte[256];
#TargetApi(Build.VERSION_CODES.KITKAT)
#Override
public void run() {
//Acquire the MulticastLock
WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
MulticastLock multicastLock = wifi.createMulticastLock("multicastLock");
multicastLock.setReferenceCounted(true);
multicastLock.acquire();
// Create a new Multicast socket (that will allow other sockets/programs
// to join it as well.
try {
MulticastSocket clientSocket = new MulticastSocket(PORT);
//Joint the Multicast group.
clientSocket.joinGroup(new InetSocketAddress(InetAddress.getByName(INET_ADDR), PORT), getWlanEth());
clientSocket.setLoopbackMode(true);
while (true) {
// Receive the information and print it.
DatagramPacket msgPacket = new DatagramPacket(buf, buf.length);
clientSocket.receive(msgPacket);
String msg = new String(msgPacket.getData());
String TAG = "Multicast-get";
Log.i(TAG, "Socket 1 received msg: " +msgPacket.getAddress()+" : "+ InetAddress.getByName(INET_ADDR) + " : " +msg);
}
} catch (IOException ex) {
multicastLock.release();
ex.printStackTrace();
}
multicastLock.release();
}
});
getThread.start();
}
}
I'm creating an application that gets the get the homestatus from a server in json but this happens on another thread. this isn't a problem when i try to set most Items on the ui because i can set them in a static void. but when i try to create a new switch and space i can't call 'this' to create a new.
code for getting the homestatus:
public void loadHomeStatus()
{
if(socket != null) {`enter code here`
if (socket.isConnected()) {
Log.d("BtnUpdate","already connected");
return;
}
}
swAlarm = (Switch) findViewById(R.id.swAlarmState);
tvTemperature = (TextView) findViewById(R.id.tvTemprateur);
tvHumidity = (TextView) findViewById(R.id.tvHumidity);
llDevices = (LinearLayout) findViewById(R.id.llDevices);
new Thread() {
public void run() {
try
{
busyConnecting = true;
Log.d("loadHomeStatus","trying to connect to: " + host + ":" + port);
socket = new Socket(host, port);
uiConnected();
Log.d("loadHomeStatus","Connected");
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
DataInputStream is = new DataInputStream(socket.getInputStream());
os.writeBytes(password);
Log.d("Connect", "send: " + password);
while (socket.isConnected()) {
byte[] data = new byte[500];
int count = is.read(data);
String recieved = new String(data).trim();
Log.d("loadHomeStatus","recieved " + recieved );
if(recieved.toLowerCase() == "failed")
{
Log.d("loadHomeStatus","failed to log in");
}
else
{
try
{
homeStatus = new Gson().fromJson(recieved, HomeStatus.class);
uiLoadStatus();
} catch (Exception e)
{
Log.d("Error", e.toString());
}
}
}//end of while loop
Log.w("loadHomeStatus", "end connection thread ");
//ends thread
Thread.currentThread().interrupt();
return;
}
catch (UnknownHostException e)
{
e.printStackTrace();
Log.w("loadHomeStatus", "no Failed to connect: " + host + "-" + 8001);
}
catch (IOException e)
{
e.printStackTrace();
Log.w("loadHomeStatus", "no Failed to connect: " + host + "-" + 8001);
}
Log.w("loadHomeStatus","Connection ended");
socket = null;
busyConnecting = false;
uiDisconnected();
}
}.start();
}`
Code for setting ui
public static void uiLoadStatus()
{
if (homeStatus != null)
{
try {
tvTemperature.post(new Runnable()
{
public void run()
{
//Log.d("uiLoadStatus to string",homeStatus.toString());
tvTemperature.setText(homeStatus.temperature + "°C");
tvHumidity.setText(homeStatus.humidity + "%");
}
});
}
catch(Exception e)
{
Log.d("uiLoadStatus status fragment", e.toString());
}
try {
swAlarm.post(new Runnable()
{
public void run() {
swAlarm.setChecked(homeStatus.alarmState);
}
});
}
catch (Exception e)
{
Log.d("uiLoadStatus alarm fragment", e.toString());
}
}
try {
llDevices.post(new Runnable()
{
public void run() {
uiLoadDevices(); //this gives and error because it's not static
}
});
}
catch (Exception e)
{
Log.d("uiLoadStatus alarm fragment", e.toString());
}
}
public void uiLoadDevices()
{
for (int i = 0; i < homeStatus.lstDevices.size(); i++) {
String deviceAdd = homeStatus.lstDevices.get(i);
Space mySpace = new Space(this);
Switch mySwitch = new Switch(this);
mySpace.setMinimumHeight(50);
mySwitch.setText(homeStatus.getName(deviceAdd));
mySwitch.setChecked(homeStatus.getState(deviceAdd));
mySwitch.setTextSize(18);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
lp.gravity = Gravity.LEFT;
llDevices.addView(mySpace, lp);
llDevices.addView(mySwitch, lp);
}
}
You should use AsyncTask and put the network interaction part in the doInBackground() method. To update the UI components, implement those logics in the onPostExecute() method
uiLoadStatus is a static method (not sure why or if it has to be without looking at all of your code) and therefore you cannot call non-static methods from within it, such as uiLoadDevices
I would advise taking a look at your code and update your uiLoadStatus to not be static if at all possible. Abusing static can lead to sloppy code.
I am trying to implement a Reliable UDP protocol for a class assignment in Java. I have managed to add the acknowledgments to every datagram packet that is received, but I am having trouble implementing Sequence Numbers in the datagram packets that I am sending.
Can anyone suggest an easy method to implement this?
#EJP I have tried implementing what you just suggested. This is my code till now (its still very raw - i was using hit and try method to implement it)
Server side
public class TestServer extends Activity {
private DatagramSocket serverSocket;
Thread serverThread = null;
byte[] incomingData;
byte[] outgoingData;
//int numBytesRead = 0;
int ackSent = 0;
int numPackRecv = 0;
int BUF_SIZE = 1024;
String msg = "ACK";
BufferedInputStream data=null;
BufferedOutputStream out =null;
public static final int SERVERPORT = 6000;
String outputFile = "/sdcard/Movies/asddcopy.mp4";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_server);
this.serverThread = new Thread(new ServerThread());
this.serverThread.start();
}
#Override
protected void onStop() {
super.onStop();
try {
serverSocket.close();
} catch (Exception e) {
Log.d("SERVER", "Inside onStop()");
Log.d("SERVER", Log.getStackTraceString(e));
}
}
class ServerThread implements Runnable {
#SuppressLint("NewApi")
public void run() {
try {
serverSocket = new DatagramSocket(SERVERPORT);
incomingData = new byte[BUF_SIZE];
//outgoingData = new byte[512];
outgoingData = msg.getBytes();
long startRxPackets = TrafficStats.getUidRxPackets(Process.myUid());
long startTime = System.nanoTime();
out = new BufferedOutputStream(new FileOutputStream(outputFile, true));
while (!Thread.currentThread().isInterrupted()) {
//serverSocket.setSoTimeout(5000);
while (true) {
try{
//DatagramPacket incomingPacket = new DatagramPacket(incomingData, incomingData.length);
DatagramPacket incomingPacket = new DatagramPacket(incomingData, BUF_SIZE);
serverSocket.receive(incomingPacket);
byte[] data = incomingPacket.getData();
//out.write(data,0,incomingPacket.getLength());
//String msg = new String(incomingPacket.getData());
ByteArrayInputStream in = new ByteArrayInputStream(data);
ObjectInputStream is = new ObjectInputStream(in);
if (is == null) {
is = new ObjectInputStream(in);
}
Message msg = (Message) is.readObject();
System.out.println(msg.getSeqNo());
/*if ("END".equals(msg.substring(0, 3).trim())) {
Log.d("SERVER", "Inside END condition");
break;
}*/
out.write(msg.getData(),0,msg.getData().length);
numPackRecv += 1;
Log.d("SERVER", "Packet Received: " + numPackRecv);
InetAddress client = incomingPacket.getAddress();
int client_port = incomingPacket.getPort();
DatagramPacket outgoingPacket = new DatagramPacket(outgoingData, outgoingData.length, client, client_port);
serverSocket.send(outgoingPacket);
ackSent += 1;
//Log.d("SERVER","Packet Received: " + numPackRecv + " :: " + "Ack Sent: " + ackSent);
}catch(Exception e) {
Log.d("SERVER", "Inside run() ex1");
Log.d("SERVER", Log.getStackTraceString(e));
break;
}
}
out.close();
serverSocket.disconnect();
serverSocket.close();
Log.d("SERVER", "Transfer Complete");
Log.d("SERVER", "Actual Time elapsed = " + (System.nanoTime() - startTime)/Math.pow(10, 9) + " s");
Log.d("SERVER", "Total Packets Received = " + Long.toString(TrafficStats.getUidRxPackets(Process.myUid()) - startRxPackets));
Log.d("SERVER", "Packets Received from Socket = " + numPackRecv);
break;
}
out.close();
serverSocket.disconnect();
serverSocket.close();
/* Log.d("SERVER", "Transfer Complete");
Log.d("SERVER", "Actual Time elapsed = " + (System.nanoTime() - startTime)/Math.pow(10, 9) + " s");
Log.d("SERVER", "Total Packets Received = " + Long.toString(TrafficStats.getUidRxPackets(Process.myUid()) - startRxPackets));
Log.d("SERVER", "Packets Received from Socket = " + numPackRecv);*/
}catch (Exception e) {
Log.d("SERVER", "Inside run() ex2");
Log.d("SERVER", Log.getStackTraceString(e));
serverSocket.disconnect();
serverSocket.close();
}
}
}
This is the Client side
public class TestClient extends Activity { private DatagramSocket clientSocket;
byte[] incomingData;
int BUF_SIZE = 500;
int numBytesRead = 0;
int numPackSent = 0;
private static final int SERVERPORT = 6000;
private static final String SERVER_IP = "10.0.0.22";
String inFile = "/sdcard/Movies/asdd.mp4";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_client);
new Thread(new ClientThread()).start();
}
public void onClick(View view) {
new workInProgress().execute("");
}
private class workInProgress extends AsyncTask<Object, Object, Object> {
#SuppressLint("NewApi")
#Override
protected Object doInBackground(Object... params) {
try {
Log.d("CLIENT", "Sending a file to the server...");
BufferedInputStream inputBuf = new BufferedInputStream(new FileInputStream(inFile));
//byte[] fileBytes = new byte[(int) inFile.length()];
byte[] fileBytes = new byte[BUF_SIZE];
incomingData = new byte[BUF_SIZE];
double numPktToSend = Math.ceil(inFile.length()*1.0/BUF_SIZE);
//Log.d("CLIENT", "Total packets to be sent = " + numPktToSend);
int sleepCycle = 1;
long sysPackSent = 0;
//long startTxPackets = TrafficStats.getTotalTxPackets();
long startTxPackets = TrafficStats.getUidTxPackets(Process.myUid());
Log.d("CLIENT", "startTxPacks: " + startTxPackets);
long packDrops = 0;
long startTime = System.nanoTime();
long count=0;
long ackRec=0;
int seqNo = 0;
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(outStream);
while((numBytesRead = inputBuf.read(fileBytes)) != -1) {
//DatagramPacket packet = new DatagramPacket(fileBytes, fileBytes.length);
if (os == null) {
os = new ObjectOutputStream(outStream);
}
Message msg = new Message(++seqNo, fileBytes, false);
os.writeObject(msg);
os.flush();
os.reset();
byte[] data = outStream.toByteArray();
DatagramPacket packet = new DatagramPacket(data, data.length);
clientSocket.send(packet);
numPackSent += 1;
//Log.d("CLIENT", "No of packets sent = " + numPackSent);
sysPackSent = TrafficStats.getUidTxPackets(Process.myUid()) - startTxPackets;
try{
clientSocket.setSoTimeout(5000);
packet = new DatagramPacket(incomingData, incomingData.length);
clientSocket.receive(packet);
String recAck = new String(packet.getData());
ackRec++;
}
catch(Exception e) {
//Log.d("CLIENT", Log.getStackTraceString(e));
}
packDrops = numPackSent - ackRec;
if (packDrops > count) {
sleepCycle = Math.min(16, sleepCycle * 2);
count = packDrops;
Log.d("CLIENT",String.valueOf(sleepCycle) + " :: " + numPackSent);
} else {
sleepCycle = Math.max(sleepCycle - 1, 1);
}
Thread.sleep(sleepCycle);
}
if (numBytesRead == -1) {
fileBytes = "END".getBytes();
Log.d("CLIENT", "Sending END Packet");
clientSocket.send(new DatagramPacket(fileBytes, fileBytes.length));
}
Log.d("CLIENT", "Actual Time elapsed = " + (System.nanoTime() - startTime)/Math.pow(10, 9) + " s");
Log.d("CLIENT", "Total Packets Transmitted = " + Long.toString(sysPackSent));
Log.d("CLIENT", "No of packets dropped = " + String.valueOf(packDrops));
Log.d("CLIENT", "Packets Pushed to Socket = " + numPackSent);
Log.d("CLIENT", "Number of Acknoledgments received " +ackRec);
inputBuf.close();
os.close();
outStream.close();
clientSocket.disconnect();
clientSocket.close();
Log.d("CLIENT", "Sending file.. Complete!!!");
} catch (Exception e) {
Log.d("CLIENT", Log.getStackTraceString(e));
clientSocket.disconnect();
clientSocket.close();
}
return null;
}
}
class ClientThread implements Runnable {
#Override
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
clientSocket = new DatagramSocket();
clientSocket.connect(serverAddr, SERVERPORT);
Log.d("CLIENT", "Connection Successful");
} catch (UnknownHostException e1) {
Log.d("CLIENT", "Inside run() UnknownHostEx");
Log.d("CLIENT", Log.getStackTraceString(e1));
} catch (IOException e1) {
Log.d("CLIENT", "Inside run() IOEx");
Log.d("CLIENT", Log.getStackTraceString(e1));
}
}
}
I am getting a few errors at the Server side:
I am receiving the same sequence number for each packet (i.e. 1)
I am not sure about the buffer size for the incoming packet, as I am using 500 bytes at Client side and 1024 at the Sever. And if I take 500 bytes in both the codes I get a End of File exception.
I would really appreciate if you could suggest better ways to implement the same thing!
Thanks :)
Thanks!
Create a ByteArrayOutputStream.
Wrap it in a DataOutputStream
Use DataOutputStream.writeInt() to write the sequence number.
Use write() to write the data.
Construct the DatagramPacket from the byte array returned by the ByteArrayOutputStream.
At the receiver, do exactly the reverse, using the complementary classes and methods in each case. What those are is left as an exercise for the reader.
The simplest method would probably be to a look at the TCP protocol, and stick all the TCP headers into the start of each of your UDP packets.