Generally speaking, when Android applications request data, they send requests to remote servers in the form of Get or Post. Have you ever thought that in fact, we can also build a small Web server on Android devices, and achieve conventional functions such as downloading pictures, downloading files and submitting forms? The following is how to set up a Web server on an Android device. The functions of the Web server are as follows:

  1. Accept client file upload and download
  2. A dynamic Http API that writes interfaces like Java servlets
  3. Deploy static web sites, such as pure Html, support JS, CSS, Image separation
  4. Deploying a dynamic Website

This relies on an open source library: AndServer

Similar to Apache and Tomcat, AndServer allows devices on the same LAN to request data from the Web server in the normal network request mode, as long as the IP address and port number of the Web server are specified

So, what is the purpose of this Web server?

Name one need I’m meeting right now! Two devices (Android or ios) need to communicate with each other without a network. The original plan is to connect the communication channel between devices through Wifi, that is, one device is connected to the Wiif hotspot of another device, so that a “channel” is established between them, and then the input and output streams are obtained through Socket connection, and data is exchanged through the input and output streams. However, it is necessary to deal with the problem of data synchronization and parsing under the condition of high concurrency, which is more troublesome. AndServer can directly apply the existing network request framework of the project to communicate data directly in the way of network request, and the server side is also better to deal with the concurrency problem

Gradle remote dependencies

implementation 'com. Yanzhenjie: andserver: 1.1.3'
Copy the code

Setting up the server

The setup of the server is simple and supports chain calls. Specify that the server listens on the IP address of the local machine, and specify the port number as 1995, and open three interfaces respectively for downloading files, downloading pictures, and Post forms

       AndServer server = AndServer.serverBuilder()
                .inetAddress(NetUtils.getLocalIPAddress())  // The network address that the server listens to
                .port(Constants.PORT_SERVER) // The port on which the server listens
                .timeout(10, TimeUnit.SECONDS) // Indicates the timeout period of the Socket
                .registerHandler(Constants.GET_FILE, new DownloadFileHandler()) // Register a file download interface
                .registerHandler(Constants.GET_IMAGE, new DownloadImageHandler()) // Register an image download interface
                .registerHandler(Constants.POST_JSON, new JsonHandler()) // Register a Post Json interface
                .filter(new HttpCacheFilter()) // Enable cache support
                .listener(new Server.ServerListener() {  // The server listens to the interface
                    @Override
                    public void onStarted(a) {
                        String hostAddress = server.getInetAddress().getHostAddress();
                        Log.e(TAG, "onStarted : " + hostAddress);
                        ServerPresenter.onServerStarted(ServerService.this, hostAddress);
                    }

                    @Override
                    public void onStopped(a) {
                        Log.e(TAG, "onStopped");
                        ServerPresenter.onServerStopped(ServerService.this);
                    }

                    @Override
                    public void onError(Exception e) {
                        Log.e(TAG, "onError : " + e.getMessage());
                        ServerPresenter.onServerError(ServerService.this, e.getMessage());
                    }
                })
                .build();
Copy the code

Start the server

server.startup(a);Copy the code

Stopping the server

server.shutdown(a);Copy the code

Interface processor

When registering an interface, you need to specify the corresponding processor in addition to the Url address. The three open interfaces correspond to the three addresses

public class Constants {

    // The port number of the server interface
    public static final int PORT_SERVER = 1995;

    public static final String GET_FILE = "/file";

    public static final String GET_IMAGE = "/image";

    public static final String POST_JSON = "/json";

}
Copy the code
· · ·. RegisterHandler (the GET_FILE,new DownloadFileHandler()) // Register a file download interface
 .registerHandler(Constants.GET_IMAGE, new DownloadImageHandler()) // Register an image download interface
 .registerHandler(Constants.POST_JSON, new JsonHandler()) // Register a Post Json interface...Copy the code

For example, assume that the IP address of the equipment is: 192.168.0.101, then visit http://192.168.0.101:1995/file in the interface, the request will be handled by DownloadFileHandler operation

The download file

The DownloadFileHandler implements the RequestHandler interface. In the Handle method, the request header and form data can be retrieved. The Get method is supported by the annotation declaration, which directly returns a text file for download

/** * Author: leavesC * Time: 2018/4/5 16:30 * Description: https://github.com/leavesC/AndroidServer * https://www.jianshu.com/u/9df45b87cfdf */
public class DownloadFileHandler implements RequestHandler {

    @RequestMapping(method = {RequestMethod.GET})
    @Override
    public void handle(HttpRequest httpRequest, HttpResponse httpResponse, HttpContext httpContext) throws HttpException, IOException {
        File file = createFile();
        HttpEntity httpEntity = new FileEntity(file, ContentType.create(getMimeType(file.getAbsolutePath()), Charset.defaultCharset()));
        httpResponse.setHeader("Content-Disposition"."attachment; filename=File.txt");
        httpResponse.setStatusCode(200);
        httpResponse.setEntity(httpEntity);
    }

    private File createFile(a) {
        File file = null;
        OutputStream outputStream = null;
        try {
            file = File.createTempFile("File".".txt", MainApplication.get().getCacheDir());
            outputStream = new FileOutputStream(file);
            outputStream.write("LeavesC, this is a test text.".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(outputStream ! =null) {
                try {
                    outputStream.flush();
                    outputStream.close();
                } catch(IOException e) { e.printStackTrace(); }}}returnfile; }}Copy the code

The interface is accessed directly in a browser (running on the same LAN as the Android Web server) and can be downloaded directly to a file


Download the pictures

Similarly, DownloadImageHandler, the interface handler that downloads images, can be designed to return the application icon in the Handle method

/** * Author: leavesC * Time: 2018/4/5 16:30 * Description: https://github.com/leavesC/AndroidServer * https://www.jianshu.com/u/9df45b87cfdf */
public class DownloadImageHandler extends SimpleRequestHandler {

    private File file = new File(Environment.getExternalStorageDirectory(), "leavesC.jpg");

    @RequestMapping(method = {RequestMethod.GET})
    @Override
    protected View handle(HttpRequest request) throws HttpException, IOException {
        writeToSdCard();
        HttpEntity httpEntity = new FileEntity(file, ContentType.create(getMimeType(file.getAbsolutePath()), Charset.defaultCharset()));
        return new View(200, httpEntity);
    }

    private void writeToSdCard(a) throws IOException {
        if(! file.exists()) {synchronized (DownloadImageHandler.class) {
                if(! file.exists()) {boolean b = file.createNewFile();
                    if(! b) {throw new IOException("What broken cell phone.");
                    }
                    Bitmap bitmap = BitmapFactory.decodeResource(MainApplication.get().getResources(), R.mipmap.ic_launcher_round);
                    OutputStream outputStream = null;
                    try {
                        outputStream = new FileOutputStream(file);
                        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    } finally {
                        if(outputStream ! =null) {
                            outputStream.flush();
                            outputStream.close();
                        }
                    }
                }
            }
        }
    }

}
Copy the code

Post form

Here need to change the annotation values to RequestMethod. POST, through HttpRequestParser. GetContentFromBody (httpRequest) functions can obtain the form data, directly to detect whether the form data to a Json string here, If yes, add an attribute: “state” as the return value, otherwise return a Json string containing only the attribute “state”

/** * Author: leavesC * Time: 2018/4/5 16:30 * Description: https://github.com/leavesC/AndroidServer * https://www.jianshu.com/u/9df45b87cfdf */
public class JsonHandler implements RequestHandler {
    
    @RequestMapping(method = {RequestMethod.POST})
    @Override
    public void handle(HttpRequest httpRequest, HttpResponse httpResponse, HttpContext httpContext) throws HttpException, IOException {
        String content = HttpRequestParser.getContentFromBody(httpRequest);
        JSONObject jsonObject = null;
        try {
            jsonObject = new JSONObject(content);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        if (jsonObject == null) {
            jsonObject = new JSONObject();
        }
        try {
            jsonObject.put("state"."success");
        } catch (JSONException e) {
            e.printStackTrace();
        }
        StringEntity stringEntity = new StringEntity(jsonObject.toString(), "utf-8");
        httpResponse.setStatusCode(200); httpResponse.setEntity(stringEntity); }}Copy the code

This is the Post operation on the Postman tool


The above three examples are all called on the computer side, which has the same effect as calling on the mobile side

The basic operation is introduced here, and then the specific content can see the example code: AndroidServer



+ QQ group 457848807:. Get the above high definition technical mind map and free video learning materials on related technologies