I posted "Java Datagram/UDP Server and Client, run on raspberry Pi" on my another blogspot. And last post show "Android Datagram/UDP Client example". This post show a Datagram/UDP Server run on Android.
MainActivity.java
package com.blogspot.android_er.androidudpserver;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.TextView;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Date;
import java.util.Enumeration;
public class MainActivity extends AppCompatActivity {
private final static String TAG = MainActivity.class.getSimpleName();
TextView infoIp, infoPort;
TextView textViewState, textViewPrompt;
static final int UdpServerPORT = 4445;
UdpServerThread udpServerThread;
@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);
textViewState = (TextView)findViewById(R.id.state);
textViewPrompt = (TextView)findViewById(R.id.prompt);
infoIp.setText(getIpAddress());
infoPort.setText(String.valueOf(UdpServerPORT));
}
@Override
protected void onStart() {
udpServerThread = new UdpServerThread(UdpServerPORT);
udpServerThread.start();
super.onStart();
}
@Override
protected void onStop() {
if(udpServerThread != null){
udpServerThread.setRunning(false);
udpServerThread = null;
}
super.onStop();
}
private void updateState(final String state){
runOnUiThread(new Runnable() {
@Override
public void run() {
textViewState.setText(state);
}
});
}
private void updatePrompt(final String prompt){
runOnUiThread(new Runnable() {
@Override
public void run() {
textViewPrompt.append(prompt);
}
});
}
private class UdpServerThread extends Thread{
int serverPort;
DatagramSocket socket;
boolean running;
public UdpServerThread(int serverPort) {
super();
this.serverPort = serverPort;
}
public void setRunning(boolean running){
this.running = running;
}
@Override
public void run() {
running = true;
try {
updateState("Starting UDP Server");
socket = new DatagramSocket(serverPort);
updateState("UDP Server is running");
Log.e(TAG, "UDP Server is running");
while(running){
byte[] buf = new byte[256];
// receive request
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet); //this code block the program flow
// send the response to the client at "address" and "port"
InetAddress address = packet.getAddress();
int port = packet.getPort();
updatePrompt("Request from: " + address + ":" + port + "\n");
String dString = new Date().toString() + "\n"
+ "Your address " + address.toString() + ":" + String.valueOf(port);
buf = dString.getBytes();
packet = new DatagramPacket(buf, buf.length, address, port);
socket.send(packet);
}
Log.e(TAG, "UDP Server ended");
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(socket != null){
socket.close();
Log.e(TAG, "socket.close()");
}
}
}
}
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;
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:orientation="vertical"
tools:context="com.blogspot.android_er.androidudpserver.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />
<TextView
android:id="@+id/infoip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="italic" />
<TextView
android:id="@+id/infoport"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="italic" />
<TextView
android:id="@+id/state"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="un-initiated"
android:textSize="20dp"/>
<TextView
android:id="@+id/prompt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18dp"/>
</LinearLayout>
uses-permission of "android.permission.INTERNET" is needed in AndroidManifest.xml
Remark about life-cycle:
In this example, the DatagramSocket server is run in background thread. I haven't handle the life-cycle very well (Actually I don't think any application will have UI like this example). Consider the cases:
Case One:
- Start the app, the activity display on screen and the DatagramSocket opened in associated thread.
- the code socket.receive(packet) block the program flow, so the thread stay here and waiting data request.
- Exit the app. It will set running to false, to request the thread to stop. But the thread is blocked in socket.receive(packet), so it's still running.
- Restart the app, the new thread cannot open the DatagramSocket, because it's still held by old thread.
- Client send a request, the DatagramSocket server response the request and exit socket.receive(packet), and check running and exit.
- In this case, the current activity and associated thread have no DatagramSocket opened!
Case Two:
- Start the app, the activity display on screen and the DatagramSocket opened in associated thread.
- the code socket.receive(packet) block the program flow, so the thread stay here and waiting data request.
- Exit the app. It will set running to false, to request the thread to stop. But the thread is blocked in socket.receive(packet), so it's still running.
- Client send a request, the DatagramSocket server response the request and exit socket.receive(packet), and check running and exit.
- Restart the app, and open the DatagramSocket.
- In this case, the current activity and associated thread can open DatagramSocket and work as expected.
Download the files .
Hi man, I appreciate your job, you are doing it really good. I want to ask that I create a socketserver on app and listening to port 8080,and I set system proxy as localhost:8080 so browsers are sending requests to app. I wonder how can I connect to requested url with request headers and send data to browser. Thanks for your business.
ReplyDeleteHi;
ReplyDeleteIm curious about adding time when sending msg from client and the time when the server receive it, to find the transmission time in millisecond or in microsecond?
HI
ReplyDeletehow can put code to find the transmission time in milliseconds or microseconed?
thanks
Is there any limit on sending or receiving? I'm working sending and receiving lots of data, not concurrently, and my application is closing alone.
ReplyDeleteTutorial is great, but it doesnot work on celluar internet connection.
ReplyDeleteyou may have tested when you where on WIFI.
do you have any Tutorial on how to use celluar internet connection?