二维码的妙用:通过Zxing实现wifi账号密码分享功能
二维码是搭载信息的一种载体,通过二维码可以传递名片、网址、商品信息等,本文讲到二维码的另外一种妙用:通过二维码实现wifi账号和密码分享。
关于二维码的基础知识,请访问:二维码的生成细节和原理
试想这样一种场景:一伙人去同一餐馆或者在一起开会,有的人之前去过且已经使用过那个场景的wifi账号,所以一去手机就能够直接连上那里的wifi,但有的同学是第一次去,也有连接wifi的需求,这时我们一般是通过别人告知wifi账号和密码然后手动登陆,但问题是有时候已经连上wifi的人也不记得wifi的密码了,本文结合这个需求场景,做了一个wifi账号和密码分享的小demo,前提是双方都需要安装这个app,并且分享wifi的一方需要有root权限(目前是,也可以将分享wifi的客户端作为热点,然后将热点分享给其他人,这个可以自行研究),这样减少了手动输入密码的麻烦。
本文主要介绍通过二维码实现wifi分享的两个核心功能:
1、获取本机已经连接上的wifi账号、密码和加密方式;
2、给定指定内容生成二维码,扫描二维码解析出其中搭载的信息。
1、获取本机已经连接上的wifi账号、密码和加密方式:
所有的事情都可以通过下面这个类搞定:
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_NOPASSconfig.wepKeys[0] = "";config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);config.wepTxKeyIndex = 0;}if (type == 2) {// WIFICIPHER_WEPconfig.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_WPAconfig.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_8888Bitmap 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();}}
@Overridepublic 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账号密码分享功能相关推荐
- 二维码的妙用:通过Zxing实现wifi账号password分享功能
二维码是搭载信息的一种载体,通过二维码能够传递名片.网址.商品信息等,本文讲到二维码的第二种妙用:通过二维码实现wifi账号和password分享. 关于二维码的基础知识,请訪问:二维码的生成细节和原 ...
- java二维码生成-谷歌(Google.zxing)开源二维码生成学习及实例
java二维码生成-谷歌(Google.zxing)开源二维码生成的实例及介绍 这里我们使用比特矩阵(位矩阵)的QR码编码在缓冲图片上画出二维码 实例有以下一个传入参数 OutputStream o ...
- 2022-02-18 Android app 二维码扫描demo,用zxing库,实测ok,记录一下所参考有价值的文章,有生成二维码的demo,但没有亲测。
一.Android中二维码扫描的最常用库是zxing和zbar,这里用zxing. 二.实测效果图,扫描完成后会以Toast方式显示结果. 三.测试代码的架构 四.代码不细说,想看源码的可以downl ...
- IOS实现扫描二维码,利用系统API实现,看了这篇IOS扫描功能再也不用求人了。
如今在国内无论走到哪里,只要是涉及支付的方面都可以使用支付宝或微信扫个二维码进行付款.现在二维码随处可见,二维码支付,二维码点餐,二维码坐公交,二维码做地铁,广告宣传页上, 电视台节目上等等.另外连乞 ...
- Android二维码识别率优化,Android Zxing 转换竖屏扫描且提高识别率的方法
最近的一个Android需要用到扫码功能,用的是Zxing开源库.Zxing的集成就不说了,但是Zxing默认的是横屏扫码,在实际生产中并不适用,需要改为竖屏扫描. 转竖屏步骤: 1>. And ...
- 支付宝PC端二维码支付(沙箱环境)
一,准备工作 jar 获取以下内容: 1,APPID 2,支付宝网关 3,公钥 4,私钥 5,支付宝钱包账号密码 支付宝开放平台: https://openhome.alipay.com/platfo ...
- (转)ZXing生成二维码和带logo的二维码,模仿微信生成二维码效果
场景:移动支付需要对二维码的生成与部署有所了解,掌握目前主流的二维码生成技术. 1 ZXing 生成二维码 首先说下,QRCode是日本人开发的,ZXing是google开发,barcode4j也是老 ...
- 谷歌zxing 二维码生成工具
一.加入maven依赖 <!-- 谷歌zxing 二维码 --> <dependency><groupId>com.google.zxing</groupId ...
- (转载)Android项目实战(二十八):使用Zxing实现二维码及优化实例
Android项目实战(二十八):使用Zxing实现二维码及优化实例 作者:听着music睡 字体:[增加 减小] 类型:转载 时间:2016-11-21 我要评论 这篇文章主要介绍了Android项 ...
最新文章
- 计算机网络- ARP(地址解析协议)
- python select模块_Python之select模块解析
- kubernetes入门到精通(二):k8s部署Tomcat集群,基于NTFS协议的文件集群共享,Service提供负载均衡,端口转发工具Rinetd配置外部访问
- PHP如何用while实现循环,PHP 循环 -
- 混凝土墙开洞_新乐专业混凝土切割报价适中
- OpenGL 学习 显示列表
- 怎么学好MYSQL的查和改_mysql学习【第3篇】:数据库之增删改查操作
- python中的单例设计模式
- Python 模拟黑客帝国中的“代码雨”
- Office | Office365 离线安装包选择安装word、ppt、excel
- cab补丁包离线安装命令
- 主板点不亮 复位BIOS_魔改主板,体会扣扣索索装个机子的快乐。昂达H110 SD3加专用条...
- 哪里可以在线观看《人再囧途之泰囧》
- 4.证券投资基金的监管
- 软件构造心得(5)spec、RI、AF、A的概念辨析之spec
- vuecli 实现导航切换
- Unloaded branch node detected. “loadOptions“ prop is required to load its children
- 梗概Kubernetes中的Pause容器为内部镜像源
- nginx配置区分移动端和PC端,访问不同域名
- 自动点击,免写代码一键制作手机脚本!神器推荐!