一、感谢2个开源库
implementation 'com.koushikdutta.async:androidasync:3.1.0'
// 大佬的README.md写的是下面这个,这个有bug:只能用http去请求,如果用https请求服务端APP会闪退,issues里建议升级为3.1.0
compile 'com.koushikdutta.async:androidasync:2.+'
implementation 'com.squareup.okhttp3:okhttp:4.0.0'
二、搭建服务端APP
AsyncHttpServer mServer = new AsyncHttpServer();
// Post接口files
mServer.post("/files", (request, response) -> {
final MultipartFormDataBody body = request.getBody();
body.setMultipartCallback(part -> {
// http里每带一个Part都会走这个回调
if (part.isFile()) {
// 文件
body.setDataCallback((DataEmitter emitter, ByteBufferList bb) -> {
Log.i("TAG", "File: " + bb.getAllByteArray().clone().length);
// 这里做对接受的文件进行文件存储
bb.recycle();
});
} else {
// 非文件
if (body.getDataCallback() == null) {
body.setDataCallback((DataEmitter emitter, ByteBufferList bb) -> {
bb.recycle();
});
}
}
});
request.setEndCallback(ex -> {
// 接口请求结束回调
response.code(666);
response.send("收到");
response.end();
});
});
// 端口
mServer.listen(5000);
....
// 关闭服务器
mServer.stop();
三、用androidasync库做客户端网络请求至服务端
public void asyncHttpPost() {
// localhost为服务端IP地址
AsyncHttpPost post = new AsyncHttpPost("http://localhost:5000/files");
MultipartFormDataBody body = new MultipartFormDataBody();
// 加入2个文件Part ,批量或单个文件, 我这边测试用多个
body.addFilePart("my-file", new File("/storage/emulated/0/xinxin/logininfo/logininfo.ini"));
body.addFilePart("my-file2", new File("/storage/emulated/0/xinxin/logininfo/logininfo.ini"));
post.setBody(body);
AsyncHttpClient.getDefaultInstance().executeString(post, new AsyncHttpClient.StringCallback() {
@Override
public void onCompleted(Exception ex, AsyncHttpResponse source, String result) {
if (ex != null) {
ex.printStackTrace();
return;
}
Log.i("TAG", "onCompleted: " + result);
}
});
}
四、用okhttp库做客户端网络请求至服务端
public void okhttpHttpPost() {
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS) //设置连接超时
.readTimeout(10, TimeUnit.SECONDS) //设置读超时
.writeTimeout(10, TimeUnit.SECONDS) //设置写超时
.retryOnConnectionFailure(true)
.build();
// 批量或单个文件, 我这边测试用多个
File file1 = new File("/storage/emulated/0/xinxin/logininfo/logininfo.ini");
File file2 = new File("/storage/emulated/0/xinxin/logininfo/logininfo.ini");
//使用MultipartBody上传多个文件
MultipartBody multipartBody = new MultipartBody.Builder()
.addFormDataPart("file1", file1.getName(), RequestBody.create(MediaType.parse("multipart/form-data"), file1))
.addFormDataPart("file2", file1.getName(), RequestBody.create(MediaType.parse("multipart/form-data"), file2))
.build();
// IP是你的服务端IP
Request request = new Request.Builder().url("http://"+IP+":5000/files")
.post(multipartBody)
.addHeader("Connection", "close")
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
Log.i("TAG", "onFailure: ");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.i("TAG", "onResponse: ");
if (response.isSuccessful()) {//判断是否返回成功
Log.i("TAG", "Get异步请求" + response.body().string());
}
}
});
}
五、获取Ip地址-服务端IP地址
try {
for (Enumeration<NetworkInterface> mEnumeration = NetworkInterface
.getNetworkInterfaces(); mEnumeration.hasMoreElements(); ) {
NetworkInterface mInf = mEnumeration.nextElement();
for (Enumeration<InetAddress> IpAddress = mInf
.getInetAddresses(); IpAddress
.hasMoreElements(); ) {
InetAddress inetAddress = IpAddress.nextElement();
if (!inetAddress.isLoopbackAddress()
&& inetAddress instanceof Inet4Address
) {
if (!inetAddress.getHostAddress().equals("null")
&& inetAddress.getHostAddress() != null) {
// displayName的类型有:eth0是有线网络地址,wlan0是无线网络,ap0是热点
if (mInf.getDisplayName().equals("eth0")) {
System.out.println("这是本机有线网络:" + inetAddress
.getHostAddress());
} else if (mInf.getDisplayName().equals("ap0")) {
System.out.println("这是本机热点:" + inetAddress
.getHostAddress());
} else if (mInf.getDisplayName().equals("wlan0")) {
System.out.println("这是本机wifi:" + inetAddress
.getHostAddress());
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
六、题外
正常来说运用场景很局限。留笔自记。有空记录蓝牙Socket传输。