<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      zxing開源庫的基本使用

      如果你的項(xiàng)目中有模塊跟二維碼相關(guān)的話,那你一定聽過或者用過大名鼎鼎的zxing開源庫。

      什么是zxing?

      ZXing是一個開源的,用Java實(shí)現(xiàn)的多種格式的1D/2D條碼圖像處理庫,它包含了聯(lián)系到其他語言的端口。zxing可以實(shí)現(xiàn)使用手機(jī)的內(nèi)置的攝像頭完成條形碼的掃描及解碼。

      本篇文章就來學(xué)習(xí)zxing的基本使用,學(xué)習(xí)了以下幾個內(nèi)容就能滿足大部分項(xiàng)目中的二維碼相關(guān)需求:

      • 通過攝像頭掃描二維碼圖片,讀取圖片內(nèi)容
      • 從相冊中選取二維碼圖片,讀取圖片內(nèi)容
      • 自己輸入字符串內(nèi)容,生成二維碼圖片
      • 長按識別自己生成的二維碼圖片

      如何依賴zxing到項(xiàng)目中?

      如果你還在使用zxing的jar包、或者你是把zxing的代碼復(fù)制到項(xiàng)目中,使用這兩種方式依賴的話那就out了,現(xiàn)在Android Studio可支持zxing在線依賴,目前最新版本是3.3.3。在線依賴的好處我就不多說了,相信大家都懂。

      新建項(xiàng)目,在app/build.gradle文件中在線依賴:

      implementation 'com.google.zxing:core:3.3.3'
      

      加入權(quán)限

      因?yàn)閽呙瓒S碼需要攝像頭權(quán)限,把圖片保存到本地需要sdcard權(quán)限,所以需要在AndroidManifest.xml中加入相應(yīng)的權(quán)限

      <uses-permission android:name="android.permission.CAMERA" />
      <uses-permission android:name="android.permission.VIBRATE" />
      <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
      
      <uses-feature android:name="android.hardware.camera" />
      <uses-feature android:name="android.hardware.camera.autofocus" />
      

      當(dāng)然現(xiàn)在市面上的手機(jī)大部分都是6.0以上的操作系統(tǒng)了,所以還得在MainActivity的onCreate方法中動態(tài)申請以上這兩個權(quán)限。

       //6.0版本或以上需請求權(quán)限
      String[] permissions=new String[]{Manifest.permission.
              WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA};
      if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
          requestPermissions(permissions,PERMS_REQUEST_CODE);
      }
      

      掃描二維碼

      項(xiàng)目依賴進(jìn)來了,權(quán)限也有了,開始用代碼實(shí)現(xiàn)第一個功能。點(diǎn)擊掃描二維碼按鈕,開啟一個ScanActivity,這個Activity是我之前封裝好的,里面處理了掃描二維碼的整個流程,掃描成功后會把掃描結(jié)果返回。ScanActivity類的代碼有點(diǎn)多,就不貼出來了,有興趣的自己看源碼。

      Intent intent = new Intent(MainActivity.this,ScanActivity.class);
      startActivityForResult(intent,SCAN_REQUEST_CODE);
      

      重寫onActivityResult方法,監(jiān)聽掃描結(jié)果。

      @Override
      protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent intent) {
          super.onActivityResult(requestCode, resultCode, intent);
      
          if (requestCode == SCAN_REQUEST_CODE && resultCode == RESULT_OK) {
              String input = intent.getStringExtra(ScanActivity.INTENT_EXTRA_RESULT);
              showToast("掃描結(jié)果:"+input);
          }
      }
      

      從相冊中選擇二維碼圖片進(jìn)行識別

      首先啟動系統(tǒng)相冊,從相冊中選擇一張圖片。

      Intent innerIntent = new Intent(Intent.ACTION_PICK,
      MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
      Intent wrapperIntent = Intent.createChooser(innerIntent, "選擇二維碼圖片");
      startActivityForResult(wrapperIntent, SELECT_IMAGE_REQUEST_CODE);
      

      然后在onActivityResult中獲取選擇圖片路徑,調(diào)用BitmapUtil.parseQRcode方法解析二維碼圖片。

      @Override
      protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent intent) {
          super.onActivityResult(requestCode, resultCode, intent);
      
          if(requestCode==SELECT_IMAGE_REQUEST_CODE){//從圖庫選擇圖片
              String[] proj = {MediaStore.Images.Media.DATA};
              // 獲取選中圖片的路徑
              Cursor cursor = this.getContentResolver().query(intent.getData(),proj, null, null, null);
              if (cursor.moveToFirst()) {
                  int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                  String photoPath = cursor.getString(columnIndex);
                  String result= BitmapUtil.parseQRcode(photoPath);
                  if (!TextUtils.isEmpty(result)) {
                      showToast("從圖庫選擇的圖片識別結(jié)果:"+result);
                  } else {
                      showToast("從圖庫選擇的圖片不是二維碼圖片");
                  }
              }
              cursor.close();
          }
      }
      

      接下來看parseQRcode方法,

      /**
       * 解析二維碼圖片
       * @param bitmapPath 文件路徑
       * @return
       */
      public static String parseQRcode(String bitmapPath){
          Bitmap bitmap = BitmapFactory.decodeFile(bitmapPath, null);
          String result=parseQRcode(bitmap);
          return result;
      }
      

      從上面的方法中看到直接把文件路徑讀取成Bitmap,繼續(xù)調(diào)用parseQRcode方法把Bitmap對象傳進(jìn)去,這里用到了方法重載。

      public static String parseQRcode(Bitmap bmp){
          bmp=comp(bmp);//bitmap壓縮  如果不壓縮的話在低配置的手機(jī)上解碼很慢
      
          int width = bmp.getWidth();
          int height = bmp.getHeight();
          int[] pixels = new int[width * height];
          bmp.getPixels(pixels, 0, width, 0, 0, width, height);
      
          QRCodeReader reader = new QRCodeReader();
          Map<DecodeHintType, Object> hints = new EnumMap<>(DecodeHintType.class);
          hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);//優(yōu)化精度
          hints.put(DecodeHintType.CHARACTER_SET,"utf-8");//解碼設(shè)置編碼方式為:utf-8
          try {
              Result result = reader.decode(new BinaryBitmap(
              new HybridBinarizer(new RGBLuminanceSource(width, height, pixels))), hints);
              return result.getText();
          } catch (NotFoundException e) {
              Log.i("ansen",""+e.toString());
              e.printStackTrace();
          } catch (ChecksumException e) {
              e.printStackTrace();
          } catch (FormatException e) {
              e.printStackTrace();
          }
          return null;
      }
      

      如果傳入的是一個Bitmap對象,先調(diào)用comp方法對Bitmap進(jìn)行壓縮(壓縮代碼這里不貼出),獲取圖片寬高,把圖像的每個像素顏色轉(zhuǎn)為int值,存入pixels數(shù)組。

      然后初始化QRCodeReader對象,調(diào)用decode方法進(jìn)行解碼,這個方法有兩個參數(shù),參數(shù)1是一個BinaryBitmap對象,第二個參數(shù)是一個Map類型,key的值是DecodeHintType枚舉類型,這里我們put了兩個值,優(yōu)化精度跟設(shè)置編碼方式為。這個方法還會返回一個Result對象,最后調(diào)用result.getText()方法獲取二維碼內(nèi)容。

      生成二維碼圖片

      生成二維碼圖片調(diào)用CreateQRBitmp.createQRCodeBitmap方法生成,這個方法是我們自己封裝的,需要傳入兩個參數(shù),參數(shù)1:圖片內(nèi)容、參數(shù)2:二維碼圖片最中間顯示的logo(Bitmap對象)。

      String contentString = etInput.getText().toString().trim();
      if(TextUtils.isEmpty(contentString)){
          showToast("請輸入二維碼內(nèi)容");
          return ;
      }
      Log.i("ansen","輸入的內(nèi)容:"+contentString);
      Bitmap portrait = BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher);
      //兩個方法,一個不傳大小,使用默認(rèn)
      qrCodeBitmap = CreateQRBitmp.createQRCodeBitmap(contentString, portrait);
      ivQrImage.setImageBitmap(qrCodeBitmap);
      

      createQRCodeBitmap源碼如下:

      public static Bitmap createQRCodeBitmap(String content,Bitmap portrait) {
          // 用于設(shè)置QR二維碼參數(shù)
          Hashtable<EncodeHintType, Object> qrParam = new Hashtable<>();
          // 設(shè)置QR二維碼的糾錯級別——這里選擇最高H級別
          qrParam.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
          // 設(shè)置編碼方式
          qrParam.put(EncodeHintType.CHARACTER_SET, "UTF-8");
      
          // 生成QR二維碼數(shù)據(jù)——這里只是得到一個由true和false組成的數(shù)組
          // 參數(shù)順序分別為:編碼內(nèi)容,編碼類型,生成圖片寬度,生成圖片高度,設(shè)置參數(shù)
          try {
              BitMatrix bitMatrix = new MultiFormatWriter().encode(content,
                      BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, qrParam);
      
              // 開始利用二維碼數(shù)據(jù)創(chuàng)建Bitmap圖片,分別設(shè)為黑白兩色
              int w = bitMatrix.getWidth();
              int h = bitMatrix.getHeight();
              int[] data = new int[w * h];
      
              for (int y = 0; y < h; y++) {
                  for (int x = 0; x < w; x++) {
                      if (bitMatrix.get(x, y))
                          data[y * w + x] = 0xff000000;// 黑色
                      else
                          data[y * w + x] = 0x00ffffff;// -1 相當(dāng)于0xffffffff 白色
                  }
              }
      
              // 創(chuàng)建一張bitmap圖片,采用最高的圖片效果ARGB_8888
              Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
              // 將上面的二維碼顏色數(shù)組傳入,生成圖片顏色
              bitmap.setPixels(data, 0, w, 0, 0, w, h);
              if(portrait!=null){
                  createQRCodeBitmapWithPortrait(bitmap,initProtrait(portrait));
              }
              return bitmap;
          } catch (WriterException e) {
              e.printStackTrace();
          }
          return null;
      }
      

      大部分代碼都有注釋,首先就是調(diào)用MultiFormatWriter對象的encode方法生成BitMatrix對象,這里我們傳入5個參數(shù),參數(shù)1:內(nèi)容、參數(shù)2:二維碼格式、參數(shù)3:圖片寬、參數(shù)4:圖片高、參數(shù)5:二維碼生成的參數(shù)(例如編碼方法以及糾錯級別)。

      拿到BitMatrix對象后開始利用二維碼數(shù)據(jù)創(chuàng)建Bitmap圖片,分別設(shè)為黑白兩色,創(chuàng)建一個寬高一樣的Bitmap對象,調(diào)用setPixels方法把上面的二維碼顏色數(shù)組傳入,生成圖片顏色。如果中間需要添加logo調(diào)用createQRCodeBitmapWithPortrait方法。最后把Bitmap對象返回。

      長按識別二維碼以及保存圖片

      識別二維碼跟從相冊中選擇圖片進(jìn)行識別功能上很相似,所以就不在做重復(fù)介紹了,就介紹一下保存圖片功能。

      從下面源碼中看到,首先獲取rootView,從rootView中獲取根布局的Bitmap,然后調(diào)用ImageUtil.savePicToLocal方法保存圖片。

      View view = getWindow().getDecorView().getRootView();//找到當(dāng)前頁面的根布局
      view.setDrawingCacheEnabled(true);//禁用繪圖緩存
      view.buildDrawingCache();
      
      Bitmap temBitmap = view.getDrawingCache();
      ImageUtil.savePicToLocal(temBitmap,MainActivity.this);
      
      //禁用DrawingCahce否則會影響性能 ,而且不禁止會導(dǎo)致每次截圖到保存的是緩存的位圖
      view.setDrawingCacheEnabled(false);//識別完成之后開啟繪圖緩存
      
      showToast("保存圖片到本地成功");
      

      ImageUtil.savePicToLocal方法也比較簡單,就是把一個Bitmap保存到本地Sdcard上。需要注意的是記得發(fā)送一個廣播,不然需要重啟手機(jī)才能在系統(tǒng)相冊中看到這個圖片。

      public static void savePicToLocal(Bitmap bitmap, Context context) {
          String filePath=Environment.getExternalStorageDirectory()
          .getAbsolutePath() + "/screen"+File.separator + System.currentTimeMillis() + ".png";
          if (bitmap != null) {
              try {
                  // 圖片文件路徑
                  Log.i("ansen", "filePath:" + filePath);
                  File file = new File(filePath);
                  if (!file.getParentFile().exists()) {
                      file.getParentFile().mkdirs();
                  }
                  FileOutputStream os = new FileOutputStream(file);
                  bitmap.compress(Bitmap.CompressFormat.PNG, 100, os);
                  Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
                  Uri uri = Uri.fromFile(new File(filePath));
                  intent.setData(uri);
                  context.sendBroadcast(intent);
                  os.flush();
                  os.close();
              } catch (Exception e) {
              }
          }
      }
      

      代碼終于寫完了,接下來看看效果,由于模擬器沒有攝像頭,而真機(jī)又不能錄制Gif圖片,所以攝像頭掃描二維碼就不演示啦,大家自己下載源碼運(yùn)行查看效果。

      image

      當(dāng)然少不了源碼,下載地址如下:

      https://github.com/ansen666/ZxingTest

      如果你想第一時間看我的后期文章,掃碼關(guān)注公眾號,長期推送Android開發(fā)文章、最新動態(tài)、開源項(xiàng)目,讓你各種漲姿勢。

            Android開發(fā)666 - 安卓開發(fā)技術(shù)分享
                   掃描二維碼加關(guān)注
      

      Android開發(fā)666

      posted @ 2018-10-25 20:43  安輝  閱讀(34671)  評論(3)    收藏  舉報(bào)
      主站蜘蛛池模板: 国产亚洲天堂另类综合| 亚洲综合色网一区二区三区| 在线无码午夜福利高潮视频| 粉嫩国产av一区二区三区| 国产福利社区一区二区| 熟妇人妻不卡中文字幕| 日韩精品一区二区三区在| 日本不卡片一区二区三区| 国产乱人伦无无码视频试看| av午夜福利亚洲精品福利| 无码AV无码免费一区二区| av中文字幕在线二区| 亚洲精品揄拍自拍首页一| 亚洲国产精品久久久天堂麻豆宅男| 中文有无人妻vs无码人妻激烈| 国产精品人妻熟女男人的天堂| 欧美精品一区二区在线观看播放 | 四虎影视一区二区精品| 国产精品亚洲а∨天堂2021| 99久久婷婷国产综合精品青草漫画 | 亚洲最大激情中文字幕| 国产在线精品一区二区三区| 热久久这里只有精品99| 临武县| 亚洲欧美人成网站在线观看看| 国产精品综合一区二区三区| 日本高清中文字幕免费一区二区| 一区二区三区四区激情视频| 一本加勒比hezyo无码人妻| 丰满人妻无码∧v区视频 | 成人精品久久一区二区三区| 国产盗摄xxxx视频xxxx| 国产情侣激情在线对白| 欧美videos粗暴| 亚洲一级特黄大片在线播放| 亚洲av永久无码精品天堂久久| 国产自拍偷拍视频在线观看| 国产综合色产在线精品| 国产精品中文字幕观看| 日韩人妻无码精品专区综合网| 真人在线射美女视频在线观看|