在安卓端启动一个服务器接口,用于接收post请求的json数据

在安卓端实现一个能接收 POST 请求(JSON 格式)的本地服务器接口,核心是借助安卓的网络编程能力搭建轻量级 HTTP 服务器。下面我会用 NanoHttpd(轻量级、易集成的 HTTP 服务器库)来实现,这是安卓端做本地服务器最常用且简单的方案。

一、实现思路

  1. 集成 NanoHttpd 依赖,简化 HTTP 服务器开发;
  2. 自定义服务器类,继承 NanoHttpd,重写 serve() 方法处理请求;
  3. serve() 中判断请求方式(POST)、解析 JSON 数据;
  4. 配置安卓权限(网络、前台服务,避免后台被杀死);
  5. 启动 / 停止服务器,测试接口可用性。

二、完整实现步骤

1. 添加依赖(build.gradle)

在模块级 build.gradle(Module: app)的 dependencies 中添加 NanoHttpd 依赖:

gradle

复制代码
dependencies {
    // 轻量级HTTP服务器库
    implementation 'org.nanohttpd:nanohttpd:2.3.1'
    // 可选:Gson解析JSON(也可用Android自带的JSONObject)
    implementation 'com.google.code.gson:gson:2.10.1'
}

同步 Gradle(Sync Now)确保依赖下载完成。

2. 自定义 HTTP 服务器类

创建 LocalHttpServer 类,处理 POST 请求并解析 JSON:

java

运行

java 复制代码
import android.util.Log;
import fi.iki.elonen.NanoHTTPD;
import com.google.gson.Gson;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;

// 自定义服务器类,指定端口(比如8080,可自定义)
public class LocalHttpServer extends NanoHTTPD {
    private static final String TAG = "LocalHttpServer";
    // 定义接口路径
    private static final String API_PATH = "/callBack";
    private final Gson gson = new Gson();

    public LocalHttpServer() {
        // 端口号:建议选1024以上(避免系统端口),比如8080
        super(8080);
    }

    @Override
    public Response serve(IHTTPSession session) {
        // 1. 判断请求方式是否为POST
        if (!Method.POST.equals(session.getMethod())) {
            // 非POST请求返回405(方法不允许)
            return newFixedLengthResponse(Response.Status.METHOD_NOT_ALLOWED, 
                    "application/json", "{\"code\":405,\"msg\":\"仅支持POST请求\"}");
        }

        // 2. 判断请求路径是否匹配目标接口
        String uri = session.getUri();
        if (!API_PATH.equals(uri)) {
            // 路径不匹配返回404
            return newFixedLengthResponse(Response.Status.NOT_FOUND, 
                    "application/json", "{\"code\":404,\"msg\":\"接口不存在\"}");
        }

        try {
            // 3. 解析POST请求中的JSON数据
            Map<String, String> files = new java.util.HashMap<>();
            session.parseBody(files);
            // 获取请求体(JSON字符串)
            String jsonBody = files.get("postData");
            Log.d(TAG, "接收到的JSON数据:" + jsonBody);

            // 示例:解析JSON为自定义对象(根据你的业务调整)
            // 假设接收的JSON结构是 {"orderId":"123","amount":100}
            NotifyData notifyData = gson.fromJson(jsonBody, NotifyData.class);
            Log.d(TAG, "解析后:订单ID=" + notifyData.getOrderId() + ",金额=" + notifyData.getAmount());

            // 4. 处理业务逻辑(比如保存数据、回调等)
            // TODO: 这里写你的业务代码

            // 5. 返回响应(JSON格式)
            String responseJson = gson.toJson(new ResponseData(200, "接收成功", notifyData));
            return newFixedLengthResponse(Response.Status.OK, 
                    "application/json;charset=UTF-8", responseJson);

        } catch (IOException | ResponseException e) {
            Log.e(TAG, "解析请求失败", e);
            // 异常返回500
            return newFixedLengthResponse(Response.Status.INTERNAL_ERROR, 
                    "application/json", "{\"code\":500,\"msg\":\"服务器内部错误\"}");
        }
    }

    // 接收的JSON数据模型(根据你的实际需求定义)
    public static class NotifyData {
        private String orderId;
        private double amount;

        // getter/setter
        public String getOrderId() { return orderId; }
        public void setOrderId(String orderId) { this.orderId = orderId; }
        public double getAmount() { return amount; }
        public void setAmount(double amount) { this.amount = amount; }
    }

    // 响应数据模型
    public static class ResponseData {
        private int code;
        private String msg;
        private NotifyData data;

        public ResponseData(int code, String msg, NotifyData data) {
            this.code = code;
            this.msg = msg;
            this.data = data;
        }

        // getter/setter(Gson需要)
        public int getCode() { return code; }
        public void setCode(int code) { this.code = code; }
        public String getMsg() { return msg; }
        public void setMsg(String msg) { this.msg = msg; }
        public NotifyData getData() { return data; }
        public void setData(NotifyData data) { this.data = data; }
    }
}
3. 配置安卓权限

AndroidManifest.xml 中添加必要权限(注意安卓 6.0 + 部分权限需动态申请,但网络权限是普通权限):

xml

复制代码
<!-- 网络权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 允许访问网络状态 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 前台服务权限(避免服务器被后台杀死) -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

<!-- 如果你的应用是安卓12+,需要声明前台服务类型 -->
<application ...>
    <service
        android:name=".LocalServerService"
        android:foregroundServiceType="dataSync|network" />
</application>
4. 封装为前台服务(避免服务器被杀死)

安卓后台进程容易被系统回收,建议将服务器放在前台服务中运行:

java

运行

java 复制代码
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import androidx.core.app.NotificationCompat;

public class LocalServerService extends Service {
    private LocalHttpServer httpServer;

    @Override
    public void onCreate() {
        super.onCreate();
        // 启动HTTP服务器
        try {
            httpServer = new LocalHttpServer();
            httpServer.start();
            // 启动前台服务
            startForeground(1, createNotification());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // 停止服务器
        if (httpServer != null) {
            httpServer.stop();
        }
    }

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

    // 创建前台服务通知
    private Notification createNotification() {
        String channelId = "LocalServerChannel";
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(
                    channelId, "本地服务器", NotificationManager.IMPORTANCE_LOW);
            NotificationManager manager = getSystemService(NotificationManager.class);
            manager.createNotificationChannel(channel);
        }

        return new NotificationCompat.Builder(this, channelId)
                .setContentTitle("本地服务器运行中")
                .setContentText("端口:8080")
                .setSmallIcon(android.R.drawable.ic_menu_info_details)
                .build();
    }
}
5. 在 Activity 中启动 / 停止服务

java

运行

java 复制代码
import android.content.Intent;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 启动本地服务器服务
        Intent serviceIntent = new Intent(this, LocalServerService.class);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            startForegroundService(serviceIntent);
        } else {
            startService(serviceIntent);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 停止服务(测试用,实际根据需求调整)
        stopService(new Intent(this, LocalServerService.class));
    }
}

三、测试接口

  1. 运行安卓应用,确保服务启动(通知栏会显示 "本地服务器运行中");
  2. 获取安卓设备的 IP 地址(设置 - 关于手机 - 状态信息 - IP 地址,比如 192.168.1.100);
  3. 用 Postman/Postwoman 等工具发送 POST 请求:
    • 请求地址:http://192.168.1.100:8080/callBack

    • 请求体:JSON 格式(示例) json

      复制代码
      {
          "orderId": "TEST123456",
          "amount": 99.9
      }
    • 请求头:Content-Type: application/json

  4. 查看安卓 Logcat,能看到 "接收到的 JSON 数据" 日志,说明接口正常工作。

四、注意事项

  1. 端口冲突:如果 8080 端口被占用,可修改服务器构造方法中的端口(比如 8081、9090);
  2. 网络环境:测试时确保请求端(比如电脑)和安卓设备在同一局域网;
  3. HTTPS 支持:NanoHttpd 默认是 HTTP,如需 HTTPS,需配置 SSL 证书(安卓端可生成自签名证书);
  4. 线程安全 :如果接口并发请求多,需在 serve() 中处理线程同步;
  5. 安卓版本适配:安卓 10 + 限制后台网络,前台服务可规避此问题。

总结

  1. 安卓端搭建接收 POST (JSON) 的服务器,首选 NanoHttpd 库,轻量且易集成;
  2. 核心是重写 serve() 方法,判断请求方式 / 路径、解析 JSON、处理业务并返回响应;
  3. 服务器需放在前台服务中运行,避免被安卓系统后台回收,同时要配置网络权限。

通过以上代码,你可以实现类似 https://opnqiaryuankejinet/prod-api/pos/kPayNotify 的接口(仅协议为 HTTP,如需 HTTPS 可扩展 SSL 配置),成功接收并解析 POST 的 JSON 数据。

相关推荐
吃不饱的得可可1 小时前
【三方库】jsoncpp
c++·json
意疏2 小时前
openJiuwen实战:用AsyncCallbackFramework为Agent增强器添加可观测性
java·服务器·前端
hindon2 小时前
一文读懂Android 中的 MVC、MVP、MVVM
android
野犬寒鸦2 小时前
面试常问:HTTP 1.0 VS HTTP 2.0 VS HTTP 3.0 的核心区别及底层实现逻辑
服务器·开发语言·网络·后端·面试
漏刻有时2 小时前
CentOS 不定时 OOM 根治方案:PHP-FPM 进程管控 + Swap 扩容 + 全维度监控
android·centos·php
闫记康2 小时前
scp工具
linux·运维·服务器·学习·ssh·github
我命由我123452 小时前
Git 问题:Author identity unknown*** Please tell me who you are.
java·服务器·git·后端·学习·java-ee·学习方法
默|笙3 小时前
【Linux】库制作与原理(2)_ELF格式
linux·运维·服务器
青桔柠薯片3 小时前
Linux I/O多路复用:深入浅出poll与epoll
linux·运维·服务器·算法