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