废话少说,直接上代码!
zxing:https://github.com/zxing/zxing
效果图:
APP端
以module形式引入zxing的android库,代码按需求自行修改,也可以下载使用此demo中的已修改的库。
主要调用的接口如下:
public class ZXingProxy {
private static ZXingProxy proxy = null;
public static ZXingProxy getInstance() {
if (null == proxy) {
synchronized (ZXingProxy.class) {
if (null == proxy) {
proxy = new ZXingProxy();
}
}
}
return proxy;
}
/**
* 开始扫码
*
* @param activity
*/
public void startScanQr(Activity activity) {
if (null == activity) {
return;
}
Intent scanIntent = new Intent(activity, CaptureActivity.class);
activity.startActivityForResult(scanIntent, 1001);
}
/**
* 生成二维码
*
* @param content 二维码内容
* @param width 宽
* @param height 高
* @param logoBm 中间图片logo
* @return 返回值
*/
public Bitmap createQrCode(String content, int width, int height, Bitmap logoBm) {
Bitmap bitmap = EncodeUtil.createQrCode(content, width, height, logoBm);
return bitmap;
}
/**
* 扫码登录请求
*
* @param url
* @param map
* @param callback
*/
public void doPost(String url, Map<String, String> map, Callback callback) {
if (null == url || url.trim().isEmpty()) {
return;
}
OkHttpUtil.getInstance().postCall(url, map, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
if (null != callback) {
callback.fail();
}
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (null != callback) {
String json = response.body().string();
callback.result(true, json);
}
}
});
}
}
打开扫码界面:
ZXingProxy.getInstance().startScanQr(MainActivity.this);
返回扫码结果,向服务器请求登录:
//返回扫码结果,向服务器请求登录
if (requestCode == 1001 && resultCode == RESULT_OK) {
String result = data.getExtras().getString("result");
OkHttpTool.webLogin(this, textView, result);
}
服务端核心代码
public class Helper {
private static final String baseUrl = "http://xxx:8080/QrCodeHelper/QrLoginService";
private static Helper helper = null;
private String uuid;
private Map<String, UserLoginVo> userLoginMap = new HashMap<String, UserLoginVo>();
public static Helper getInstance() {
if (null == helper) {
synchronized (Helper.class) {
if (null == helper) {
helper = new Helper();
}
}
}
return helper;
}
/**
* 创建二维码信息,和其创建的时间
*
* @return
*/
public void creatQRMes(HttpServletResponse response) {
//创建UUID
uuid = UUID.randomUUID().toString().replace("-", "").toUpperCase();
/**
* Path.QR_SUBMIT:扫码后要提交地址(例如:"http://192.168.43.9:8080/CarTaketing/User/esauCode.do",即是要执行服务端的方法,
* 这是为了方便app端扫码后是执行登录进而做自己需要的操作,若扫到其它地址,app端直接跳转到该地址)。
* uuid:二维码唯一的标志符
*/
String qrMessage = baseUrl + "?k=" + uuid;//二维码信息,是一个带参数的地址
//返回qrMessage 和 qrMessage 创建的时间给客户端
String dateStr = String.valueOf(new Date().getTime());
TokenVo tokenVo = new TokenVo();
tokenVo.setQrMessage(qrMessage);
tokenVo.setDate(dateStr);
try {
JSONUtil.writeJsonStr(response, tokenVo);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 轮询 判断用户是否扫码,没有则返回 "0" ,扫了则返回 "1",验证码过期了返回 "-1"
*
* @param response
* @param dateStr 创建二维码信息的时间
* @return
*/
public void isScanCode(HttpServletResponse response, String dateStr) {
long newDate = new Date().getTime();
long date = Long.valueOf(dateStr);
String result = "0";
if(userLoginMap.get(uuid) != null) {//判断是否扫码
result = "1";
}else if(newDate - date >= 60000){//判断是否过期,过期将重新生成二维码
result = "-1";
}
try {
JSONUtil.writeJsonStr(response, result);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 判断是否同意登录
* 返回1则同意登录,0为反之,-1则未做出选择
*
* @param response
* @param request
*/
public void isAgreeLogin(HttpServletResponse response, HttpServletRequest request) {
String result = "-1";
UserLoginVo uLoginVo = userLoginMap.get(uuid);
if(uLoginVo != null && uLoginVo.getAgreeOrNot() != null) {
if(uLoginVo.getAgreeOrNot()) {
//说明app端已经同意登录
User user = new User();
user.setUserName(uLoginVo.getUserName());
request.getSession().setAttribute("user", user);//保存用户
result = "1";
}else {
//不同意登录
result = "0";
}
//清除qrMessage在userLoginMap里的信息
userLoginMap.remove(uuid);
}
try {
JSONUtil.writeJsonStr(response, result);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* app端调用:userLoginMap添加键值对,标记该二维码已经被扫码
*
* @param uuid
*/
public void markCode(String uuid) {
if(uuid != null) {
userLoginMap.put(uuid, new UserLoginVo());
}
}
/**
* app端调用:
* 是否同意web登录
*
* @param request
* @param agreeOrNot 是否允许登录
* @param user 用户信息
* @return
*/
public void doSelection(HttpServletResponse response, Boolean agreeOrNot, User user) {
Message message = new Message(400,"信息异常");
if(agreeOrNot != null) {
//同意登录
if(agreeOrNot) {
if(user != null && userLoginMap.get(uuid) != null) {
//标记用户同意登录
userLoginMap.get(uuid).setAgreeOrNot(true);
userLoginMap.get(uuid).setUserName(user.getUserName());
message = new Message(200,"已授权");
//此处做具体验证操作
//不同意
}else {
//标记用户不同意登录
userLoginMap.get(uuid).setAgreeOrNot(false);
message = new Message(200,"取消登录");
}
}
try {
JSONUtil.writeJsonStr(response, message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
完整demo下载:客户端&服务器