Android 搭建局域网服务器

AndServer

AndServer 类似于 Apache 和 Tomcat,支持在同个局域网下的设备能够以常规的网络请求方式来向 Web 服务器请求数据,只要指明 Web 服务器的 IP 地址和端口号即可

使用

添加依赖

implementation 'com.yanzhenjie:andserver:1.1.3'

CoreService类
注意在注册时.registerHandler()中字符要与html文件中的action一致
NetUtils类文末提供

**
 * 本地局域网启动Service
 */

public class CoreService extends Service {

    private Server mServer;

    @Override
    public void onCreate() {
        AssetManager mAssetManager = getAssets();
        /**
         * rootPath 表示在assets资源文件中的位置,根目录为空即可
         * 有目录传入 "目录" 即可
         */
        AssetsWebsite wesite = new AssetsWebsite(mAssetManager, "");

        mServer = AndServer.serverBuilder()
                .port(8080) //服务器要监听的端口
                .timeout(30000, TimeUnit.SECONDS) //Socket超时时间
                .website(wesite)        //设置路径
                .registerHandler("/json", new JsonHandler()) //注册一个Post Json接口  /json对应html form标签中的action
                .filter(new HttpCacheFilter()) //开启缓存支持
                .listener(new Server.ServerListener() {  //服务器监听接口
                    @Override
                    public void onStarted() {
                        //获取本地地址供外部访问
                        InetAddress address = NetUtils.getLocalIPAddress();
                        ServerManager.onServerStart(CoreService.this, address.getHostAddress());
                    }

                    @Override
                    public void onStopped() {
                    }

                    @Override
                    public void onError(Exception e) {
                        ServerManager.onServerError(CoreService.this, e.getMessage());
                    }
                })
                .build();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        startServer();
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        stopServer();
        super.onDestroy();
    }

    /**
     * 开启服务
     */
    private void startServer() {
        mServer.startup();
    }

    /**
     * 停止服务
     */
    private void stopServer() {
        mServer.shutdown();
    }

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

JsonHandler类
日志与设置类就不提供了,这里自己处理返回的数据即可;
转义的工具类文末提供

/**
 * post表单处理
 */
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);

        //解析网址(还原转义字符)
        String ServiceUrl = UrlDeal.decodeURIComponent(content).substring(UrlDeal.decodeURIComponent(content).indexOf("=")+1);
        //保存日志
        LogUtil.info("Time:"+System.currentTimeMillis()+"IPAddress"+ServiceUrl+"  Modify server address");
        //保存解析后的网址
        ConfigOperate.getInstance(null).setHost_url(ServiceUrl);
        JSONObject jsonObject = null;
        try {
            jsonObject = new JSONObject(content);
            //进行
        } catch (JSONException e) {
            e.printStackTrace();
        }
        if (jsonObject == null) {
            jsonObject = new JSONObject();
        }
        try {
            //向web返回数据 中文乱码
            jsonObject.put("state", "Server address modified successfully");
        } catch (JSONException e) {
            e.printStackTrace();
        }
        StringEntity stringEntity = new StringEntity(jsonObject.toString(), "utf-8");
        httpResponse.setStatusCode(200);
        httpResponse.setEntity(stringEntity);
    }

}

index.html
这个文件直接放在assets资源文件夹下即可

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>修改地址</title>
    <style>
		.search{
			width: 681px;
			height: 43px;
			margin: 0px auto;
			margin-top:20%;
		}
		.search input#ip{
			height: 43px;
			line-height: 43px;
			width: 550px;
			font-size: 16px;
			padding: 0px 15px;
			border: 1px #b6b6b6 solid;
			border-radius: 10px 0 0 10px;
			border-right: 0px;
			float: left;
		}
		.search input#submit{
			float: left;
			width: 100px;
			text-align: center;
			background: #4e6ef2;
			border: 1px solid #4e6ef2;
			border-radius: 0 10px 10px 0;
			height: 45px;
			font-size: 18px;
			color: #fff;
			font-weight: bold;
		}
	</style>
</head>
<body>
<div class="search">
    <form id="form1" action="/json" method="post">
        <input type="text" name="ip" id="ip" value="" placeholder="请输入服务器地址"/>
        <input type="submit" id="submit" value="确定" />
    </form>

</div>
</body>
</html>

UrlDeal类

import java.io.UnsupportedEncodingException;

/**
 * 实现JS中的encodeURIComponent 、 decodeURIComponent 方法
 * 转义字符串、解析字符串
 */

public class UrlDeal {
    public static final String ALLOWED_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!~*'()";


    public static String encodeURIComponent(String input) {

        if (input == null || "".equals(input)) {

            return input;

        }


        int l = input.length();

        StringBuilder o = new StringBuilder(l * 3);

        try {

            for (int i = 0; i < l; i++) {

                String e = input.substring(i, i + 1);

                if (ALLOWED_CHARS.indexOf(e) == -1) {

                    byte[] b = e.getBytes("utf-8");

                    o.append(getHex(b));

                    continue;

                }

                o.append(e);

            }

            return o.toString();

        } catch (UnsupportedEncodingException e) {

            e.printStackTrace();

        }

        return input;

    }


    private static String getHex(byte buf[]) {

        StringBuilder o = new StringBuilder(buf.length * 3);

        for (int i = 0; i < buf.length; i++) {

            int n = (int) buf[i] & 0xff;

            o.append("%");

            if (n < 0x10) {

                o.append("0");

            }

            o.append(Long.toString(n, 16).toUpperCase());

        }

        return o.toString();

    }


    public static String decodeURIComponent(String encodedURI) {

        char actualChar;


        StringBuffer buffer = new StringBuffer();


        int bytePattern, sumb = 0;


        for (int i = 0, more = -1; i < encodedURI.length(); i++) {

            actualChar = encodedURI.charAt(i);


            switch (actualChar) {

                case '%': {

                    actualChar = encodedURI.charAt(++i);

                    int hb = (Character.isDigit(actualChar) ? actualChar - '0'

                            : 10 + Character.toLowerCase(actualChar) - 'a') & 0xF;

                    actualChar = encodedURI.charAt(++i);

                    int lb = (Character.isDigit(actualChar) ? actualChar - '0'

                            : 10 + Character.toLowerCase(actualChar) - 'a') & 0xF;

                    bytePattern = (hb << 4) | lb;

                    break;

                }

                case '+': {

                    bytePattern = ' ';

                    break;

                }

                default: {

                    bytePattern = actualChar;

                }

            }


            if ((bytePattern & 0xc0) == 0x80) { // 10xxxxxx

                sumb = (sumb << 6) | (bytePattern & 0x3f);

                if (--more == 0)

                    buffer.append((char) sumb);

            } else if ((bytePattern & 0x80) == 0x00) { // 0xxxxxxx

                buffer.append((char) bytePattern);

            } else if ((bytePattern & 0xe0) == 0xc0) { // 110xxxxx

                sumb = bytePattern & 0x1f;

                more = 1;

            } else if ((bytePattern & 0xf0) == 0xe0) { // 1110xxxx

                sumb = bytePattern & 0x0f;

                more = 2;

            } else if ((bytePattern & 0xf8) == 0xf0) { // 11110xxx

                sumb = bytePattern & 0x07;

                more = 3;

            } else if ((bytePattern & 0xfc) == 0xf8) { // 111110xx

                sumb = bytePattern & 0x03;

                more = 4;

            } else { // 1111110x

                sumb = bytePattern & 0x01;

                more = 5;

            }

        }

        return buffer.toString();

    }
}

NetUtils类

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.regex.Pattern;

/**
 * 网络工具类
 */

public class NetUtils {

    /**
     * Ipv4 address check.
     */
    private static final Pattern IPV4_PATTERN = Pattern.compile(
        "^(" + "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}" +
            "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$");

    /**
     * Check if valid IPV4 address.
     *
     * @param input the address string to check for validity.
     *
     * @return True if the input parameter is a valid IPv4 address.
     */
    public static boolean isIPv4Address(String input) {
        return IPV4_PATTERN.matcher(input).matches();
    }

    /**
     * Get local Ip address.
     */
    public static InetAddress getLocalIPAddress() {
        Enumeration<NetworkInterface> enumeration = null;
        try {
            enumeration = NetworkInterface.getNetworkInterfaces();
        } catch (SocketException e) {
            e.printStackTrace();
        }
        if (enumeration != null) {
            while (enumeration.hasMoreElements()) {
                NetworkInterface nif = enumeration.nextElement();
                Enumeration<InetAddress> inetAddresses = nif.getInetAddresses();
                if (inetAddresses != null) {
                    while (inetAddresses.hasMoreElements()) {
                        InetAddress inetAddress = inetAddresses.nextElement();
                        if (!inetAddress.isLoopbackAddress() && isIPv4Address(inetAddress.getHostAddress())) {

                            return inetAddress;

                        }
                    }
                }
            }
        }
        return null;
    }
}

直接在需要使用的地方启动CoreService即可开启服务
局域网地址示例 http://10.0.0.1:8080/index.html
具体ip地址打日志或者debug看吧

github地址: Anderver

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值