完成Device之间的文件传输demo, 可以通过WiFi传输, 也可以用通用的HTTP协议, 因为只是演示作用, 因此 选择NanoHTTPD(https://github.com/NanoHttpd/nanohttpd),
NanoHTTPD免费/轻量级的(只有一个Java文件), 可以用来搭建http server,可以很好地嵌入到Java程序中,支持 GET, POST, PUT, HEAD 和 DELETE 请求,支持文件上传,占用内存很小. 我们可以根据自己的需求进行简单的封装,
github上有对这个库进行了简单封装(implementation 'cn.hotapk:fhttpserver:0.4.0'), 其实就是加入了注解反射, 使用更加简单
httpclient 使用了AsyncHttpClient(https://github.com/loopj/android-async-http), 使用起来也很简单,
官方文档:loopj.com/android-async-http
具体的例子解析:https://blog.csdn.net/maybeforever/article/details/88073914
HttpServer:
在子线程中启动服务:
implementation 'cn.hotapk:fhttpserver:0.4.0'
FHttpManager fHttpManager;
fHttpManager = FHttpManager.init(this, UserController.class);
fHttpManager.setPort(8000);
fHttpManager.setAllowCross(true);
fHttpManager.startServer();
public class UserController {
private String defaultStatus;
private IProcessListener mListener;
//客户端上传文件, 服务器接收文件
@RequestMapping("upload")
public String upload(NanoHTTPD.IHTTPSession session) {
ToastUtils.showShort("Received a message");
boolean result = FFileUploadUtils.uploadFile(session, Constants.getBitmapPath(), "file")
if (uploadStatus) {
final CountDownLatch latch = new CountDownLatch(1);
mListener = new IProcessListener() {
@Override
public void success(String status) {
defaultStatus = status;
latch.countDown();
}
@Override
public void failure(String error) {
defaultStatus = error;
latch.countDown();
}
};
parseFile(fileDir + "/" + parms.get(parm));
latch.await();
return defaultStatus;
} else {
return "Failed to download file";
}
}
@RequestMapping("gethtml")
public String getHtml() {
ToastUtils.showShort("testHtml");
return "index2.html";
}
}
结束时销毁服务
if (fHttpManager != null) {
fHttpManager.stopServer();
}
fHttpManager = null;
获取当前device的ip
public static String getIPAddress(Context context) {
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 en=NetworkInterface.getNetworkInterfaces();
for (Enumeration en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
NetworkInterface intf = en.nextElement();
for (Enumeration 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();
String ipAddress = intIP2StringIP(wifiInfo.getIpAddress());//得到IPV4地址
return ipAddress;
}
} else {
//当前无网络连接,请在设置中打开网络
}
return null;
}
HttpClient:
implementation 'com.loopj.android:android-async-http:1.4.10'
String path = "文件路径";
if (!isOnline(context)){
ToastUtils.showShort("Network is Unavailable!");
return false;
}
String url = "123.123.0.10";//可以通过getIPAddress获取,填入client Device中
RequestParams params = new RequestParams();
try {
params.put("file", new File(path));
} catch(FileNotFoundException e) {
ToastUtils.showShort("File not found!");
return false;
}
AsyncHttpClient client = new AsyncHttpClient();
client.setTimeout(2000);
StringBuilder urlUpload = new StringBuilder();
if (!url.contains("http")){
urlUpload.append("http://");
}
urlUpload.append(url);
urlUpload.append(":8000/upload");
ToastUtils.showShort("IP: "+urlUpload);
client.post(urlUpload.toString(), params, new AsyncHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, cz.msebera.android.httpclient.Header[] headers, byte[] responseBody) {
Log.i("upload", "upload success");
ToastUtils.showShort("success");
}
@Override
public void onFailure(int statusCode, cz.msebera.android.httpclient.Header[] headers, byte[] responseBody, Throwable error) {
Log.i("upload", "upload failure");
ToastUtils.showShort("Failure:"+error.getMessage());
}
});
public static boolean isOnline(Context context) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = null;
try {
networkInfo = cm.getActiveNetworkInfo();
} catch (Exception e) {
// #1405 shows that this throws a SecurityException.
// b/70869360 shows that this throws NullPointerException on APIs 22, 23, and 24.
// b/70869360 also shows that this throws RuntimeException on API 24 and 25.
Log.e("isOnline", "exception: " + CommonTool.getExceptionMessage(e));
// 无法判断, 就返回true
return true;
}
if (networkInfo != null && networkInfo.isAvailable() && networkInfo.isConnected()) {
return true;
}
return false;
}
PS:
接收请求是异步进行的,中间会调用其它异步操作进行处理,如何进行接收异步调用结果并返回呢?
用CountDownLatch 啦,异步请求转阻塞式同步请求
CountDownLatch latch = new CountDownLatch(1);
异步回调 latch.countDown();