Skip to content

Commit a8c381f

Browse files
Release 26.3
1 parent 2f155ef commit a8c381f

5 files changed

Lines changed: 70 additions & 123 deletions

File tree

app/build.gradle

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ plugins {
55

66
android {
77
namespace 'com.aspose.barcode.cloud.demo_app'
8-
compileSdk 33
8+
compileSdk 35
99

1010
defaultConfig {
1111
applicationId "com.aspose.barcode.cloud.demo_app"
1212
minSdk 23
13-
targetSdk 33
13+
targetSdk 35
1414
versionCode 1
1515
versionName "1.0"
1616

@@ -23,28 +23,30 @@ android {
2323
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
2424
}
2525
}
26+
2627
compileOptions {
2728
sourceCompatibility JavaVersion.VERSION_1_8
2829
targetCompatibility JavaVersion.VERSION_1_8
2930
}
31+
3032
kotlinOptions {
3133
jvmTarget = '1.8'
32-
}
34+
}
35+
3336
buildFeatures {
37+
buildConfig true
3438
viewBinding true
3539
}
3640
}
3741

3842
dependencies {
39-
implementation fileTree(dir: "libs", include: ["*.jar"])
43+
implementation fileTree(dir: "libs", include: ["*.jar"])
4044
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
4145
implementation 'androidx.core:core-ktx:1.9.0'
4246
implementation 'androidx.appcompat:appcompat:1.6.0'
4347
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
4448
implementation 'com.aspose:aspose-barcode-cloud:26.3.0'
4549
implementation 'com.google.android.material:material:1.8.0'
46-
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
47-
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
4850
testImplementation 'junit:junit:4.13.2'
4951
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
5052
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'

app/src/main/AndroidManifest.xml

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,11 @@
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
33

44
<uses-permission android:name="android.permission.INTERNET" />
5-
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
6-
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
7-
android:maxSdkVersion="32" />
85

96
<queries>
10-
<!-- Camera -->
117
<intent>
128
<action android:name="android.media.action.IMAGE_CAPTURE" />
139
</intent>
14-
15-
<!-- Gallery -->
16-
<intent>
17-
<action android:name="android.intent.action.GET_CONTENT" />
18-
</intent>
1910
</queries>
2011

2112
<application
@@ -26,7 +17,8 @@
2617
android:roundIcon="@mipmap/ic_launcher_round"
2718
android:supportsRtl="true"
2819
android:theme="@style/AppTheme">
29-
<activity android:name=".MainActivity"
20+
<activity
21+
android:name=".MainActivity"
3022
android:exported="true">
3123
<intent-filter>
3224
<action android:name="android.intent.action.MAIN" />

app/src/main/java/com/aspose/barcode/cloud/demo_app/MainActivity.kt

Lines changed: 59 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,11 @@
2727

2828
package com.aspose.barcode.cloud.demo_app
2929

30-
import android.Manifest
3130
import android.app.Activity
3231
import android.content.Intent
33-
import android.content.pm.PackageManager
3432
import android.graphics.Bitmap
3533
import android.graphics.BitmapFactory
34+
import android.net.Uri
3635
import android.os.Bundle
3736
import android.provider.MediaStore
3837
import android.util.Size
@@ -42,47 +41,41 @@ import android.widget.ArrayAdapter
4241
import android.widget.EditText
4342
import android.widget.ImageView
4443
import android.widget.Spinner
44+
import androidx.activity.result.PickVisualMediaRequest
45+
import androidx.activity.result.contract.ActivityResultContracts
4546
import androidx.appcompat.app.AppCompatActivity
46-
import androidx.core.content.ContextCompat
47+
import androidx.core.view.ViewCompat
48+
import androidx.core.view.WindowCompat
49+
import androidx.core.view.WindowInsetsCompat
4750
import com.aspose.barcode.cloud.ApiClient
4851
import com.aspose.barcode.cloud.ApiException
4952
import com.aspose.barcode.cloud.api.GenerateApi
5053
import com.aspose.barcode.cloud.api.ScanApi
5154
import com.aspose.barcode.cloud.model.BarcodeImageFormat
52-
import com.aspose.barcode.cloud.model.BarcodeResponseList
5355
import com.aspose.barcode.cloud.model.EncodeBarcodeType
54-
import com.aspose.barcode.cloud.model.EncodeDataType
5556
import com.aspose.barcode.cloud.requests.GenerateRequestWrapper
5657
import com.aspose.barcode.cloud.requests.ScanMultipartRequestWrapper
5758
import com.google.android.material.snackbar.Snackbar
5859
import java.io.File
5960
import java.io.FileOutputStream
6061
import kotlin.math.floor
6162

62-
6363
class MainActivity : AppCompatActivity() {
6464
companion object {
65-
const val PERMISSION_REQUEST_CALLBACK_CODE = 1
66-
const val ACTION_GET_CONTENT_CALLBACK_CODE = 2
6765
const val ACTION_IMAGE_CAPTURE_CALLBACK_CODE = 3
6866

6967
private fun imageSize(width: Int, height: Int, maxSize: Int = 384): Size {
7068
val ratio = width.toFloat() / height
7169
if (ratio > 1) {
72-
// width > height
73-
// use width
7470
if (width < maxSize) {
75-
// do not resize
7671
return Size(width, height)
7772
}
7873

7974
val newHeight = floor(maxSize / ratio).toInt()
8075
return Size(maxSize, newHeight)
8176
}
82-
// width <= height
83-
// use height
77+
8478
if (height < maxSize) {
85-
// do not resize
8679
return Size(width, height)
8780
}
8881
val newWidth = floor(maxSize * ratio).toInt()
@@ -103,9 +96,19 @@ class MainActivity : AppCompatActivity() {
10396
private lateinit var generateApi: GenerateApi
10497
private val encodeTypes = EncodeBarcodeType.values().map { it.toString() }.sorted()
10598

99+
private val photoPickerLauncher =
100+
registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri ->
101+
if (uri == null) {
102+
return@registerForActivityResult
103+
}
104+
105+
recognizeSelectedImage(uri)
106+
}
107+
106108
override fun onCreate(savedInstanceState: Bundle?) {
107109
super.onCreate(savedInstanceState)
108110
setContentView(R.layout.activity_main)
111+
configureEdgeToEdge()
109112

110113
val client = ApiClient(
111114
"Client Id from https://dashboard.aspose.cloud/applications",
@@ -124,6 +127,18 @@ class MainActivity : AppCompatActivity() {
124127
barcodeImgView = findViewById(R.id.imageView)
125128
}
126129

130+
private fun configureEdgeToEdge() {
131+
WindowCompat.setDecorFitsSystemWindows(window, false)
132+
133+
val rootLayout = findViewById<View>(R.id.rootLayout)
134+
ViewCompat.setOnApplyWindowInsetsListener(rootLayout) { view, windowInsets ->
135+
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
136+
view.setPadding(insets.left, insets.top, insets.right, insets.bottom)
137+
windowInsets
138+
}
139+
ViewCompat.requestApplyInsets(rootLayout)
140+
}
141+
127142
private fun showErrorMessage(error: String) {
128143
Snackbar.make(findViewById(android.R.id.content), error, Snackbar.LENGTH_LONG).show()
129144
}
@@ -135,82 +150,39 @@ class MainActivity : AppCompatActivity() {
135150
barcodeTypeSpinner.setSelection(encodeTypes.indexOf("QR"))
136151
}
137152

138-
private fun requestPermissionAndPickFile(context: Activity) {
139-
if (ContextCompat.checkSelfPermission(
140-
context,
141-
Manifest.permission.READ_EXTERNAL_STORAGE
142-
) == PackageManager.PERMISSION_GRANTED
143-
) {
144-
pickFile()
145-
} else {
146-
requestPermissions(
147-
arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
148-
PERMISSION_REQUEST_CALLBACK_CODE
149-
)
150-
}
151-
}
152-
153+
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
154+
super.onActivityResult(requestCode, resultCode, data)
153155

154-
override fun onRequestPermissionsResult(
155-
requestCode: Int,
156-
permissions: Array<String>, grantResults: IntArray
157-
) {
158-
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
159-
when (requestCode) {
160-
PERMISSION_REQUEST_CALLBACK_CODE -> {
161-
// If request is cancelled, the result arrays are empty.
162-
if ((grantResults.isNotEmpty() &&
163-
grantResults[0] == PackageManager.PERMISSION_GRANTED)
164-
) {
165-
// Permission is granted. Continue the action or workflow
166-
// in your app.
167-
pickFile()
168-
} else {
169-
// Explain to the user that the feature is unavailable because
170-
// the features requires a permission that the user has denied.
171-
// At the same time, respect the user's decision. Don't link to
172-
// system settings in an effort to convince the user to change
173-
// their decision.
174-
showErrorMessage("Permission to read image denied")
175-
}
156+
if (requestCode == ACTION_IMAGE_CAPTURE_CALLBACK_CODE && resultCode == Activity.RESULT_OK) {
157+
val bmpImage = data?.extras?.get("data") as? Bitmap
158+
if (bmpImage == null) {
159+
showErrorMessage("No photo captured")
176160
return
177161
}
178-
179-
// Add other 'when' lines to check for other
180-
// permissions this app might request.
181-
else -> {
182-
// Ignore all other requests.
183-
}
162+
recognizeBarcode(bmpImage)
184163
}
185164
}
186165

187-
188-
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
189-
super.onActivityResult(requestCode, resultCode, data)
190-
191-
when (requestCode) {
192-
ACTION_GET_CONTENT_CALLBACK_CODE -> {
193-
if (resultCode == Activity.RESULT_OK) {
194-
val bytes = contentResolver.openInputStream(data?.data!!)!!.readBytes()
195-
val bmpImage = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
196-
recognizeBarcode(bmpImage)
197-
}
166+
private fun recognizeSelectedImage(uri: Uri) {
167+
try {
168+
val bytes = contentResolver.openInputStream(uri)?.use { it.readBytes() }
169+
if (bytes == null) {
170+
showErrorMessage("Unable to read selected image")
171+
return
198172
}
199173

200-
ACTION_IMAGE_CAPTURE_CALLBACK_CODE -> {
201-
if (resultCode == RESULT_OK) {
202-
val bmpImage = data?.extras?.get("data") as Bitmap
203-
recognizeBarcode(bmpImage)
204-
}
174+
val bmpImage = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
175+
if (bmpImage == null) {
176+
showErrorMessage("Unable to decode selected image")
177+
return
205178
}
206179

207-
else -> {
208-
showErrorMessage("No file selected")
209-
}
180+
recognizeBarcode(bmpImage)
181+
} catch (e: Exception) {
182+
showErrorMessage("Unable to read selected image")
210183
}
211184
}
212185

213-
214186
private fun recognizeBarcode(image: Bitmap) {
215187
try {
216188
val smallerBmp = reduceBitmapSize(image)
@@ -224,7 +196,7 @@ class MainActivity : AppCompatActivity() {
224196
smallerBmp.compress(Bitmap.CompressFormat.PNG, 100, output)
225197
}
226198

227-
val apiRequest = ScanMultipartRequestWrapper(tmpFile);
199+
val apiRequest = ScanMultipartRequestWrapper(tmpFile)
228200

229201
Thread {
230202
try {
@@ -259,9 +231,8 @@ class MainActivity : AppCompatActivity() {
259231
}
260232
}
261233
}.start()
262-
263-
} catch (e: java.lang.Exception) {
264-
showErrorMessage(e.message!!)
234+
} catch (e: Exception) {
235+
showErrorMessage(e.message ?: "Unknown error")
265236
}
266237
}
267238

@@ -276,25 +247,20 @@ class MainActivity : AppCompatActivity() {
276247
}
277248

278249
fun onBtnGenerateClick(@Suppress("UNUSED_PARAMETER") view: View) {
250+
val type = EncodeBarcodeType.fromValue(barcodeTypeSpinner.selectedItem.toString())
279251

280-
val type: EncodeBarcodeType = EncodeBarcodeType.fromValue(barcodeTypeSpinner.selectedItem.toString())
281-
282-
val genRequest = GenerateRequestWrapper(
283-
type, barcodeTextEdit.text.toString());
284-
285-
genRequest.imageFormat = BarcodeImageFormat.PNG;
252+
val genRequest = GenerateRequestWrapper(type, barcodeTextEdit.text.toString())
253+
genRequest.imageFormat = BarcodeImageFormat.PNG
286254
genRequest.imageHeight = barcodeImgView.measuredHeight.toFloat()
287255
genRequest.imageWidth = barcodeImgView.measuredWidth.toFloat()
288256

289-
290257
Thread {
291258
try {
292-
val generated: File? = generateApi.generate(genRequest);
259+
val generated = generateApi.generate(genRequest)
293260
runOnUiThread {
294261
val bitmap = BitmapFactory.decodeFile(generated!!.absolutePath)
295262
barcodeImgView.setImageBitmap(bitmap)
296263
}
297-
298264
} catch (e: ApiException) {
299265
runOnUiThread {
300266
var message = e.message + ": " + e.details
@@ -319,21 +285,8 @@ class MainActivity : AppCompatActivity() {
319285
}
320286

321287
fun onBtnSelectImageClick(@Suppress("UNUSED_PARAMETER") view: View) {
322-
requestPermissionAndPickFile(this)
323-
}
324-
325-
private fun pickFile() {
326-
val getContentIntent = Intent(Intent.ACTION_GET_CONTENT)
327-
getContentIntent.type = "image/*"
328-
getContentIntent.addCategory(Intent.CATEGORY_OPENABLE)
329-
try {
330-
startActivityForResult(
331-
Intent.createChooser(getContentIntent, "Select an Image to Recognize"),
332-
ACTION_GET_CONTENT_CALLBACK_CODE
333-
)
334-
} catch (ex: java.lang.Exception) {
335-
showErrorMessage("Unable to start file selector")
336-
}
337-
288+
photoPickerLauncher.launch(
289+
PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly)
290+
)
338291
}
339292
}

app/src/main/res/layout/activity_main.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
33
xmlns:app="http://schemas.android.com/apk/res-auto"
44
xmlns:tools="http://schemas.android.com/tools"
5+
android:id="@+id/rootLayout"
56
android:layout_width="match_parent"
67
android:layout_height="match_parent"
78
tools:context=".MainActivity">

gradle.properties

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,5 @@ kotlin.code.style=official
2121
# resources declared in the library itself and none from the library's dependencies,
2222
# thereby reducing the size of the R class for that library
2323
android.nonTransitiveRClass=true
24-
android.defaults.buildfeatures.buildconfig=true
2524
android.nonFinalResIds=false
2625
org.gradle.configuration-cache=true

0 commit comments

Comments
 (0)