You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android基于NanoHTTPD搭建本地Web服务器遇问题,求可用示例

在Android上搭建可访问本地index.html的Web服务器(完整可运行示例)

我懂你折腾了好几种方法都跑不起来的挫败感——Android环境下的Web服务器确实和普通Java项目不一样,比如不能在主线程启动、文件访问权限、网络配置这些坑都容易踩。下面给你一个基于NanoHTTPD的完整可运行方案,亲测能正常启动并加载本地assets里的index.html:


步骤1:添加依赖

在你的Module级别的build.gradle文件里,添加NanoHTTPD的依赖:

dependencies {
    // 其他依赖...
    implementation 'org.nanohttpd:nanohttpd:2.3.1'
}

步骤2:配置权限和网络

在AndroidManifest.xml里添加必要的权限,同时允许明文HTTP请求(Android 9+默认禁止):

<uses-permission android:name="android.permission.INTERNET" />

<application
    // 其他属性...
    android:usesCleartextTraffic="true">
    // Activity声明...
</application>

步骤3:编写Web服务器类

创建一个继承自NanoHTTPD的类,负责处理请求并从assets读取静态文件:

import android.content.Context;
import org.nanohttpd.NanoHTTPD;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

public class LocalWebServer extends NanoHTTPD {

    private Context mContext;

    public LocalWebServer(Context context, int port) throws IOException {
        super(port);
        this.mContext = context;
    }

    @Override
    public Response serve(IHTTPSession session) {
        // 默认访问根路径时返回index.html
        String requestUri = session.getUri();
        if (requestUri.equals("/")) {
            requestUri = "/index.html";
        }

        try {
            // 从assets文件夹读取目标文件
            InputStream inputStream = mContext.getAssets().open(requestUri.substring(1));
            byte[] fileBytes = new byte[inputStream.available()];
            inputStream.read(fileBytes);
            inputStream.close();
            String fileContent = new String(fileBytes, StandardCharsets.UTF_8);

            // 根据文件后缀设置正确的Content-Type
            String mimeType = getMimeType(requestUri);
            return newFixedLengthResponse(Response.Status.OK, mimeType, fileContent);
        } catch (IOException e) {
            // 文件不存在时返回404
            return newFixedLengthResponse(Response.Status.NOT_FOUND, "text/plain", "404 页面未找到");
        }
    }

    // 简单的MIME类型映射,可根据需要扩展
    private String getMimeType(String uri) {
        if (uri.endsWith(".html") || uri.endsWith(".htm")) {
            return "text/html";
        } else if (uri.endsWith(".css")) {
            return "text/css";
        } else if (uri.endsWith(".js")) {
            return "application/javascript";
        } else if (uri.endsWith(".png")) {
            return "image/png";
        } else if (uri.endsWith(".jpg") || uri.endsWith(".jpeg")) {
            return "image/jpeg";
        }
        return "text/plain";
    }
}

步骤4:在Activity中启动服务器

注意不能在Android主线程启动服务器,所以要放在子线程里执行:

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private LocalWebServer webServer;

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

        // 启动服务器的操作放在子线程
        new Thread(() -> {
            try {
                // 监听8080端口
                webServer = new LocalWebServer(MainActivity.this, 8080);
                webServer.start();
                // 回到主线程显示提示
                runOnUiThread(() -> 
                    Toast.makeText(MainActivity.this, "服务器启动成功!访问地址:http://localhost:8080", Toast.LENGTH_LONG).show()
                );
            } catch (IOException e) {
                e.printStackTrace();
                runOnUiThread(() -> 
                    Toast.makeText(MainActivity.this, "服务器启动失败:" + e.getMessage(), Toast.LENGTH_LONG).show()
                );
            }
        }).start();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 页面销毁时停止服务器
        if (webServer != null) {
            webServer.stop();
        }
    }
}

步骤5:放置你的index.html

在项目的app/src/main/assets目录下(如果没有assets文件夹,手动创建一个),放入你的index.html文件,示例内容:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Android本地服务器测试</title>
</head>
<body>
    <h1 style="color: #2196F3;">🎉 成功访问本地页面!</h1>
    <p>这是从Android assets文件夹加载的静态HTML文件</p>
</body>
</html>

测试方法

  • 模拟器:直接在浏览器输入 http://localhost:8080 即可访问
  • 真机:先查看手机的局域网IP(比如192.168.1.100),然后在同一网络的设备浏览器输入 http://192.168.1.100:8080

内容的提问来源于stack exchange,提问作者huby

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:58:00