Android QR Code 掃描 各種條碼都能掃
透過Google Vision套件快速製作屬於自己的QR Code 掃描,進行QR Code 掃描各種條碼都能掃,Android QR Code利用相機功能・透過Mobile Vision API 解析QR Code,各種條碼都能掃。
文章目錄
- 導入Google Vision
 
- 聲明相機權限
 
- 布局&方法介紹
 
- 程式碼範例
 
- 效果展示
 
- Github
 
1.導入Google Vision
dependencies {
     implementation 'com.google.android.gms:play-services-vision:20.1.3'
}
2.聲明相機權限
<uses-permission android:name="android.permission.CAMERA"/>
3.布局&方法介紹
布局
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <SurfaceView
        android:id="@+id/scanner"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/guideline2"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <TextView
        android:id="@+id/result"
        android:textSize="30sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/black"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/scanner" />
    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.5" />
</androidx.constraintlayout.widget.ConstraintLayout>
方法介紹
偵測Barcode樣式
BarcodeDetector.Builder(this@MainActivity)
        .setBarcodeFormats(Barcode.ALL_FORMATS)
        .build()
創建Camera
//傳入Barcode樣式
CameraSource.Builder(this@MainActivity, barcodeDetector)
        //自動對焦
        .setAutoFocusEnabled(true)
        //預覽寬高
        .setRequestedPreviewSize(measuredWidth, measuredHeight)
        .build()
綁定Camer
holder.addCallback(object : SurfaceHolder.Callback {
    override fun surfaceCreated(holder: SurfaceHolder) {
        cameraSource.start(holder)
    }
    override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
    }
    override fun surfaceDestroyed(holder: SurfaceHolder) {
        cameraSource.stop()
    }
})
掃描完成資料回傳
barcodeDetector.setProcessor(object : Detector.Processor<Barcode> {
    override fun release() {
    }
    override fun receiveDetections(detections: Detector.Detections<Barcode>) {
        result = findViewById(R.id.result)
        //獲取資料
        val barcode = detections.detectedItems
        if (barcode.size() > 0) {
            runOnUiThread {
                result.text = barcode.valueAt(0).displayValue
            }
        }
    }
})
4.程式碼範例
import android.Manifest
import android.annotation.SuppressLint
import android.content.pm.PackageManager
import android.os.Bundle
import android.util.Log
import android.view.SurfaceHolder
import android.view.SurfaceView
import android.view.ViewTreeObserver.OnGlobalLayoutListener
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import com.google.android.gms.vision.CameraSource
import com.google.android.gms.vision.Detector
import com.google.android.gms.vision.barcode.Barcode
import com.google.android.gms.vision.barcode.BarcodeDetector
private const val REQUEST_CAMERA: Int = 40
@SuppressLint("MissingPermission")
class MainActivity : AppCompatActivity() {
    private lateinit var scanner: SurfaceView
    private lateinit var result: TextView
    private lateinit var cameraSource: CameraSource
    private lateinit var barcodeDetector: BarcodeDetector
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //移除ActionBar
        supportActionBar?.hide()
        //先獲取相機權限
        if (ActivityCompat.checkSelfPermission(
                this,
                Manifest.permission.CAMERA
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            ActivityCompat.requestPermissions(
                this,
                arrayOf(Manifest.permission.CAMERA),
                REQUEST_CAMERA
            )
        } else {
            //初始化掃描器
            initScanner()
            //偵測後回傳
            resultCallback()
        }
    }
    private fun resultCallback() {
        barcodeDetector.setProcessor(object : Detector.Processor<Barcode> {
            override fun release() {
            }
            override fun receiveDetections(detections: Detector.Detections<Barcode>) {
                result = findViewById(R.id.result)
                //或取資料
                val barcode = detections.detectedItems
                if (barcode.size() > 0) {
                    runOnUiThread {
                        result.text = barcode.valueAt(0).displayValue
                    }
                }
            }
        })
    }
    private fun initScanner() {
        scanner = findViewById(R.id.scanner)
        scanner.apply {
            //創建Barcode偵測
            barcodeDetector = BarcodeDetector.Builder(this@MainActivity)
                .setBarcodeFormats(Barcode.ALL_FORMATS)
                .build()
            //獲取寬高後創建Camera
            viewTreeObserver.addOnGlobalLayoutListener(object : OnGlobalLayoutListener {
                override fun onGlobalLayout() {
                    viewTreeObserver.removeOnGlobalLayoutListener(this)
                    cameraSource = CameraSource.Builder(this@MainActivity, barcodeDetector)
                        .setAutoFocusEnabled(true)
                        .setRequestedPreviewSize(measuredWidth, measuredHeight)
                        .build()
                }
            })
            //camera綁定surfaceView
            holder.addCallback(object : SurfaceHolder.Callback {
                override fun surfaceCreated(holder: SurfaceHolder) {
                    cameraSource.start(holder)
                }
                override fun surfaceChanged(
                    holder: SurfaceHolder,
                    format: Int,
                    width: Int,
                    height: Int
                ) {
                }
                override fun surfaceDestroyed(holder: SurfaceHolder) {
                    cameraSource.stop()
                }
            })
        }
    }
    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (REQUEST_CAMERA == requestCode && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            setContentView(R.layout.activity_main)
            //初始化掃描器
            initScanner()
            //偵測後回傳
            resultCallback()
        }
    }
}
5.效果展示

6.Github
Github