Showing posts with label Web Server. Show all posts
Showing posts with label Web Server. Show all posts

Wednesday, November 25, 2015

Simple HTTP server running on Android

It's my old exercise "Implement simple HTTP server running on Android". Somebody report it's not work, so I re-try it on Android Studio. Actually the code is same as before, and work as expected. Please notice both the server and client have to connect in the same WiFi network.


Updated@2015-11-26:
This code NOT work on Android 5, may be all 5+ version.
Fixed, refer next post "socket.getInetAddress() return null on Android 5".


Work on Xiaomi Redmi 2, running Android 4.4.4


MainActivity.java
package com.blogspot.android_er.androidhttpserver;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.EditText;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Enumeration;

public class MainActivity extends AppCompatActivity {

    EditText welcomeMsg;
    TextView infoIp;
    TextView infoMsg;
    String msgLog = "";

    ServerSocket httpServerSocket;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        welcomeMsg = (EditText) findViewById(R.id.welcomemsg);
        infoIp = (TextView) findViewById(R.id.infoip);
        infoMsg = (TextView) findViewById(R.id.msg);

        infoIp.setText(getIpAddress() + ":"
                + HttpServerThread.HttpServerPORT + "\n");

        HttpServerThread httpServerThread = new HttpServerThread();
        httpServerThread.start();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (httpServerSocket != null) {
            try {
                httpServerSocket.close();
            } catch (IOException e) {
                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;
    }

    private class HttpServerThread extends Thread {

        static final int HttpServerPORT = 8888;

        @Override
        public void run() {
            Socket socket = null;

            try {
                httpServerSocket = new ServerSocket(HttpServerPORT);

                while(true){
                    socket = httpServerSocket.accept();

                    HttpResponseThread httpResponseThread =
                            new HttpResponseThread(
                                    socket,
                                    welcomeMsg.getText().toString());
                    httpResponseThread.start();
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }

    private class HttpResponseThread extends Thread {

        Socket socket;
        String h1;

        HttpResponseThread(Socket socket, String msg){
            this.socket = socket;
            h1 = msg;
        }

        @Override
        public void run() {
            BufferedReader is;
            PrintWriter os;
            String request;

            try {
                is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                request = is.readLine();

                os = new PrintWriter(socket.getOutputStream(), true);

                String response =
                        "<html><head></head>" +
                                "<body>" +
                                "<h1>" + h1 + "</h1>" +
                                "</body></html>";

                os.print("HTTP/1.0 200" + "\r\n");
                os.print("Content type: text/html" + "\r\n");
                os.print("Content length: " + response.length() + "\r\n");
                os.print("\r\n");
                os.print(response + "\r\n");
                os.flush();
                socket.close();
                
                msgLog += "Request of " + request
                        + " from " + socket.getInetAddress().toString() + "\n";
                MainActivity.this.runOnUiThread(new Runnable() {

                    @Override
                    public void run() {

                        infoMsg.setText(msgLog);
                    }
                });

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            return;
        }
    }
}


layout/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.androidhttpserver.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" />

    <EditText
        android:id="@+id/welcomemsg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Welcome from Android-er" />

    <TextView
        android:id="@+id/infoip"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <TextView
            android:id="@+id/msg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </ScrollView>
</LinearLayout>


Permission of "android.permission.INTERNET" is needed in AndroidManifest.xml.

download filesDownload the files (Android Studio Format) .

Saturday, January 31, 2015

Simple web server provide image download, using org.apache.http.protocol.HttpService

Last post show a "Simple web server using org.apache.http.protocol.HttpService". In this post, I tried to provide image download, by visiting http://<ip address>:8080/image

But FAIL - As shown in the video, sometimes the download will fail. And once fail, the code will block and have to be re-start. Hope anybody can advise.


Modify MainActivity.java
package com.example.androidhttpservice;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Enumeration;

import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.entity.ContentProducer;
import org.apache.http.entity.EntityTemplate;
import org.apache.http.entity.FileEntity;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.DefaultHttpResponseFactory;
import org.apache.http.impl.DefaultHttpServerConnection;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.BasicHttpProcessor;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestHandler;
import org.apache.http.protocol.HttpRequestHandlerRegistry;
import org.apache.http.protocol.HttpService;
import org.apache.http.protocol.ResponseConnControl;
import org.apache.http.protocol.ResponseContent;
import org.apache.http.protocol.ResponseDate;
import org.apache.http.protocol.ResponseServer;

import android.support.v7.app.ActionBarActivity;
import android.widget.TextView;
import android.os.Bundle;
import android.os.Environment;

/*
 * Permission needed:
 * "android.permission.INTERNET"
 * "android.permission.READ_EXTERNAL_STORAGE"
 */

public class MainActivity extends ActionBarActivity {

 HttpServiceThread httpServiceThread;
 
 TextView infoIp;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  infoIp = (TextView) findViewById(R.id.infoip);
  infoIp.setText(getIpAddress() + ":" 
    + HttpServiceThread.HttpServerPORT + "\n");

  httpServiceThread = new HttpServiceThread();
  httpServiceThread.start();
 }

 @Override
 protected void onDestroy() {
  super.onDestroy();
  httpServiceThread.stopServer();
 }

 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;
 }

 private class HttpServiceThread extends Thread {

  ServerSocket serverSocket;
  Socket socket;
  HttpService httpService;
  BasicHttpContext basicHttpContext;
  static final int HttpServerPORT = 8080;
  boolean RUNNING = false;

  HttpServiceThread() {
   RUNNING = true;
   startHttpService();
  }

  @Override
  public void run() {

   try {
    serverSocket = new ServerSocket(HttpServerPORT);
    serverSocket.setReuseAddress(true);

    while (RUNNING) {
     socket = serverSocket.accept();
     
     DefaultHttpServerConnection httpServerConnection = new DefaultHttpServerConnection();
     httpServerConnection.bind(socket, new BasicHttpParams());
     httpService.handleRequest(httpServerConnection,
       basicHttpContext);
     httpServerConnection.shutdown();
    }
    serverSocket.close();
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   } catch (HttpException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }

  private synchronized void startHttpService() {
   BasicHttpProcessor basicHttpProcessor = new BasicHttpProcessor();
   basicHttpContext = new BasicHttpContext();

   basicHttpProcessor.addInterceptor(new ResponseDate());
   basicHttpProcessor.addInterceptor(new ResponseServer());
   basicHttpProcessor.addInterceptor(new ResponseContent());
   basicHttpProcessor.addInterceptor(new ResponseConnControl());

   httpService = new HttpService(basicHttpProcessor,
     new DefaultConnectionReuseStrategy(),
     new DefaultHttpResponseFactory());

   HttpRequestHandlerRegistry registry = new HttpRequestHandlerRegistry();
   registry.register("/", new HomeCommandHandler());
   registry.register("/image", new ImageCommandHandler());
   httpService.setHandlerResolver(registry);
  }

  public synchronized void stopServer() {
   RUNNING = false;
   if (serverSocket != null) {
    try {
     serverSocket.close();
    } catch (IOException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
  }

  class HomeCommandHandler implements HttpRequestHandler {

   @Override
   public void handle(HttpRequest request, HttpResponse response,
     HttpContext httpContext) throws HttpException, IOException {

    HttpEntity httpEntity = new EntityTemplate(
      new ContentProducer() {

       public void writeTo(final OutputStream outstream)
         throws IOException {

        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(
          outstream, "UTF-8");
        String response = "<html><head></head><body><h1>Hello HttpService, from Android-er<h1></body></html>";

        outputStreamWriter.write(response);
        outputStreamWriter.flush();
       }
      });
    response.setHeader("Content-Type", "text/html");
    response.setEntity(httpEntity);
   }

  }
  
  class ImageCommandHandler implements HttpRequestHandler {

   @Override
   public void handle(HttpRequest request, HttpResponse response,
     HttpContext context) throws HttpException, IOException {

    File file = new File(
      Environment.getExternalStorageDirectory(), 
      "android-er_sketch.jpg");

                FileEntity fileEntity = new FileEntity(file, "image/jpg");
                response.setHeader("Content-Type", "application/force-download");
                response.setHeader("Content-Disposition","attachment; filename=image.jpg");
    response.setHeader("Content-Type", "image/jpg");
    response.setEntity(fileEntity);
   }
   
  }

 }

}

Layout file, activity_main.xml, refer to last post.

Permission of "android.permission.INTERNET" and "android.permission.READ_EXTERNAL_STORAGE" is needed in AndroidManifest.xml.

download filesDownload the files.

Friday, January 30, 2015

Simple web server using org.apache.http.protocol.HttpService

It is a example of simple web server, using org.apache.http.protocol.HttpService. org.apache.http.protocol.HttpServiceis a server side HTTP protocol handler based on the classic (blocking) I/O model.


MainActivity.java
package com.example.androidhttpservice;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Enumeration;

import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.entity.ContentProducer;
import org.apache.http.entity.EntityTemplate;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.DefaultHttpResponseFactory;
import org.apache.http.impl.DefaultHttpServerConnection;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.BasicHttpProcessor;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestHandler;
import org.apache.http.protocol.HttpRequestHandlerRegistry;
import org.apache.http.protocol.HttpService;
import org.apache.http.protocol.ResponseConnControl;
import org.apache.http.protocol.ResponseContent;
import org.apache.http.protocol.ResponseDate;
import org.apache.http.protocol.ResponseServer;

import android.support.v7.app.ActionBarActivity;
import android.widget.TextView;
import android.os.Bundle;

/*
 * Permission needed:
 * "android.permission.INTERNET"
 */

public class MainActivity extends ActionBarActivity {

 HttpServiceThread httpServiceThread;
 
 TextView infoIp;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  infoIp = (TextView) findViewById(R.id.infoip);
  infoIp.setText(getIpAddress() + ":" 
    + HttpServiceThread.HttpServerPORT + "\n");

  httpServiceThread = new HttpServiceThread();
  httpServiceThread.start();
 }

 @Override
 protected void onDestroy() {
  super.onDestroy();
  httpServiceThread.stopServer();
 }

 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;
 }

 private class HttpServiceThread extends Thread {

  ServerSocket serverSocket;
  Socket socket;
  HttpService httpService;
  BasicHttpContext basicHttpContext;
  static final int HttpServerPORT = 8080;
  boolean RUNNING = false;

  HttpServiceThread() {
   RUNNING = true;
   startHttpService();
  }

  @Override
  public void run() {

   try {
    serverSocket = new ServerSocket(HttpServerPORT);
    serverSocket.setReuseAddress(true);

    while (RUNNING) {
     socket = serverSocket.accept();
     DefaultHttpServerConnection httpServerConnection = new DefaultHttpServerConnection();
     httpServerConnection.bind(socket, new BasicHttpParams());
     httpService.handleRequest(httpServerConnection,
       basicHttpContext);
     httpServerConnection.shutdown();
    }
    serverSocket.close();
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   } catch (HttpException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }

  private synchronized void startHttpService() {
   BasicHttpProcessor basicHttpProcessor = new BasicHttpProcessor();
   basicHttpContext = new BasicHttpContext();

   basicHttpProcessor.addInterceptor(new ResponseDate());
   basicHttpProcessor.addInterceptor(new ResponseServer());
   basicHttpProcessor.addInterceptor(new ResponseContent());
   basicHttpProcessor.addInterceptor(new ResponseConnControl());

   httpService = new HttpService(basicHttpProcessor,
     new DefaultConnectionReuseStrategy(),
     new DefaultHttpResponseFactory());

   HttpRequestHandlerRegistry registry = new HttpRequestHandlerRegistry();
   registry.register("/", new HomeCommandHandler());
   httpService.setHandlerResolver(registry);
  }

  public synchronized void stopServer() {
   RUNNING = false;
   if (serverSocket != null) {
    try {
     serverSocket.close();
    } catch (IOException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
  }

  class HomeCommandHandler implements HttpRequestHandler {

   @Override
   public void handle(HttpRequest request, HttpResponse response,
     HttpContext httpContext) throws HttpException, IOException {

    HttpEntity httpEntity = new EntityTemplate(
      new ContentProducer() {

       public void writeTo(final OutputStream outstream)
         throws IOException {

        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(
          outstream, "UTF-8");
        String response = "<html><head></head><body><h1>Hello HttpService, from Android-er<h1></body></html>";

        outputStreamWriter.write(response);
        outputStreamWriter.flush();
       }
      });
    response.setHeader("Content-Type", "text/html");
    response.setEntity(httpEntity);
   }

  }

 }

}

activity_main.xml
<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:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.androidhttpservice.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" />

</LinearLayout>

download filesDownload the files.

Saturday, August 16, 2014

Implement simple HTTP server running on Android

Example to implement simple HTTP server on Android:


MainActivity.java
package com.example.androidhttpserver;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Enumeration;

import android.support.v7.app.ActionBarActivity;
import android.widget.EditText;
import android.widget.TextView;
import android.os.Bundle;

public class MainActivity extends ActionBarActivity {

 EditText welcomeMsg;
 TextView infoIp;
 TextView infoMsg;
 String msgLog = "";
 
 ServerSocket httpServerSocket;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  welcomeMsg = (EditText) findViewById(R.id.welcomemsg);
  infoIp = (TextView) findViewById(R.id.infoip);
  infoMsg = (TextView) findViewById(R.id.msg);

  infoIp.setText(getIpAddress() + ":" 
   + HttpServerThread.HttpServerPORT + "\n");

  HttpServerThread httpServerThread = new HttpServerThread();
  httpServerThread.start();
 }
 
 @Override
 protected void onDestroy() {
  super.onDestroy();

  if (httpServerSocket != null) {
   try {
    httpServerSocket.close();
   } catch (IOException e) {
    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;
 }
 
 private class HttpServerThread extends Thread {
  
  static final int HttpServerPORT = 8888;

  @Override
  public void run() {
   Socket socket = null;
   
   try {
    httpServerSocket = new ServerSocket(HttpServerPORT);
    
    while(true){
     socket = httpServerSocket.accept();

     HttpResponseThread httpResponseThread = 
      new HttpResponseThread(
       socket, 
       welcomeMsg.getText().toString());
     httpResponseThread.start();
    }
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }

  }

  
 }
 
 private class HttpResponseThread extends Thread {
  
  Socket socket;
  String h1;
  
  HttpResponseThread(Socket socket, String msg){
   this.socket = socket;
   h1 = msg;
  }

  @Override
  public void run() {
   BufferedReader is;
   PrintWriter os;
   String request;
   
   
   try {
    is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    request = is.readLine();
    
    os = new PrintWriter(socket.getOutputStream(), true);
    
    String response = 
     "<html><head></head>" +
     "<body>" +
     "<h1>" + h1 + "</h1>" +
     "</body></html>";
    
    os.print("HTTP/1.0 200" + "\r\n");
    os.print("Content type: text/html" + "\r\n");
    os.print("Content length: " + response.length() + "\r\n");
    os.print("\r\n");
    os.print(response + "\r\n");
    os.flush();
    socket.close();
    
    
    msgLog += "Request of " + request 
      + " from " + socket.getInetAddress().toString() + "\n";
    MainActivity.this.runOnUiThread(new Runnable() {

     @Override
     public void run() {
      
      infoMsg.setText(msgLog);
     }
    });
    
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
   
   return;
  }
 }

}

<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:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".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" />
    
    <EditText
        android:id="@+id/welcomemsg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Welcome from Android-er" />

    <TextView
        android:id="@+id/infoip"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <TextView
            android:id="@+id/msg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </ScrollView>

</LinearLayout>

download filesDownload the files.

Related:
Simple web server using org.apache.http.protocol.HttpService

Updated@2015-11-25:
Permission of "android.permission.INTERNET" is needed in AndroidManifest.xml.

Updated@2015-11-26:
This code NOT work on Android 5, may be all 5+ version.
Fixed, refer post "socket.getInetAddress() return null on Android 5".