Skip to content

Most visited

Recently visited

navigation
PermissionRequest / src / com.example.android.permissionrequest /

SimpleWebServer.java

1
/*
2
 * Copyright (C) 2014 The Android Open Source Project
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
 
17
package com.example.android.permissionrequest;
18
 
19
import android.content.res.AssetManager;
20
import android.text.TextUtils;
21
import android.util.Log;
22
 
23
import java.io.BufferedReader;
24
import java.io.ByteArrayOutputStream;
25
import java.io.FileNotFoundException;
26
import java.io.IOException;
27
import java.io.InputStream;
28
import java.io.InputStreamReader;
29
import java.io.PrintStream;
30
import java.net.ServerSocket;
31
import java.net.Socket;
32
import java.net.SocketException;
33
 
34
/**
35
 * Implementation of a very basic HTTP server. The contents are loaded from the assets folder. This
36
 * server handles one request at a time. It only supports GET method.
37
 */
38
public class SimpleWebServer implements Runnable {
39
 
40
    private static final String TAG = "SimpleWebServer";
41
 
42
    /**
43
     * The port number we listen to
44
     */
45
    private final int mPort;
46
 
47
    /**
48
     * {@link android.content.res.AssetManager} for loading files to serve.
49
     */
50
    private final AssetManager mAssets;
51
 
52
    /**
53
     * True if the server is running.
54
     */
55
    private boolean mIsRunning;
56
 
57
    /**
58
     * The {@link java.net.ServerSocket} that we listen to.
59
     */
60
    private ServerSocket mServerSocket;
61
 
62
    /**
63
     * WebServer constructor.
64
     */
65
    public SimpleWebServer(int port, AssetManager assets) {
66
        mPort = port;
67
        mAssets = assets;
68
    }
69
 
70
    /**
71
     * This method starts the web server listening to the specified port.
72
     */
73
    public void start() {
74
        mIsRunning = true;
75
        new Thread(this).start();
76
    }
77
 
78
    /**
79
     * This method stops the web server
80
     */
81
    public void stop() {
82
        try {
83
            mIsRunning = false;
84
            if (null != mServerSocket) {
85
                mServerSocket.close();
86
                mServerSocket = null;
87
            }
88
        } catch (IOException e) {
89
            Log.e(TAG, "Error closing the server socket.", e);
90
        }
91
    }
92
 
93
    public int getPort() {
94
        return mPort;
95
    }
96
 
97
    @Override
98
    public void run() {
99
        try {
100
            mServerSocket = new ServerSocket(mPort);
101
            while (mIsRunning) {
102
                Socket socket = mServerSocket.accept();
103
                handle(socket);
104
                socket.close();
105
            }
106
        } catch (SocketException e) {
107
            // The server was stopped; ignore.
108
        } catch (IOException e) {
109
            Log.e(TAG, "Web server error.", e);
110
        }
111
    }
112
 
113
    /**
114
     * Respond to a request from a client.
115
     *
116
     * @param socket The client socket.
117
     * @throws IOException
118
     */
119
    private void handle(Socket socket) throws IOException {
120
        BufferedReader reader = null;
121
        PrintStream output = null;
122
        try {
123
            String route = null;
124
 
125
            // Read HTTP headers and parse out the route.
126
            reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
127
            String line;
128
            while (!TextUtils.isEmpty(line = reader.readLine())) {
129
                if (line.startsWith("GET /")) {
130
                    int start = line.indexOf('/') + 1;
131
                    int end = line.indexOf(' ', start);
132
                    route = line.substring(start, end);
133
                    break;
134
                }
135
            }
136
 
137
            // Output stream that we send the response to
138
            output = new PrintStream(socket.getOutputStream());
139
 
140
            // Prepare the content to send.
141
            if (null == route) {
142
                writeServerError(output);
143
                return;
144
            }
145
            byte[] bytes = loadContent(route);
146
            if (null == bytes) {
147
                writeServerError(output);
148
                return;
149
            }
150
 
151
            // Send out the content.
152
            output.println("HTTP/1.0 200 OK");
153
            output.println("Content-Type: " + detectMimeType(route));
154
            output.println("Content-Length: " + bytes.length);
155
            output.println();
156
            output.write(bytes);
157
            output.flush();
158
        } finally {
159
            if (null != output) {
160
                output.close();
161
            }
162
            if (null != reader) {
163
                reader.close();
164
            }
165
        }
166
    }
167
 
168
    /**
169
     * Writes a server error response (HTTP/1.0 500) to the given output stream.
170
     *
171
     * @param output The output stream.
172
     */
173
    private void writeServerError(PrintStream output) {
174
        output.println("HTTP/1.0 500 Internal Server Error");
175
        output.flush();
176
    }
177
 
178
    /**
179
     * Loads all the content of {@code fileName}.
180
     *
181
     * @param fileName The name of the file.
182
     * @return The content of the file.
183
     * @throws IOException
184
     */
185
    private byte[] loadContent(String fileName) throws IOException {
186
        InputStream input = null;
187
        try {
188
            ByteArrayOutputStream output = new ByteArrayOutputStream();
189
            input = mAssets.open(fileName);
190
            byte[] buffer = new byte[1024];
191
            int size;
192
            while (-1 != (size = input.read(buffer))) {
193
                output.write(buffer, 0, size);
194
            }
195
            output.flush();
196
            return output.toByteArray();
197
        } catch (FileNotFoundException e) {
198
            return null;
199
        } finally {
200
            if (null != input) {
201
                input.close();
202
            }
203
        }
204
    }
205
 
206
    /**
207
     * Detects the MIME type from the {@code fileName}.
208
     *
209
     * @param fileName The name of the file.
210
     * @return A MIME type.
211
     */
212
    private String detectMimeType(String fileName) {
213
        if (TextUtils.isEmpty(fileName)) {
214
            return null;
215
        } else if (fileName.endsWith(".html")) {
216
            return "text/html";
217
        } else if (fileName.endsWith(".js")) {
218
            return "application/javascript";
219
        } else if (fileName.endsWith(".css")) {
220
            return "text/css";
221
        } else {
222
            return "application/octet-stream";
223
        }
224
    }
225
 
226
}
This site uses cookies to store your preferences for site-specific language and display options.

Hooray!