背景
Androidでカメラアプリを作成しています。(当方はAndroidもKotlinも数日前から始めた初心者です)
AWSのAmplify Predictionsを用いて、撮った画像から文字列を検出しようとしているのですが、
写真撮影後にエラーが発生し、アプリがシャットダウンしてしまいます。
エラーについて
エラー文は、java.lang.IllegalStateException: Tried to get a plugin but that plugin was not present.となっていたので、Google検索をしてみた結果、複数のサイトでAmplify.addPlugin(AWSPredictionsPlugin())が抜けていることが原因だと書かれていましたので、追加しました。ですが、エラーはそのままです。画像は以下です。
ソースコード
エラーの箇所は、以下のコードのimageCapture.takePicture内で、detectText(imageBit)としているところです。Amplify.addPlugin(AWSPredictionsPlugin())は、onCreateで行っています。よろしく願いします。
kotlin
1package com.example.urldetection 2 3import androidx.appcompat.app.AppCompatActivity 4import android.os.Bundle 5import android.Manifest 6import android.content.pm.PackageManager 7import android.net.Uri 8import android.util.Log 9import android.widget.Toast 10import androidx.core.app.ActivityCompat 11import androidx.core.content.ContextCompat 12import java.util.concurrent.Executors 13import androidx.camera.core.* 14import androidx.camera.lifecycle.ProcessCameraProvider 15import kotlinx.android.synthetic.main.activity_main.* 16import java.io.File 17import java.nio.ByteBuffer 18import java.text.SimpleDateFormat 19import java.util.* 20import java.util.concurrent.ExecutorService 21import android.media.MediaPlayer 22 23import com.amazonaws.services.rekognition.model.TextDetection 24import com.amazonaws.services.rekognition.model.DetectTextResult 25import com.amazonaws.services.rekognition.model.DetectTextRequest 26import com.amazonaws.services.rekognition.AmazonRekognition 27import com.amazonaws.services.rekognition.model.Image 28import com.amazonaws.util.IOUtils 29 30// 画像をBitmapからBase64エンコードするために使う 31import android.graphics.Bitmap 32import android.graphics.BitmapFactory 33import java.io.ByteArrayOutputStream 34import android.util.Base64 35 36import com.amplifyframework.AmplifyException 37import com.amplifyframework.core.Amplify 38import com.amplifyframework.predictions.models.TextFormatType 39import com.amplifyframework.predictions.result.IdentifyTextResult 40import com.amplifyframework.api.aws.AWSApiPlugin 41import com.amplifyframework.auth.cognito.AWSCognitoAuthPlugin 42import com.amplifyframework.predictions.aws.AWSPredictionsPlugin 43 44 45typealias LumaListener = (luma: Double) -> Unit 46 47class MainActivity : AppCompatActivity() { 48 private var imageCapture: ImageCapture? = null 49 50 private lateinit var outputDirectory: File 51 private lateinit var cameraExecutor: ExecutorService 52 53 override fun onCreate(savedInstanceState: Bundle?) { 54 super.onCreate(savedInstanceState) 55 setContentView(R.layout.activity_main) 56 57 // amplify初期化 58 try { 59// Amplify.addPlugin(AWSDataStorePlugin()) 60// Amplify.addPlugin(AWSApiPlugin()) 61 Amplify.addPlugin(AWSCognitoAuthPlugin()) 62 Amplify.addPlugin(AWSPredictionsPlugin()) 63 Amplify.configure(applicationContext) 64 Log.i(TAG, "Initialized Amplify") 65 } catch (error: AmplifyException) { 66 Log.e(TAG, "Could not initialize Amplify", error) 67 } 68 69 // Request camera permissions 70 if (allPermissionsGranted()) { 71 startCamera() 72 } else { 73 ActivityCompat.requestPermissions( 74 this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS) 75 } 76 77 // Set up the listener for take photo button 78 camera_capture_button.setOnClickListener { takePhoto() } 79 80 outputDirectory = getOutputDirectory() 81 82 cameraExecutor = Executors.newSingleThreadExecutor() 83 } 84 85 private fun takePhoto() { 86 // Get a stable reference of the modifiable image capture use case 87 val imageCapture = imageCapture ?: return 88 89 // Create time-stamped output file to hold the image 90 // ここで画像ファイルを定義する。 91 val photoFile = File( 92 outputDirectory, 93 SimpleDateFormat(FILENAME_FORMAT, Locale.US 94 ).format(System.currentTimeMillis()) + ".jpg") 95 96 // Create output options object which contains file + metadata 97 val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile).build() 98 99 // Set up image capture listener, which is triggered after photo has 100 // been taken 101 imageCapture.takePicture( 102 outputOptions, ContextCompat.getMainExecutor(this), object : ImageCapture.OnImageSavedCallback { 103 override fun onError(exc: ImageCaptureException) { 104 Log.e(TAG, "Photo capture failed: ${exc.message}", exc) 105 } 106 107 override fun onImageSaved(output: ImageCapture.OutputFileResults) { 108 val savedUri = Uri.fromFile(photoFile) 109 val msg = "Photo capture succeeded: $savedUri" 110 Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show() 111 Log.d(TAG, msg) 112 113 // 画像のuriを文字列に変換し、先頭からfile://を削除する 114 val imageUri: String = savedUri.toString().removePrefix("file://") 115 Log.d(TAG, imageUri) 116 117 // 画像をbitmapへ 118 val imageBit: Bitmap = BitmapFactory.decodeFile(imageUri) 119 120** //ここでエラーが出る** 121 detectText(imageBit) 122 123 } 124 }) 125 } 126 // amplify利用 127 fun detectText(image: Bitmap) { 128 Amplify.Predictions.identify( 129 TextFormatType.PLAIN, image, 130 { result -> 131 val identifyResult = result as IdentifyTextResult 132 Log.i("MyAmplifyApp", "${identifyResult?.fullText}") 133 }, 134 { Log.e("MyAmplifyApp", "Identify text failed", it) } 135 ) 136 } 137 138 private fun startCamera() { 139 val cameraProviderFuture = ProcessCameraProvider.getInstance(this) 140 141 cameraProviderFuture.addListener(Runnable { 142 // Used to bind the lifecycle of cameras to the lifecycle owner 143 val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get() 144 145 // Preview 146 val preview = Preview.Builder() 147 .build() 148 .also { 149 it.setSurfaceProvider(viewFinder.surfaceProvider) 150 } 151 imageCapture = ImageCapture.Builder().build() 152 153 // Select back camera as a default 154 val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA 155 156 try { 157 // Unbind use cases before rebinding 158 cameraProvider.unbindAll() 159 160 // Bind use cases to camera 161 cameraProvider.bindToLifecycle( 162 this, cameraSelector, preview, imageCapture) 163 164 } catch(exc: Exception) { 165 Log.e(TAG, "Use case binding failed", exc) 166 } 167 168 }, ContextCompat.getMainExecutor(this)) 169 } 170 171 private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all { 172 ContextCompat.checkSelfPermission( 173 baseContext, it) == PackageManager.PERMISSION_GRANTED 174 } 175 176 private fun getOutputDirectory(): File { 177 val mediaDir = externalMediaDirs.firstOrNull()?.let { 178 File(it, resources.getString(R.string.app_name)).apply { mkdirs() } } 179 return if (mediaDir != null && mediaDir.exists()) 180 mediaDir else filesDir 181 } 182 183 override fun onDestroy() { 184 super.onDestroy() 185 cameraExecutor.shutdown() 186 } 187 188 override fun onRequestPermissionsResult( 189 requestCode: Int, permissions: Array<String>, grantResults: 190 IntArray) { 191 if (requestCode == REQUEST_CODE_PERMISSIONS) { 192 if (allPermissionsGranted()) { 193 startCamera() 194 } else { 195 Toast.makeText(this, 196 "Permissions not granted by the user.", 197 Toast.LENGTH_SHORT).show() 198 finish() 199 } 200 } 201 } 202 203 companion object { 204 private const val TAG = "CameraXBasic" 205 private const val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS" 206 private const val REQUEST_CODE_PERMISSIONS = 10 207 private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA) 208 } 209} 210 211
あなたの回答
tips
プレビュー