【NanoHTTPD】Android,使用NanoHTTPD搭建服务器,接受Http请求,最佳实践

Android,NanoHTTPD搭建服务器,接受Http请求最佳实践

1,了解

安卓app,作为服务器,接受Http,get post 请求推送数据,NanoHTTPD是一个免费、轻量级的(只有一个Java文件) HTTP服务器,可以很好地嵌入到Java程序中。支持 GET, POST, PUT, HEAD 和 DELETE 请求,支持文件上传,占用内存很小。

开源地址:GitHub - NanoHttpd/nanohttpd: Tiny, easily embeddable HTTP server in Java.

2,引入依赖

implementation 'org.nanohttpd:nanohttpd:2.3.1'

3,开始集成

这里需要注意以下三点问题:

  • 系统端口:0~1023,用于运行标准服务,例如 HTTP 服务(端口 80)、FTP 服务(端口 21)等。
    注册端口:1024~49151,用于运行注册的应用程序或服务,例如 DNS 服务(端口 53)、SMTP 服务(端口 25)等。
    动态/私有端口:49152~65535,可以被动态分配给任何应用程序或服务,通常用于客户端。 所以,如下代码,我们声明监听的端口是 49152 ,避免端口被占用
  • 请求携带中文,需要将请求头设置 UTF-8 字符集,防止中文乱码,如下代码27行进行相关处理;
  • 客户端发送POST请求,获取 POSTBody参数,需要 session.parseBody(new HashMap<String,String>()),如下代码40行处理,获取Body参数。

3.1 自定义类,继承 NanoHTTPD

public class MyNanoHttpdServer extends NanoHTTPD  {
	
    //声明服务端 端口
    private static final Integer HTTP_PORT = 49152;

    public MyNanoHttpdServer(String hostname, int port) {
        super(hostname, port);
    }

    private volatile static MyNanoHttpdServer myNanoHttpdServer;

 	//TODO	单例模式,获取实例对象,并传入当前机器IP
    public static MyNanoHttpdServer getInstance(String ipAddress) {
        if (myNanoHttpdServer == null) {
            synchronized (MyNanoHttpdServer.class) {
                if (myNanoHttpdServer == null) {
                    myNanoHttpdServer = new MyNanoHttpdServer(ipAddress, HTTP_PORT);
                }
            }
        }
        return myNanoHttpdServer;
    }

    @Override
    public Response serve(IHTTPSession session) {
        //TODO  解决客户端请求参数携带中文,出现中文乱码问题
        ContentType ct = new ContentType(session.getHeaders().get("content-type")).tryUTF8();
        session.getHeaders().put("content-type", ct.getContentTypeHeader());
        return dealWith(session);
    }

    private Response dealWith(IHTTPSession  session) {
        Date dateTime = new Date();
        if (Method.POST == session.getMethod()) {
            //获取请求头数据
            Map<String,String> header = session.getHeaders();
            //获取传参参数
            Map<String, String> params = new HashMap<String, String>();
            try {
                session.parseBody(params);
                String paramStr = params.get("postData");
                if(StringUtils.isEmpty(paramStr)){
                    return newFixedLengthResponse("success");
                }
                paramStr = paramStr.replace("\r\n"," ");

                JSONObject jsonParam = JSON.parseObject(paramStr);
                Map<String,Object> result = new HashMap<>();
				//TODO 写你的业务逻辑.....
                
                 //响应客户端
                 return   newFixedLengthResponse("success");
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ResponseException e) {
                e.printStackTrace();
            }
            return   newFixedLengthResponse("success");
        }else if (Method.GET == session.getMethod()){

            Map<String, List<String>> parameters = session.getParameters();
            return   newFixedLengthResponse("success");
        }

        return newFixedLengthResponse("404");
    }

    public static Response newFixedLengthResponse(String msg) {
        return newFixedLengthResponse(Response.Status.OK, NanoHTTPD.MIME_HTML, msg);
    }

}

3.2 在 AndroidMainifest.xml,开启网络权限,注册服务,后台运行

<!--开启网络权限-->
<uses-permission android:name="android.permission.INTERNET" />
<application>
     <!--注册服务>
     <service android:name=".nanoHttpd.MyNanoHttpService" />
</application>

自定义服务类,继承 Service

public class MyNanoHttpService extends Service {

    private MyNanoHttpdServer httpServer = MyNanoHttpdServer.getInstance(null);

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        try {
            httpServer.start();
        } catch (Exception e) {
            e.printStackTrace();
            startService(new Intent(this,MyNanoHttpService.class));
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId){

        return super.onStartCommand(intent, flags, startId);
    }

    public void onDestroy() {
        httpServer.stop();
    }
}

MainActivity 启动服务

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
		 //实例化 获取ip 地址
         MyNanoHttpdServer.getInstance(getIPAddress());
        //启动服务监听
        startService(new Intent(this, MyNanoHttpService.class));
    }

     /**
     * 获得IP地址,分为两种情况:
     * 一:是wifi下;
     * 二:是移动网络下;
     */
    public  String getIPAddress() {
        Context context = WelcomeActivity.this;
        NetworkInfo info = ((ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
        if (info != null && info.isConnected()) {
            if (info.getType() == ConnectivityManager.TYPE_MOBILE) {//当前使用2G/3G/4G网络
                try {
                    //Enumeration<NetworkInterface> en=NetworkInterface.getNetworkInterfaces();
                    for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
                        NetworkInterface intf = en.nextElement();
                        for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
                            InetAddress inetAddress = enumIpAddr.nextElement();
                            if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
                                return inetAddress.getHostAddress();
                            }
                        }
                    }
                } catch (SocketException e) {
                    e.printStackTrace();
                }
            } else if (info.getType() == ConnectivityManager.TYPE_WIFI) {//当前使用无线网络
                WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
                WifiInfo wifiInfo = wifiManager.getConnectionInfo();
                //调用方法将int转换为地址字符串
                String ipAddress = intIP2StringIP(wifiInfo.getIpAddress());//得到IPV4地址
                return ipAddress;
            }
        } else {
            //当前无网络连接,请在设置中打开网络
        }
        return null;
    }

    /**
     * 将得到的int类型的IP转换为String类型
     * @param ip
     * @return
     */
    public static String intIP2StringIP(int ip) {
        return (ip & 0xFF) + "." +
                ((ip >> 8) & 0xFF) + "." +
                ((ip >> 16) & 0xFF) + "." +
                (ip >> 24 & 0xFF);
    }
}

4,总结

  • 如果想要APP保持服务持久可用,又不被系统限制网络,,可以进入系统设置中设置“电池不优化”。
  • 根据之前的并发请求测试发现,只会返回同一条数据,而不是分别响应每一个接口请求。
    目前尚未找到适合的处理方式,暂且只能控制请求端的请求频次。
  • 如果并发请求大,请不要使用NanoHTTPD,还是通过JAVA和Spring 来做服务。
  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
### 回答1: 使用Android Studio中的nanohttpd库创建HTTP服务器,并使用WebView打开HTML页面的步骤如下: 1. 首先,在build.gradle文件中的dependencies块中添加依赖项: ``` implementation 'org.nanohttpd:nanohttpd-webserver:2.3.1' ``` 2. 在需要创建HTTP服务器的Activity中,创建一个继承自NanoHTTPD的子类。例如: ```java public class MyServer extends NanoHTTPD { public MyServer() { super(8080); // 设置服务器端口为8080 } @Override public Response serve(IHTTPSession session) { String uri = session.getUri(); // 获取请求的URI // 判断请求的URI是否为根目录,如果是,则返回HTML页面,否则返回404错误 if (uri.equals("/")) { try { InputStream inputStream = getAssets().open("index.html"); // 打开assets文件夹中的index.html文件 BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); StringBuilder builder = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { builder.append(line); } reader.close(); inputStream.close(); String html = builder.toString(); return newFixedLengthResponse(Response.Status.OK, "text/html", html); // 返回HTML页面 } catch (IOException e) { e.printStackTrace(); } } return newFixedLengthResponse(Response.Status.NOT_FOUND, "text/plain", "404 Not Found"); // 返回404错误 } } ``` 3. 在Activity中启动HTTP服务器,并使用WebView打开页面: ```java WebView webView = findViewById(R.id.webView); webView.getSettings().setJavaScriptEnabled(true); // 允许WebView执行JavaScript代码 MyServer server = new MyServer(); try { server.start(); // 启动HTTP服务器 } catch (IOException e) { e.printStackTrace(); } webView.loadUrl("http://localhost:8080/"); // 使用WebView打开服务器的根目录页面 ``` 以上就是使用NanoHTTPD创建HTTP服务器使用WebView打开HTML页面的过程。在实际开发中,可以根据需要进行相应的修改和扩展。 ### 回答2: 要使用Android Studio创建一个HTTP服务器并打开HTML页面,可以使用NanoHTTPD库来实现。 首先,需要在项目的`build.gradle`文件中添加NanoHTTPD的依赖项。在`dependencies`部分添加以下代码: ``` implementation 'org.nanohttpd:nanohttpd:2.3.1' ``` 接下来,在你的Activity或Fragment中创建一个NanoHTTPD的子类,例如`MyServer`。这个子类需要实现`NanoHTTPD.IHTTPD`接口,并重写`serve()`方法来响应HTTP请求。在这个方法中,你可以通过判断请求URI来确定要返回给客户端的内容。 具体代码如下: ```java import android.content.Context; import android.webkit.WebView; import android.widget.Toast; import org.nanohttpd.protocols.http.IHTTPSession; import org.nanohttpd.protocols.http.NanoHTTPD; import org.nanohttpd.protocols.http.response.Response; import org.nanohttpd.protocols.http.response.Status; import java.io.IOException; public class MyServer extends NanoHTTPD { private Context context; public MyServer(Context context) { super(8080); this.context = context; } @Override public Response serve(IHTTPSession session) { String uri = session.getUri(); if (uri.equals("/index.html")) { String html = "<html><body><h1>Hello, World!</h1></body></html>"; return newFixedLengthResponse(Response.Status.OK, "text/html", html); } else { return newFixedLengthResponse(Response.Status.NOT_FOUND, "text/plain", "404 Not Found"); } } } ``` 然后,在你的Activity或Fragment中,可以通过创建一个WebView来加载HTML页面,并启动NanoHTTPD服务器。具体代码如下: ```java import android.os.Bundle; import android.webkit.WebView; import android.webkit.WebViewClient; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { private WebView webView; private MyServer server; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); webView = findViewById(R.id.webView); webView.getSettings().setJavaScriptEnabled(true); webView.setWebViewClient(new WebViewClient()); server = new MyServer(this); try { server.start(); Toast.makeText(this, "Server started", Toast.LENGTH_SHORT).show(); } catch (IOException e) { e.printStackTrace(); } webView.loadUrl("http://localhost:8080/index.html"); } @Override protected void onDestroy() { super.onDestroy(); if (server != null) { server.stop(); } } } ``` 在XML布局文件中添加一个WebView用于显示HTML页面。 这样,当你运行这个应用时,会在Android设备上启动一个HTTP服务器,并使用WebView加载服务器上的HTML页面。 ### 回答3: 使用Android Studio创建HTTP服务器并在WebView中打开HTML页面需要以下步骤: 1. 首先,将nanohttpd库导入到Android Studio项目中。可以通过在项目的build.gradle文件中添加以下行来实现: ```groovy dependencies { implementation 'org.nanohttpd:nanohttpd:2.3.1' } ``` 2. 创建一个新的Java类,继承自`NanoHTTPD`类,用于实现HTTP服务器。在这个类中,需要重写NanoHTTPD的`serve()`方法,来处理HTTP请求和响应。通过使用`InputStream`读取HTML文件的内容,并将其响应给请求的客户端。 ```java public class MyHTTPServer extends NanoHTTPD { // 构造方法 public MyHTTPServer() { super(8080); } @Override public Response serve(IHTTPSession session) { String uri = session.getUri(); if (uri.equals("/")) { uri = "/index.html"; } try { InputStream inputStream = getApplicationContext().getAssets().open(uri.substring(1)); String mimeType = "text/html"; return newChunkedResponse(Response.Status.OK, mimeType, inputStream); } catch (IOException e) { e.printStackTrace(); return newFixedLengthResponse(Response.Status.NOT_FOUND, "text/plain", "File not found"); } } } ``` 3. 在AndroidManifest.xml文件中添加以下权限: ```xml <uses-permission android:name="android.permission.INTERNET" /> ``` 4. 在Activity的`onCreate()`方法中启动HTTP服务器并加载WebView: ```java public class MainActivity extends AppCompatActivity { private WebView webView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 启动HTTP服务器 MyHTTPServer server = new MyHTTPServer(); try { server.start(); } catch (IOException e) { e.printStackTrace(); } webView = findViewById(R.id.webView); // 允许WebView执行JavaScript代码 webView.getSettings().setJavaScriptEnabled(true); // 加载HTTP服务器的地址 webView.loadUrl("http://localhost:8080"); } } ``` 以上是在Android Studio中使用NanoHTTPD库创建HTTP服务器并在WebView中打开HTML页面的步骤。可以根据需要对服务器和WebView进行进一步的自定义和配置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

可乐cc呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值