Target Version : 27
•とにかくなんでもいいからCamera2でバーコードを読みたい。
•基本的に「Camera2でプレビューしてみる」と同じ。
build.gradle
dependencies {
...
implementation 'com.google.android.gms:play-services:11.0.4+'
}
MainActivity.kt
package jp.kd2.simplebarcode1
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
import android.view.TextureView;
import android.widget.Toast;
import com.google.android.gms.vision.Frame
import com.google.android.gms.vision.barcode.Barcode
import com.google.android.gms.vision.barcode.BarcodeDetector
class MainActivity : AppCompatActivity() {
// ? -> Nullable Type
private var mTextureView: TextureView? = null
private val TAG = MainActivity::class.java.simpleName
private var detector : BarcodeDetector? = null // Activity初期化
// 立ち上げ時と、タテ→ヨコ、ヨコ→タテの変換時にも呼ばれる。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mTextureView = findViewById(R.id.preview)
detector = BarcodeDetector.Builder(applicationContext)
.setBarcodeFormats(Barcode.DATA_MATRIX or Barcode.QR_CODE or Barcode.ISBN or Barcode.CODE_128).build()
}
// 描画時
override fun onResume() {
super.onResume()
// TextureViewが利用可能になったらカメラを開く
if (mTextureView!!.isAvailable) {
// call now
val width = mTextureView!!.width
val height = mTextureView!!.height
openCamera(width, height)
} else {
// 動画等を描画する際にコールバックする関数を登録する。
mTextureView!!.surfaceTextureListener = mSurfaceTextureListener
}
}
// 停止時
public override fun onPause() {
super.onPause()
closeCamera()
}
/******************** カメラ制御 ********************/
private var mCameraDevice: CameraDevice? = null
private var mSize: Size? = null // カメラの状態によるコールバックメソッド
private val mStateCallback = object : CameraDevice.StateCallback() {
// カメラに接続された時
override fun onOpened(cameraDevice: CameraDevice) {
mCameraDevice = cameraDevice
createCameraPreviewSession()
}
// カメラが切断させたとき
override fun onDisconnected(cameraDevice: CameraDevice) {
mCameraDevice = null
}
// エラー
override fun onError(cameraDevice: CameraDevice, i: Int) {
mCameraDevice = null
}
}
// カメラに接続する。
private fun openCamera(width: Int, height: Int) {
// パーミッションのチェック
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
// パーミッションを求める。
requestCameraPermission()
return
}
val cameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManager
try {
val cameraId = cameraManager.cameraIdList[0]
val characteristics = cameraManager.getCameraCharacteristics(cameraId)
val map = characteristics.get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
mSize = map!!.getOutputSizes(SurfaceTexture::class.java)[0]
cameraManager.openCamera(cameraId, mStateCallback, null)
} catch (t: Throwable) {
Log.d(TAG, t.message)
}
}
// カメラを切断する。
private fun closeCamera() {
try {
if (null != mCameraDevice)
mCameraDevice!!.close()
} catch (t: Throwable) {
Log.d(TAG, t.message)
}
}
/******************** プレビュー制御 ********************/
private var mCaptureRequestbuilder: CaptureRequest.Builder? = null
private var gWidth : Int = 0
private var gHeight : Int = 0 // 描画領域のイベントリスナ
private val mSurfaceTextureListener = object : TextureView.SurfaceTextureListener {
override fun onSurfaceTextureAvailable(texture: SurfaceTexture, width: Int, height: Int) {
openCamera(width, height)
gWidth = width
gHeight = height
}
override fun onSurfaceTextureSizeChanged(texture: SurfaceTexture, width: Int, height: Int) {
Log.d("DEBUG", "onSurfaceTextureSizeChanged")
}
override fun onSurfaceTextureDestroyed(texture: SurfaceTexture): Boolean {
return true
}
override fun onSurfaceTextureUpdated(texture: SurfaceTexture) {
Log.d("DEBUG", "onSurfaceTextureUpdated")
try {
val frame = Frame.Builder().setBitmap(mTextureView!!.getBitmap(gWidth, gHeight)).build()
val barcodes = detector!!.detect(frame)
if (barcodes.size() > 0) {
val thisCode = barcodes.valueAt(0)
Log.d("code", thisCode.rawValue)
System.out.println(thisCode.rawValue)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
// 描画領域のコールバックメソッド
private val mCaptureStateCallback = object : CameraCaptureSession.StateCallback() {
override fun onConfigured(cameraCaptureSession: CameraCaptureSession) {
try {
cameraCaptureSession.setRepeatingRequest(mCaptureRequestbuilder!!.build(), null, null)
} catch (t: Throwable) {
Log.d(TAG, t.message)
}
} override fun onConfigureFailed(cameraCaptureSession: CameraCaptureSession) {}
}
// プレビューセッションの開始
private fun createCameraPreviewSession() {
val texture = mTextureView!!.surfaceTexture
texture.setDefaultBufferSize(mSize!!.width, mSize!!.height)
val surface = Surface(texture)
try {
mCaptureRequestbuilder = mCameraDevice!!.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
mCaptureRequestbuilder!!.addTarget(surface)
mCameraDevice!!.createCaptureSession(listOf(surface), mCaptureStateCallback, null)
} catch (t: Throwable) {
Log.d(TAG, t.message)
}
}
/******************** パーミッション制御 ********************/
private val REQUEST_CAMERA_PERMISSION = 1
// ユーザにパーミッションの許可を求める。
private fun requestCameraPermission() {
requestPermissions(arrayOf(Manifest.permission.CAMERA), REQUEST_CAMERA_PERMISSION)
}
// パーミッションの結果を取得後のコールバックメソッド
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array,
grantResults: IntArray) {
if (requestCode == REQUEST_CAMERA_PERMISSION) {
if (grantResults.size != 1 || grantResults[0] != PackageManager.PERMISSION_GRANTED) {
// パーミッションが許可されなかった場合。
this.finish()
}
} else {
// 許可ダイアログの承認結果を受け取る。
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
}
}