22{ {> licenseInfo} }
33package { {invokerPackage} }
44
5- import android.Manifest
65import android.app.Activity
76import android.content.Intent
8- import android.content.pm.PackageManager
97import android.graphics.Bitmap
108import android.graphics.BitmapFactory
9+ import android.net.Uri
1110import android.os.Bundle
1211import android.provider.MediaStore
1312import android.util.Size
@@ -17,47 +16,41 @@ import android.widget.ArrayAdapter
1716import android.widget.EditText
1817import android.widget.ImageView
1918import android.widget.Spinner
19+ import androidx.activity.result.PickVisualMediaRequest
20+ import androidx.activity.result.contract.ActivityResultContracts
2021import androidx.appcompat.app.AppCompatActivity
21- import androidx.core.content.ContextCompat
22+ import androidx.core.os.BundleCompat
23+ import androidx.core.view.ViewCompat
24+ import androidx.core.view.WindowCompat
25+ import androidx.core.view.WindowInsetsCompat
2226import com.aspose.barcode.cloud.ApiClient
2327import com.aspose.barcode.cloud.ApiException
2428import com.aspose.barcode.cloud.api.GenerateApi
2529import com.aspose.barcode.cloud.api.ScanApi
2630import com.aspose.barcode.cloud.model.BarcodeImageFormat
27- import com.aspose.barcode.cloud.model.BarcodeResponseList
2831import com.aspose.barcode.cloud.model.EncodeBarcodeType
29- import com.aspose.barcode.cloud.model.EncodeDataType
3032import com.aspose.barcode.cloud.requests.GenerateRequestWrapper
3133import com.aspose.barcode.cloud.requests.ScanMultipartRequestWrapper
3234import com.google.android.material.snackbar.Snackbar
3335import java.io.File
3436import java.io.FileOutputStream
3537import kotlin.math.floor
36-
38+ import androidx.core.graphics.scale
3739
3840class MainActivity : AppCompatActivity() {
3941 companion object {
40- const val PERMISSION_REQUEST_CALLBACK_CODE = 1
41- const val ACTION_GET_CONTENT_CALLBACK_CODE = 2
42- const val ACTION_IMAGE_CAPTURE_CALLBACK_CODE = 3
43-
4442 private fun imageSize(width: Int, height: Int, maxSize: Int = 384): Size {
4543 val ratio = width.toFloat() / height
4644 if (ratio > 1) {
47- // width > height
48- // use width
4945 if (width < maxSize) {
50- // do not resize
5146 return Size(width, height)
5247 }
5348
5449 val newHeight = floor(maxSize / ratio).toInt()
5550 return Size(maxSize, newHeight)
5651 }
57- // width <= height
58- // use height
52+
5953 if (height < maxSize) {
60- // do not resize
6154 return Size(width, height)
6255 }
6356 val newWidth = floor(maxSize * ratio).toInt()
@@ -66,7 +59,7 @@ class MainActivity : AppCompatActivity() {
6659
6760 private fun reduceBitmapSize(image: Bitmap): Bitmap {
6861 val newSize = imageSize(image.width, image.height)
69- return Bitmap.createScaledBitmap(image, newSize.width, newSize.height, true )
62+ return image.scale( newSize.width, newSize.height)
7063 }
7164 }
7265
@@ -76,11 +69,35 @@ class MainActivity : AppCompatActivity() {
7669
7770 private lateinit var scanApi: ScanApi
7871 private lateinit var generateApi: GenerateApi
79- private val encodeTypes = EncodeBarcodeType.values().map { it.toString() } .sorted()
72+ private val encodeTypes = EncodeBarcodeType.entries.map { it.toString() } .sorted()
73+
74+ private val cameraLauncher =
75+ registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
76+ if (result.resultCode == Activity.RESULT_OK) {
77+ val bmpImage = result.data?.extras?.let {
78+ BundleCompat.getParcelable(it, " data" , Bitmap::class.java)
79+ }
80+ if (bmpImage == null) {
81+ showErrorMessage(" No photo captured" )
82+ return@registerForActivityResult
83+ }
84+ recognizeBarcode(bmpImage)
85+ }
86+ }
87+
88+ private val photoPickerLauncher =
89+ registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri ->
90+ if (uri == null) {
91+ return@registerForActivityResult
92+ }
93+
94+ recognizeSelectedImage(uri)
95+ }
8096
8197 override fun onCreate(savedInstanceState: Bundle?) {
8298 super.onCreate(savedInstanceState)
8399 setContentView(R.layout.activity_main)
100+ configureEdgeToEdge()
84101
85102 val client = ApiClient(
86103 " Client Id from https://dashboard.aspose.cloud/applications" ,
@@ -99,6 +116,18 @@ class MainActivity : AppCompatActivity() {
99116 barcodeImgView = findViewById(R.id.imageView)
100117 }
101118
119+ private fun configureEdgeToEdge() {
120+ WindowCompat.setDecorFitsSystemWindows(window, false )
121+
122+ val rootLayout = findViewById< View> (R.id.rootLayout)
123+ ViewCompat.setOnApplyWindowInsetsListener(rootLayout) { view, windowInsets ->
124+ val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
125+ view.setPadding(insets.left, insets.top, insets.right, insets.bottom)
126+ windowInsets
127+ }
128+ ViewCompat.requestApplyInsets(rootLayout)
129+ }
130+
102131 private fun showErrorMessage(error: String) {
103132 Snackbar.make(findViewById(android.R.id.content), error, Snackbar.LENGTH_LONG).show()
104133 }
@@ -110,82 +139,26 @@ class MainActivity : AppCompatActivity() {
110139 barcodeTypeSpinner.setSelection(encodeTypes.indexOf(" QR" ))
111140 }
112141
113- private fun requestPermissionAndPickFile(context: Activity) {
114- if (ContextCompat.checkSelfPermission(
115- context,
116- Manifest.permission.READ_EXTERNAL_STORAGE
117- ) == PackageManager.PERMISSION_GRANTED
118- ) {
119- pickFile()
120- } else {
121- requestPermissions(
122- arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
123- PERMISSION_REQUEST_CALLBACK_CODE
124- )
125- }
126- }
127-
128-
129- override fun onRequestPermissionsResult(
130- requestCode: Int,
131- permissions: Array<String >, grantResults: IntArray
132- ) {
133- super.onRequestPermissionsResult(requestCode, permissions, grantResults)
134- when (requestCode) {
135- PERMISSION_REQUEST_CALLBACK_CODE -> {
136- // If request is cancelled, the result arrays are empty.
137- if ((grantResults.isNotEmpty() &&
138- grantResults[0] == PackageManager.PERMISSION_GRANTED)
139- ) {
140- // Permission is granted. Continue the action or workflow
141- // in your app.
142- pickFile()
143- } else {
144- // Explain to the user that the feature is unavailable because
145- // the features requires a permission that the user has denied.
146- // At the same time, respect the user' s decision. Don' t link to
147- // system settings in an effort to convince the user to change
148- // their decision.
149- showErrorMessage(" Permission to read image denied" )
150- }
142+ private fun recognizeSelectedImage(uri: Uri) {
143+ try {
144+ val bytes = contentResolver.openInputStream(uri)?.use { it.readBytes() }
145+ if (bytes == null) {
146+ showErrorMessage(" Unable to read selected image" )
151147 return
152148 }
153149
154- // Add other 'when' lines to check for other
155- // permissions this app might request.
156- else -> {
157- // Ignore all other requests.
158- }
159- }
160- }
161-
162-
163- override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
164- super.onActivityResult(requestCode, resultCode, data)
165-
166- when (requestCode) {
167- ACTION_GET_CONTENT_CALLBACK_CODE -> {
168- if (resultCode == Activity.RESULT_OK) {
169- val bytes = contentResolver.openInputStream(data?.data!! )!! .readBytes()
170- val bmpImage = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
171- recognizeBarcode(bmpImage)
172- }
173- }
174-
175- ACTION_IMAGE_CAPTURE_CALLBACK_CODE -> {
176- if (resultCode == RESULT_OK) {
177- val bmpImage = data?.extras?.get(" data" ) as Bitmap
178- recognizeBarcode(bmpImage)
179- }
150+ val bmpImage = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
151+ if (bmpImage == null) {
152+ showErrorMessage(" Unable to decode selected image" )
153+ return
180154 }
181155
182- else -> {
183- showErrorMessage( " No file selected " )
184- }
156+ recognizeBarcode(bmpImage)
157+ } catch (_: Exception) {
158+ showErrorMessage( " Unable to read selected image " )
185159 }
186160 }
187161
188-
189162 private fun recognizeBarcode(image: Bitmap) {
190163 try {
191164 val smallerBmp = reduceBitmapSize(image)
@@ -199,7 +172,7 @@ class MainActivity : AppCompatActivity() {
199172 smallerBmp.compress(Bitmap.CompressFormat.PNG, 100, output)
200173 }
201174
202- val apiRequest = ScanMultipartRequestWrapper(tmpFile);
175+ val apiRequest = ScanMultipartRequestWrapper(tmpFile)
203176
204177 Thread {
205178 try {
@@ -234,9 +207,8 @@ class MainActivity : AppCompatActivity() {
234207 }
235208 }
236209 }.start()
237-
238- } catch (e: java.lang.Exception) {
239- showErrorMessage(e.message!! )
210+ } catch (e: Exception) {
211+ showErrorMessage(e.message ?: " Unknown error" )
240212 }
241213 }
242214
@@ -251,25 +223,20 @@ class MainActivity : AppCompatActivity() {
251223 }
252224
253225 fun onBtnGenerateClick(@Suppress("UNUSED_PARAMETER") view: View) {
226+ val type = EncodeBarcodeType.fromValue(barcodeTypeSpinner.selectedItem.toString())
254227
255- val type: EncodeBarcodeType = EncodeBarcodeType.fromValue(barcodeTypeSpinner.selectedItem.toString())
256-
257- val genRequest = GenerateRequestWrapper(
258- type, barcodeTextEdit.text.toString());
259-
260- genRequest.imageFormat = BarcodeImageFormat.PNG;
228+ val genRequest = GenerateRequestWrapper(type, barcodeTextEdit.text.toString())
229+ genRequest.imageFormat = BarcodeImageFormat.PNG
261230 genRequest.imageHeight = barcodeImgView.measuredHeight.toFloat()
262231 genRequest.imageWidth = barcodeImgView.measuredWidth.toFloat()
263232
264-
265233 Thread {
266234 try {
267- val generated: File? = generateApi.generate(genRequest);
235+ val generated = generateApi.generate(genRequest)
268236 runOnUiThread {
269237 val bitmap = BitmapFactory.decodeFile(generated!! .absolutePath)
270238 barcodeImgView.setImageBitmap(bitmap)
271239 }
272-
273240 } catch (e: ApiException) {
274241 runOnUiThread {
275242 var message = e.message + " : " + e.details
@@ -289,26 +256,13 @@ class MainActivity : AppCompatActivity() {
289256 fun onBtnTakePhotoClick(@Suppress("UNUSED_PARAMETER") view: View) {
290257 val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
291258 if (takePictureIntent.resolveActivity(packageManager) != null) {
292- startActivityForResult (takePictureIntent, ACTION_IMAGE_CAPTURE_CALLBACK_CODE )
259+ cameraLauncher.launch (takePictureIntent)
293260 }
294261 }
295262
296263 fun onBtnSelectImageClick(@Suppress("UNUSED_PARAMETER") view: View) {
297- requestPermissionAndPickFile(this)
298- }
299-
300- private fun pickFile() {
301- val getContentIntent = Intent(Intent.ACTION_GET_CONTENT)
302- getContentIntent.type = " image/*"
303- getContentIntent.addCategory(Intent.CATEGORY_OPENABLE)
304- try {
305- startActivityForResult(
306- Intent.createChooser(getContentIntent, " Select an Image to Recognize" ),
307- ACTION_GET_CONTENT_CALLBACK_CODE
308- )
309- } catch (ex: java.lang.Exception) {
310- showErrorMessage(" Unable to start file selector" )
311- }
312-
264+ photoPickerLauncher.launch(
265+ PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly)
266+ )
313267 }
314268}
0 commit comments