二维码的妙用:通过Zxing实现wifi账号password分享功能
二维码是搭载信息的一种载体,通过二维码能够传递名片、网址、商品信息等,本文讲到二维码的第二种妙用:通过二维码实现wifi账号和password分享。
关于二维码的基础知识,请訪问:二维码的生成细节和原理
试想这样一种场景:一伙人去同一餐馆或者在一起开会,有的人之前去过且已经使用过那个场景的wifi账号。所以一去手机就能够直接连上那里的wifi,但有的同学是第一次去。也有连接wifi的需求,这时我们通常是通过别人告知wifi账号和password然后手动登陆。但问题是有时候已经连上wifi的人也不记得wifi的password了。本文结合这个需求场景。做了一个wifi账号和password分享的小demo。前提是两方都须要安装这个app,而且分享wifi的一方须要有root权限(眼下是。也能够将分享wifi的client作为热点,然后将热点分享给其它人,这个能够自行研究),这样降低了手动输入password的麻烦。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZWtldXk=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
本文主要介绍通过二维码实现wifi分享的两个核心功能:
1、获取本机已经连接上的wifi账号、password和加密方式。
2、给定指定内容生成二维码,扫描二维码解析出当中搭载的信息。
1、获取本机已经连接上的wifi账号、password和加密方式:
全部的事情都能够通过以下这个类搞定:
public class WifiAdmin {
public WifiAdmin(Context context) {
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
mWifiInfo = mWifiManager.getConnectionInfo();
} // 打开WIFI
public void openWifi() {
if (!mWifiManager.isWifiEnabled()) {
mWifiManager.setWifiEnabled(true);
}
} // 关闭WIFI
public void closeWifi() {
if (mWifiManager.isWifiEnabled()) {
mWifiManager.setWifiEnabled(false);
}
} // 检查当前WIFI状态
public int checkState() {
return mWifiManager.getWifiState();
} // 锁定WifiLock
public void acquireWifiLock() {
mWifiLock.acquire();
} // 解锁WifiLock
public void releaseWifiLock() {
// 推断时候锁定
if (mWifiLock.isHeld()) {
mWifiLock.acquire();
}
} // 创建一个WifiLock
public void creatWifiLock() {
mWifiLock = mWifiManager.createWifiLock("Test");
} // 得到配置好的网络
public List<WifiConfiguration> getConfiguration() {
return mWifiConfiguration;
} // 指定配置好的网络进行连接
public void connectConfiguration(int index) {
// 索引大于配置好的网络索引返回
if (index > mWifiConfiguration.size()) {
return;
}
// 连接配置好的指定ID的网络
mWifiManager.enableNetwork(mWifiConfiguration.get(index).networkId,
true);
} public void startScan() {
mWifiManager.startScan();
// 得到扫描结果
mWifiList = mWifiManager.getScanResults();
// 得到配置好的网络连接
mWifiConfiguration = mWifiManager.getConfiguredNetworks();
} // 得到网络列表
public List<ScanResult> getWifiList() {
return mWifiList;
} // 查看扫描结果
@SuppressLint("UseValueOf")
public StringBuilder lookUpScan() {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < mWifiList.size(); i++) {
stringBuilder.append("Index_" + new Integer(i + 1).toString() + ":");
// 将ScanResult信息转换成一个字符串包 当中把包含:BSSID、SSID、capabilities、frequency、level
stringBuilder.append((mWifiList.get(i)).toString());
stringBuilder.append("/n");
}
return stringBuilder;
} // 得到MAC地址
public String getMacAddress() {
return (mWifiInfo == null) ? "NULL" : mWifiInfo.getMacAddress();
} // 得到接入点的BSSID
public String getBSSID() {
return (mWifiInfo == null) ? "NULL" : mWifiInfo.getBSSID();
} // 得到IP地址
public int getIPAddress() {
return (mWifiInfo == null) ? 0 : mWifiInfo.getIpAddress();
} // 得到连接的ID
public int getNetworkId() {
return (mWifiInfo == null) ? 0 : mWifiInfo.getNetworkId();
} // 得到WifiInfo的全部信息包
public WifiInfo getWifiInfo() {
return mWifiInfo;
} // 加入一个网络并连接
public void addNetwork(WifiConfiguration wcg) {
int wcgID = mWifiManager.addNetwork(wcg);
boolean b = mWifiManager.enableNetwork(wcgID, true);
System.out.println("a--" + wcgID);
System.out.println("b--" + b);
} // 断开指定ID的网络
public void disconnectWifi(int netId) {
mWifiManager.disableNetwork(netId);
mWifiManager.disconnect();
} // 然后是一个实际应用方法。仅仅验证过没有密码的情况:
// 分为三种情况:1没有密码2用wep加密3用wpa加密
public WifiConfiguration CreateWifiInfo(String SSID, String password, int type) {
WifiConfiguration config = new WifiConfiguration();
config.allowedAuthAlgorithms.clear();
config.allowedGroupCiphers.clear();
config.allowedKeyManagement.clear();
config.allowedPairwiseCiphers.clear();
config.allowedProtocols.clear();
config.SSID = "\"" + SSID + "\""; WifiConfiguration tempConfig = this.IsExsits(SSID);
if (tempConfig != null) {
mWifiManager.removeNetwork(tempConfig.networkId);
} if (type == 1) {
// WIFICIPHER_NOPASS
config.wepKeys[0] = "";
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
config.wepTxKeyIndex = 0;
}
if (type == 2) {
// WIFICIPHER_WEP
config.hiddenSSID = true;
config.wepKeys[0] = "\"" + password + "\"";
config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
config.wepTxKeyIndex = 0;
}
if (type == 3) {
// WIFICIPHER_WPA
config.preSharedKey = "\"" + password + "\"";
config.hiddenSSID = true;
config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
// config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
config.status = WifiConfiguration.Status.ENABLED;
} return config;
} private WifiConfiguration IsExsits(String SSID) {
List<WifiConfiguration> existingConfigs = mWifiManager.getConfiguredNetworks();
if (null == existingConfigs) {
return null;
}
for (WifiConfiguration existingConfig : existingConfigs) {
System.out.println("existingConfig == " + existingConfig.toString());
if (existingConfig.SSID.equals("\"" + SSID + "\"")) {
System.out.println("existingConfig.SSID == " + existingConfig.SSID + " SSID == " + SSID);
return existingConfig;
}
} return null;
} public List<UserWifiInfo> getUserWifiInfoList( ) throws Exception {
List<UserWifiInfo> wifiInfos=new ArrayList<UserWifiInfo>(); Process process = null;
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
StringBuffer wifiConf = new StringBuffer();
try {
process = Runtime.getRuntime().exec("su");
dataOutputStream = new DataOutputStream(process.getOutputStream());
dataInputStream = new DataInputStream(process.getInputStream());
dataOutputStream.writeBytes("cat /data/misc/wifi/*.conf\n");
dataOutputStream.writeBytes("exit\n");
dataOutputStream.flush();
InputStreamReader inputStreamReader = new InputStreamReader(
dataInputStream, "UTF-8");
BufferedReader bufferedReader = new BufferedReader(
inputStreamReader);
String line = null;
while ((line = bufferedReader.readLine()) != null) {
wifiConf.append(line);
}
bufferedReader.close();
inputStreamReader.close();
process.waitFor();
} catch (Exception e) {
throw e;
} finally {
try {
if (dataOutputStream != null) {
dataOutputStream.close();
}
if (dataInputStream != null) {
dataInputStream.close();
}
process.destroy();
} catch (Exception e) {
throw e;
}
} Pattern network = Pattern.compile("network=\\{([^\\}]+)\\}", Pattern.DOTALL);
Matcher networkMatcher = network.matcher(wifiConf.toString() );
while (networkMatcher.find() ) {
String networkBlock = networkMatcher.group();
Pattern ssid = Pattern.compile("ssid=\"([^\"]+)\"");
Matcher ssidMatcher = ssid.matcher(networkBlock); if (ssidMatcher.find() ) {
UserWifiInfo wifiInfo=new UserWifiInfo();
wifiInfo.Ssid=ssidMatcher.group(1);
Pattern psk = Pattern.compile("psk=\"([^\"]+)\"");
Matcher pskMatcher = psk.matcher(networkBlock);
if (pskMatcher.find() ) {
wifiInfo.Password=pskMatcher.group(1);
} else {
wifiInfo.Password="无密码";
}
wifiInfos.add(wifiInfo);
} } return wifiInfos;
} private WifiManager mWifiManager = null;
private WifiInfo mWifiInfo = null;
private List<ScanResult> mWifiList = null;
private List<WifiConfiguration> mWifiConfiguration = null;
private WifiLock mWifiLock = null;
}
使用到wifi的各种功能。记得添加对应地权限:
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" >
</uses-permission>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" >
</uses-permission>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" >
</uses-permission>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" >
</uses-permission>
2、给定指定内容生成二维码,扫描二维码解析出当中搭载的信息:
本文使用到了开源二维码项目zxing,关于zxing的很多其它介绍请參看:二维码、条形码扫描——使用Google ZXing
(1)将指定内容生成二维码的方法例如以下:
@SuppressWarnings("deprecation")
private void generate( String result ){
if( TextUtils.isEmpty( result ) ){
return;
} try{
//推断result合法性
if (result == null || "".equals(result) || result.length() < 1){
return;
}
Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
//图像数据转换,使用了矩阵转换
BitMatrix bitMatrix = new QRCodeWriter().encode(result, BarcodeFormat.QR_CODE, QR_WIDTH, QR_HEIGHT, hints);
int[] pixels = new int[QR_WIDTH * QR_HEIGHT];
//以下这里依照二维码的算法,逐个生成二维码的图片。
//两个for循环是图片横列扫描的结果
for (int y = 0; y < QR_HEIGHT; y++){
for (int x = 0; x < QR_WIDTH; x++){
if (bitMatrix.get(x, y)){
pixels[y * QR_WIDTH + x] = 0xff000000;
}else{
pixels[y * QR_WIDTH + x] = 0xffffffff;
}
}
}
//生成二维码图片的格式,使用ARGB_8888
Bitmap bitmap = Bitmap.createBitmap(QR_WIDTH, QR_HEIGHT, Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, QR_WIDTH, 0, 0, QR_WIDTH, QR_HEIGHT);
//显示到一个ImageView上面
mResultImg.setBackground( new BitmapDrawable( bitmap ) ); decodeBitmap( bitmap );
}catch (WriterException e) {
e.printStackTrace();
}
} private String decodeBitmap( Bitmap bitmap ){
MultiFormatReader multiFormatReader = new MultiFormatReader();
// 解码的參数
Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>(2);
// 能够解析的编码类型
Vector<BarcodeFormat> decodeFormats = new Vector<BarcodeFormat>();
if (decodeFormats == null || decodeFormats.isEmpty()) {
decodeFormats = new Vector<BarcodeFormat>(); // 这里设置可扫描的类型,我这里选择了都支持
decodeFormats.addAll(DecodeFormatManager.ONE_D_FORMATS);
decodeFormats.addAll(DecodeFormatManager.QR_CODE_FORMATS);
decodeFormats.addAll(DecodeFormatManager.DATA_MATRIX_FORMATS);
}
hints.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormats); // 设置继续的字符编码格式为UTF8
// hints.put(DecodeHintType.CHARACTER_SET, "UTF8"); // 设置解析配置參数
multiFormatReader.setHints(hints); // 開始对图像资源解码
try {
Result rawResult = multiFormatReader.decodeWithState(new BinaryBitmap(new HybridBinarizer( new com.uperone.zxing.decoding.BitmapLuminanceSource(bitmap))));
mDecodeReslutTxt.setText(new StringBuilder().append("包含内容:")
.append(rawResult.getText()).append("\n编码方式:")
.append(rawResult.getBarcodeFormat()).toString());
} catch (NotFoundException e) {
e.printStackTrace();
} return null;
}
(2)解析出二维码中搭载的内容方法例如以下:
/**
* Decode the data within the viewfinder rectangle, and time how long it took. For efficiency,
* reuse the same reader objects from one decode to the next.
*
* @param data The YUV preview frame.
* @param width The width of the preview frame.
* @param height The height of the preview frame.
*/
private void decode(byte[] data, int width, int height) {
long start = System.currentTimeMillis();
Result rawResult = null;
PlanarYUVLuminanceSource source = CameraManager.get().buildLuminanceSource(data, width, height);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
try {
rawResult = multiFormatReader.decodeWithState(bitmap);
} catch (ReaderException re) {
// continue
} finally {
multiFormatReader.reset();
} if (rawResult != null) {
long end = System.currentTimeMillis();
Log.d(TAG, "Found barcode (" + (end - start) + " ms):\n" + rawResult.toString());
Message message = Message.obtain(activity.getHandler(), R.id.decode_succeeded, rawResult);
Bundle bundle = new Bundle();
bundle.putParcelable(DecodeThread.BARCODE_BITMAP, source.renderCroppedGreyscaleBitmap());
message.setData(bundle);
//Log.d(TAG, "Sending decode succeeded message...");
message.sendToTarget();
} else {
Message message = Message.obtain(activity.getHandler(), R.id.decode_failed);
message.sendToTarget();
}
}
@Override
public void handleMessage(Message message) {
switch (message.what) {
case R.id.auto_focus:
//Log.d(TAG, "Got auto-focus message");
// When one auto focus pass finishes, start another. This is the closest thing to
// continuous AF. It does seem to hunt a bit, but I'm not sure what else to do.
if (state == State.PREVIEW) {
CameraManager.get().requestAutoFocus(this, R.id.auto_focus);
}
break;
case R.id.restart_preview:
Log.d(TAG, "Got restart preview message");
restartPreviewAndDecode();
break;
case R.id.decode_succeeded:
Log.d(TAG, "Got decode succeeded message");
state = State.SUCCESS;
Bundle bundle = message.getData();
Bitmap barcode = bundle == null ? null :
(Bitmap) bundle.getParcelable(DecodeThread.BARCODE_BITMAP);
activity.handleDecode((Result) message.obj, barcode);
break;
case R.id.decode_failed:
// We're decoding as fast as possible, so when one decode fails, start another.
state = State.PREVIEW;
CameraManager.get().requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
break;
case R.id.return_scan_result:
Log.d(TAG, "Got return scan result message");
activity.setResult(Activity.RESULT_OK, (Intent) message.obj);
activity.finish();
break;
case R.id.launch_product_query:
Log.d(TAG, "Got product query message");
String url = (String) message.obj;
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
activity.startActivity(intent);
break;
}
}
public void handleDecode(final Result obj, Bitmap barcode){
inactivityTimer.onActivity();
playBeepSoundAndVibrate();
String result = obj.getText();
if(!TextUtils.isEmpty( result ) ){
System.out.println( "result == " + result );
String[] results = result.split( "#" );
String user = results[ 0 ];
String password = results[ 1 ];
int type = Integer.parseInt( results[ 2 ] );
WifiAdmin wifiAdmin = new WifiAdmin(this);
wifiAdmin.openWifi();
wifiAdmin.addNetwork(wifiAdmin.CreateWifiInfo(user, password, type)); Toast.makeText( this, result, Toast.LENGTH_LONG ).show( );
}
}
本例在扫描二维码时使用到了相机功能,所以须要加上关于camera的一些权限:
<uses-permission android:name="android.permission.CAMERA" >
</uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" >
</uses-permission> <uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
关于demo的具体功能和各功能的具体代码可到这里下载demo体验。
二维码的妙用:通过Zxing实现wifi账号password分享功能的更多相关文章
- 提高zxing生成二维码的容错率及zxing生成二维码的边框设置
最近做了一个项目要生成二维码,跟几年前不同,最近大家都喜欢在二维码中间加logo. 加logo倒是不难,两个图片叠一起就是了,但是遇到一个新问题,logo加得太大的话,会导致二维码扫描不出来;加的太小 ...
- 二维码开源库zbar、zxing使用心得
首先说明我的测试场景是“识别打印在纸上的二维码”,在扫描结果中寻找二维码并进行识别,而不是直接让摄像头对着二维码扫描. zbar和zxing用的都是自己从github上clone的c++源码/接口编译 ...
- java二维码生成-谷歌(Google.zxing)开源二维码生成学习及实例
java二维码生成-谷歌(Google.zxing)开源二维码生成的实例及介绍 我们使用比特矩阵(位矩阵)的QR码编码在缓冲图片上画出二维码 实例有以下一个传入参数 OutputStream ou ...
- 生成二维码的方法,基于zxing
现在生活中常用了一些二维码,这些在现实生活中已经非常密切了,那么怎么使用java来产生一个二维码呢? 下面给出代码 首先给出一个工具类,这里包含了生成二维码的图片对象,保存到流中,或者文件中: pac ...
- Java二维码生成与解码工具Zxing使用
Zxing是Google研发的一款非常好用的开放源代码的二维码生成工具,目前源码托管在github上,源码地址: https://github.com/zxing/zxing 可以看到Zxing库有很 ...
- java二维码之利用谷歌的zxing生成二维码,解析二维码
生成二维码 @RequestMapping("/123") public void test(HttpServletRequest request,HttpServletRespo ...
- zxing解析带logo二维码会报com.google.zxing.NotFoundException
参考原文:https://blog.csdn.net/cyl1226541/article/details/70557232 //复杂模式,开启PURE_BARCODE模式(☆☆☆) HINTS.pu ...
- 今天成功完成二维码扫描程序, 利用zxing
利用的网上参考文档是https://blog.csdn.net/gorky_19/article/details/78454030,里面介绍了如何修改build.gradle的dependency 和 ...
- Java生成带小图标的二维码-google zxing 工具类
近期一直忙于开发微信商城项目,应客户要求,要开发个有图标的二维码.经过两次改版,终于实现了该功能(第一次没有小图标,这次才整合好的),如下是完整代码 . 该代码使用Java7开发,另外使用 core- ...
随机推荐
- Java集合框架的知识总结
说明:面试准备,写的挺不错的. 转载地址: http://www.cnblogs.com/zhxxcq/archive/2012/03/11/2389611.html 1.综述 所有集合类都位于jav ...
- Installing on CentOS/RHEL / KB forum / Ajenti
Installing on CentOS/RHEL / KB forum / Ajenti Ajenti → KB → Installation Is it?: Inappropriate Spam ...
- asp.net中 服务器控件中onselectedindexchanged 没有反应的解决方案
最近发现项目中一个BUG就是 DropDownList 中的onselectedindexchanged 没有反应 AutoPostBack="true"和页面中的<%@ P ...
- 访问Tableau自带的PostgreSQL数据库
突然发现公司Tableau服务器的数据库大小急剧增加,因此决定直接连上数据库排查.过程记录如下:最后发现有个http_requests 表体积巨大(7G),本来以为是数据缓存什么的.结果是日志问题o( ...
- C# 读取Excel日期格式
读取Excel日期数据,一种方式是在EXCEL中把你的日期列的格式设置一下,设成"文本"型. 如果单元格格式设置为date,则在后台读出的数值是一个数值,如2008-08-08读出 ...
- C#_会员管理系统:开发八(权限分配)
数据库设计 这里由于增加了普通用户权限值,我们需要对数据库结构稍作修改.这里在MovieAccount表中增加4列内容 分别用于 RightFManager 判断普通用户管理界面权限 ...
- C++改变编程入口为main函数
1, 你用vc建了一个控制台程序,它的入口函数应该是main, 而你使用了WinMain. 2. 你用vc打开了一个.c/.cpp 文件,然后直接编译这个文件,这个文件中使用了WinMian而不是m ...
- selenium 怎么处理display:none
页面HTML是这样的: .... <div class="cf w index-middle"> <div id="li" class=&q ...
- NSData 数据转换
NSData,数据,当我们需要把一些信息写入到文件里或发送到网络上,我们需要把这些数据转换下,变成纯粹的0.1字符流 数组转 NSData NSData *GLYtime = [NSKeyedArch ...
- NET Core 环境搭建和命令行CLI入门
NET Core 环境搭建和命令行CLI入门 2016年6月27日.NET Core & ASP.NET Core 1.0在Redhat峰会上正式发布,社区里涌现了很多文章,我也计划写个系列文 ...