最近接到一个需求,需要实现一个局域网的图片二维码分享功能;具体怎么样呢,先看下面的效果图:
由于是局域网,请使用真机,如果有两个手机更好了,连接同个局域网就可以看到;如果是只有一个手机,那就电脑上看把, html 的布局有点丑,因为主要是 适配手机,我也不擅长这一块,见怪不怪吧。
一、需求分析
要实现局域网,一般就是搭建个 ServerSocket,设备连接时输出网址即可
二维码分享,没啥好说,zxing .
咦,好像就没了啊,关键是局域网这个服务器了, 搭建 Android 的局域网,自己写的话,估计调试都调到很久,github 搜了一下,主要有三个,AndServer ,国人写的,思路比较适合我们,但有时会遇到连接超时的问题,不知道是不是我网络的问题;还有 NanoHttpd 和 AndroidAsync,NanoHttpd 适合java,且调试不好调试,最后选择了 AndroidAsync,接入简单,而且接口也比较好用。(以上只是个人观点),但 AndroidAsync 关于服务器方面的资料还是比较少的,所以得看源码了,不过这里也做了一些封装,到时可以参考一下。
二、代码配置
局域网,首先需要有网络,所以这里直接检查网络好了,需要检测 WiFi 是否能检测到,这里的 WiFi 的 IP 获取也比较简单,当检测到 WiFi 连接了,直接拿就是了:
//wifi是否连接
if (CusUtil.isWifiConnected()){
//获取 ip
DEVICE_IP = CusUtil.getWifiIpaddr();
StringBuilder sb = new StringBuilder();
sb.append("请在同个wifi下,扫描该二维码,或者浏览器中输入: \n")
.append("http://"+DEVICE_IP+":"+SERVER_PORT)
.append("\n或者输入:\n")
.append("http://"+DEVICE_IP+":"+SERVER_PORT+"/password");
textView.setText(sb.toString());
}else{
textView.setText("您还未连接 wifi ");
}
如果 WiFi 获取了,则开始配置数据,主要是 ip 和port,当然还有添加拦截器,图片和密码还是需要拦截的。
private void startLanServer(){
mCheckRequestHandle = CheckRequestHandle.create(this,DEVICE_IP,SERVER_PORT);
//配置数据,builder 模式
LanServerBean bean = LanServerBean.lanBuilder()
.setPort(SERVER_PORT)
.setIpAddr(DEVICE_IP)
//配置默认 html 字符串
.setDefaultHtml(CusUtil.getDefaultString(DEVICE_IP,SERVER_PORT))
//添加拦截,当检测 image,输出图片
.registerHandler("image", ImageRequestHandle.create(this))
//添加拦截,当检测 password,弹出密码验证框
.registerHandler("password",mCheckRequestHandle)
.builder();
if (mServiceBinder != null) {
mServiceBinder.startLanServer(bean);
}
}
如果自己有新的需求,也可以继续添加拦截器,拦截器也比较简单,AndroidAsync 的 api 还是比较人性化的:
public class ImageRequestHandle implements HttpServerRequestCallback {
private static final String TAG = "ImageRequestHandle";
private Context mContext;
private ImageRequestHandle(Context context){
mContext = context;
}
public static ImageRequestHandle create(Context context){
return new ImageRequestHandle(context);
}
@Override
public void onRequest(AsyncHttpServerRequest request, AsyncHttpServerResponse response) {
try {
InputStream is = mContext.getAssets().open("beauty.jpg");
//输入图片
response.sendStream(is,is.available());
} catch (Exception e) {
e.printStackTrace();
}
}
}
html 的获取都是在 assets 中,而一些动态的,比如 ip 和 端口,则是通过 代码重新添加,关于 html 的基础,就不解释啦,自己去撸吧:
/**
* 输出验证密码的html
* @return
*/
public static String getCheckPasswordHtml(String ipaddr,int port,String password){
StringBuilder sb = new StringBuilder();
sb.append(CusUtil.getAssetsString("checkpass.html")).append("\n")
.append("<button class=\"button\" onclick=\"checkPassword(")
.append(password+",'"+"http://"+ipaddr+":"+port+"')\">确定</button>").append("\n")
.append(" </div>").append("\n")
.append(" </div>").append("\n")
.append(" </body>").append("\n")
.append(" </html>").append("\n");
return sb.toString();
}
三、扩展
继续局域网分享图片已经懂了,那么像局域网传输文件,信息共享等等,都是可以搞的。比如比较火的 WiFi 传书,就是这个原理。多去折腾吧。
四、代码地址
完整的文章代码可以查看Github地址:https://github.com/LillteZheng/LanServer
原文发布时间为:2018-0717
本文作者:LillteZheng
本文来自云栖社区合作伙伴“ 安卓巴士Android开发者门户”,了解相关信息可以关注“ 安卓巴士Android开发者门户”。