二维码的妙用:通过Zxing实现wifi账号password分享功能

时间:2023-03-08 23:58:28
二维码的妙用:通过Zxing实现wifi账号password分享功能

二维码是搭载信息的一种载体,通过二维码能够传递名片、网址、商品信息等,本文讲到二维码的第二种妙用:通过二维码实现wifi账号和password分享。

关于二维码的基础知识,请訪问:二维码的生成细节和原理

试想这样一种场景:一伙人去同一餐馆或者在一起开会,有的人之前去过且已经使用过那个场景的wifi账号。所以一去手机就能够直接连上那里的wifi,但有的同学是第一次去。也有连接wifi的需求,这时我们通常是通过别人告知wifi账号和password然后手动登陆。但问题是有时候已经连上wifi的人也不记得wifi的password了。本文结合这个需求场景。做了一个wifi账号和password分享的小demo。前提是两方都须要安装这个app,而且分享wifi的一方须要有root权限(眼下是。也能够将分享wifi的client作为热点,然后将热点分享给其它人,这个能够自行研究),这样降低了手动输入password的麻烦。

二维码的妙用:通过Zxing实现wifi账号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体验。