二維碼的妙用:通過Zxing實現wifi帳號密碼分享功能,zxingwifi

來源:互聯網
上載者:User

二維碼的妙用:通過Zxing實現wifi帳號密碼分享功能,zxingwifi

        二維碼是搭載資訊的一種載體,通過二維碼可以傳遞名片、網址、商品資訊等,本文講到二維碼的另外一種妙用:通過二維碼實現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_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的二維碼編碼功可以將代碼(例如A,B,C)編碼成二維碼

www.apkbus.com/...139981
此處是一個網友分享的二維碼產生和識別的教程,附有Demo,你去瞭解一下吧,希望對你有協助!望採納!
 
我們自己開發的二維碼用戶端拍碼功可以用的Zxing

您這個自己解決的二維碼東東,恐怕沒人會跟您這邊說吧!現在都要花錢買的啊
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.