作为移动开发码农,扫码功能几乎是绕不开的功能点,之前开发一般使用的是Zxing类库操作,最近发现有华为的扫码SDK可用且效果更好更好用,故记录下用Swift及Kotlin分别实现。

1. 相关资料

2. Android实现

<!--相机权限-->
<uses-permission android:name="android.permission.CAMERA" />
<!--读文件权限-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
  • 代码动态获取权限

    import android.Manifest
    import android.content.Intent
    import android.content.pm.PackageManager
    import android.os.Build
    import androidx.appcompat.app.AppCompatActivity
    import android.os.Bundle
    import android.widget.Toast
    import com.huawei.hms.hmsscankit.ScanUtil
    import com.huawei.hms.ml.scan.HmsScan
    import com.huawei.hms.ml.scan.HmsScanAnalyzerOptions
    import com.xlgz520.scantest.databinding.ActivityMainBinding
    
    class MainActivity : AppCompatActivity() {
    
        private lateinit var binding: ActivityMainBinding
    
        private val rCode = 10000
        private val requestCodeScan = 10001
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            binding = ActivityMainBinding.inflate(layoutInflater)
            setContentView(binding.root)
    
            binding.scan.setOnClickListener {
                // 请求权限
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
                    this.requestPermissions(
                        arrayOf(Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE), rCode
                    )
                }
            }
        }
    
        override fun onRequestPermissionsResult(
            requestCode: Int,
            permissions: Array<out String>,
            grantResults: IntArray) {
            if (grantResults.size < 2 || 
                grantResults[0] != PackageManager.PERMISSION_GRANTED || 
                grantResults[1] != PackageManager.PERMISSION_GRANTED) return
    
            if (requestCode == rCode){
                ScanUtil.startScan(this, requestCodeScan, HmsScanAnalyzerOptions.Creator().setHmsScanTypes(
                    HmsScan.ALL_SCAN_TYPE).create())
            }
        }
    
        override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
            //当扫码页面结束后,处理扫码结果
            super.onActivityResult(requestCode, resultCode, data)
          
            if (resultCode != RESULT_OK || data == null) return
    
            if (requestCode == requestCodeScan){
                val obj: Any? = data.getParcelableExtra(ScanUtil.RESULT)
                if (obj is HmsScan){
                    if (obj.getOriginalValue().isNotEmpty()){
                      // 这里就获取到了扫描结果,本demo只做了最简单的扫码功能,更多使用情况请查看上面的官方文档
                        Toast.makeText(this, obj.getOriginalValue(), Toast.LENGTH_SHORT).show()
                    }
                    return
                }
            }
        }
    }

### 3. iOS实现

  • 集成HMS Core SDK,本文使用的是cocoapods方式安装

    pod 'ScanKitFrameWork', '~> 1.0.2.300'

  • 指定权限,打开项目的info.plist文件,增加以下权限

    <key>NSCameraUsageDescription</key>
    <string>请允许APP访问您的相机</string>
    <key>NSPhotoLibraryUsageDescription</key>
    <string>请允许APP访问您的相册</string>
  • 代码实现

    func initV(){
      let btn = UIButton()
      self.view.addSubview(btn)
      // 这里使用的snapkit布局
      btn.snp.makeConstraints { make in
          make.center.equalTo(self.view.snp.center)
          make.width.equalTo(80)
          make.height.equalTo(35)
      }
      btn.backgroundColor = .red
      btn.setTitleColor(.white, for: .normal)
      btn.setTitle("点我扫码", for: UIControlState.normal)
      btn.addTarget(self, action: #selector(scan), for: .touchUpInside)
    }
        
    @objc func scan(){
       //"QR_CODE | DATA_MATRIX"表示只扫描QR和DataMatrix的码
       let options = HmsScanOptions.init(scanFormatType:
                                         UInt32(HMSScanFormatTypeCode.QR_CODE.rawValue |           
                                                HMSScanFormatTypeCode.DATA_MATRIX.rawValue), 
                                         photo: false)
       let scanVc = HmsDefaultScanViewController(defaultScanWithFormatType: options)!
       scanVc.defaultScanDelegate = self
       self.view.addSubview(scanVc.view)
       self.addChildViewController(scanVc)
       //隐藏导航栏
       self.navigationController?.isNavigationBarHidden = false
    }
        
    // 扫描本地图片返回结果
    func defaultScanImagePickerDelegate(for image: UIImage!) {
      DispatchQueue.main.async {
        //在主线程内处理数据
    
      }
    }
        
    // 扫描结果
    func defaultScanDelegate(forDicResult resultDic: [AnyHashable : Any]!) {
      DispatchQueue.main.async {
        /**
        ResultPoint = (
        {
        posX = "323.595001";
        posY = "600.075012";
      },
        {
        posX = "321.975006";
        posY = "316.575012";
      },
        {
        posX = "607.905029";
        posY = "327.1050011";
      },
        {
        posX = "609.525024";
        posY = "610.605042";
      }
      );
        //曝光值
        exposureAdjustmentValue = 0;
        //码制
        formatvalue = "QR_CODE";
        //放大倍数
        zoomValue = 1.0;
        //场景类型
        sceneType = Text;
        //码值
        text = ssssss
        */
        //在主线程内处理数据  上面注释的就是返回的字典里可取出的各项相关数据
        print(resultDic["text"] as! String)
      }
    }
文章目录