From 2f155ef5ee0de66cca0caf595e72786b8288d71f Mon Sep 17 00:00:00 2001 From: Timur Baiguskarov Date: Wed, 18 Mar 2026 13:24:53 +0500 Subject: [PATCH 1/3] Release 26.3 --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index a6dd736..78e8569 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -41,7 +41,7 @@ implementation fileTree(dir: "libs", include: ["*.jar"]) implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' - implementation 'com.aspose:aspose-barcode-cloud:26.2.0' + implementation 'com.aspose:aspose-barcode-cloud:26.3.0' implementation 'com.google.android.material:material:1.8.0' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' From a8c381f62a2728840b23c49c4b3280e8f13f8f7f Mon Sep 17 00:00:00 2001 From: Timur Baiguskarov Date: Thu, 19 Mar 2026 15:23:13 +0500 Subject: [PATCH 2/3] Release 26.3 --- app/build.gradle | 14 +- app/src/main/AndroidManifest.xml | 12 +- .../barcode/cloud/demo_app/MainActivity.kt | 165 +++++++----------- app/src/main/res/layout/activity_main.xml | 1 + gradle.properties | 1 - 5 files changed, 70 insertions(+), 123 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 78e8569..60eddc0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,12 +5,12 @@ plugins { android { namespace 'com.aspose.barcode.cloud.demo_app' - compileSdk 33 + compileSdk 35 defaultConfig { applicationId "com.aspose.barcode.cloud.demo_app" minSdk 23 - targetSdk 33 + targetSdk 35 versionCode 1 versionName "1.0" @@ -23,28 +23,30 @@ android { proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + kotlinOptions { jvmTarget = '1.8' -} + } + buildFeatures { + buildConfig true viewBinding true } } dependencies { -implementation fileTree(dir: "libs", include: ["*.jar"]) + implementation fileTree(dir: "libs", include: ["*.jar"]) implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'com.aspose:aspose-barcode-cloud:26.3.0' implementation 'com.google.android.material:material:1.8.0' - androidTestImplementation 'androidx.test.ext:junit:1.1.5' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 15d49ab..4268a9f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,20 +2,11 @@ - - - - - - - - - diff --git a/app/src/main/java/com/aspose/barcode/cloud/demo_app/MainActivity.kt b/app/src/main/java/com/aspose/barcode/cloud/demo_app/MainActivity.kt index 57ac0eb..c66ab39 100644 --- a/app/src/main/java/com/aspose/barcode/cloud/demo_app/MainActivity.kt +++ b/app/src/main/java/com/aspose/barcode/cloud/demo_app/MainActivity.kt @@ -27,12 +27,11 @@ package com.aspose.barcode.cloud.demo_app -import android.Manifest import android.app.Activity import android.content.Intent -import android.content.pm.PackageManager import android.graphics.Bitmap import android.graphics.BitmapFactory +import android.net.Uri import android.os.Bundle import android.provider.MediaStore import android.util.Size @@ -42,16 +41,18 @@ import android.widget.ArrayAdapter import android.widget.EditText import android.widget.ImageView import android.widget.Spinner +import androidx.activity.result.PickVisualMediaRequest +import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity -import androidx.core.content.ContextCompat +import androidx.core.view.ViewCompat +import androidx.core.view.WindowCompat +import androidx.core.view.WindowInsetsCompat import com.aspose.barcode.cloud.ApiClient import com.aspose.barcode.cloud.ApiException import com.aspose.barcode.cloud.api.GenerateApi import com.aspose.barcode.cloud.api.ScanApi import com.aspose.barcode.cloud.model.BarcodeImageFormat -import com.aspose.barcode.cloud.model.BarcodeResponseList import com.aspose.barcode.cloud.model.EncodeBarcodeType -import com.aspose.barcode.cloud.model.EncodeDataType import com.aspose.barcode.cloud.requests.GenerateRequestWrapper import com.aspose.barcode.cloud.requests.ScanMultipartRequestWrapper import com.google.android.material.snackbar.Snackbar @@ -59,30 +60,22 @@ import java.io.File import java.io.FileOutputStream import kotlin.math.floor - class MainActivity : AppCompatActivity() { companion object { - const val PERMISSION_REQUEST_CALLBACK_CODE = 1 - const val ACTION_GET_CONTENT_CALLBACK_CODE = 2 const val ACTION_IMAGE_CAPTURE_CALLBACK_CODE = 3 private fun imageSize(width: Int, height: Int, maxSize: Int = 384): Size { val ratio = width.toFloat() / height if (ratio > 1) { - // width > height - // use width if (width < maxSize) { - // do not resize return Size(width, height) } val newHeight = floor(maxSize / ratio).toInt() return Size(maxSize, newHeight) } - // width <= height - // use height + if (height < maxSize) { - // do not resize return Size(width, height) } val newWidth = floor(maxSize * ratio).toInt() @@ -103,9 +96,19 @@ class MainActivity : AppCompatActivity() { private lateinit var generateApi: GenerateApi private val encodeTypes = EncodeBarcodeType.values().map { it.toString() }.sorted() + private val photoPickerLauncher = + registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri -> + if (uri == null) { + return@registerForActivityResult + } + + recognizeSelectedImage(uri) + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) + configureEdgeToEdge() val client = ApiClient( "Client Id from https://dashboard.aspose.cloud/applications", @@ -124,6 +127,18 @@ class MainActivity : AppCompatActivity() { barcodeImgView = findViewById(R.id.imageView) } + private fun configureEdgeToEdge() { + WindowCompat.setDecorFitsSystemWindows(window, false) + + val rootLayout = findViewById(R.id.rootLayout) + ViewCompat.setOnApplyWindowInsetsListener(rootLayout) { view, windowInsets -> + val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) + view.setPadding(insets.left, insets.top, insets.right, insets.bottom) + windowInsets + } + ViewCompat.requestApplyInsets(rootLayout) + } + private fun showErrorMessage(error: String) { Snackbar.make(findViewById(android.R.id.content), error, Snackbar.LENGTH_LONG).show() } @@ -135,82 +150,39 @@ class MainActivity : AppCompatActivity() { barcodeTypeSpinner.setSelection(encodeTypes.indexOf("QR")) } - private fun requestPermissionAndPickFile(context: Activity) { - if (ContextCompat.checkSelfPermission( - context, - Manifest.permission.READ_EXTERNAL_STORAGE - ) == PackageManager.PERMISSION_GRANTED - ) { - pickFile() - } else { - requestPermissions( - arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), - PERMISSION_REQUEST_CALLBACK_CODE - ) - } - } - + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) - override fun onRequestPermissionsResult( - requestCode: Int, - permissions: Array, grantResults: IntArray - ) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults) - when (requestCode) { - PERMISSION_REQUEST_CALLBACK_CODE -> { - // If request is cancelled, the result arrays are empty. - if ((grantResults.isNotEmpty() && - grantResults[0] == PackageManager.PERMISSION_GRANTED) - ) { - // Permission is granted. Continue the action or workflow - // in your app. - pickFile() - } else { - // Explain to the user that the feature is unavailable because - // the features requires a permission that the user has denied. - // At the same time, respect the user's decision. Don't link to - // system settings in an effort to convince the user to change - // their decision. - showErrorMessage("Permission to read image denied") - } + if (requestCode == ACTION_IMAGE_CAPTURE_CALLBACK_CODE && resultCode == Activity.RESULT_OK) { + val bmpImage = data?.extras?.get("data") as? Bitmap + if (bmpImage == null) { + showErrorMessage("No photo captured") return } - - // Add other 'when' lines to check for other - // permissions this app might request. - else -> { - // Ignore all other requests. - } + recognizeBarcode(bmpImage) } } - - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - - when (requestCode) { - ACTION_GET_CONTENT_CALLBACK_CODE -> { - if (resultCode == Activity.RESULT_OK) { - val bytes = contentResolver.openInputStream(data?.data!!)!!.readBytes() - val bmpImage = BitmapFactory.decodeByteArray(bytes, 0, bytes.size) - recognizeBarcode(bmpImage) - } + private fun recognizeSelectedImage(uri: Uri) { + try { + val bytes = contentResolver.openInputStream(uri)?.use { it.readBytes() } + if (bytes == null) { + showErrorMessage("Unable to read selected image") + return } - ACTION_IMAGE_CAPTURE_CALLBACK_CODE -> { - if (resultCode == RESULT_OK) { - val bmpImage = data?.extras?.get("data") as Bitmap - recognizeBarcode(bmpImage) - } + val bmpImage = BitmapFactory.decodeByteArray(bytes, 0, bytes.size) + if (bmpImage == null) { + showErrorMessage("Unable to decode selected image") + return } - else -> { - showErrorMessage("No file selected") - } + recognizeBarcode(bmpImage) + } catch (e: Exception) { + showErrorMessage("Unable to read selected image") } } - private fun recognizeBarcode(image: Bitmap) { try { val smallerBmp = reduceBitmapSize(image) @@ -224,7 +196,7 @@ class MainActivity : AppCompatActivity() { smallerBmp.compress(Bitmap.CompressFormat.PNG, 100, output) } - val apiRequest = ScanMultipartRequestWrapper(tmpFile); + val apiRequest = ScanMultipartRequestWrapper(tmpFile) Thread { try { @@ -259,9 +231,8 @@ class MainActivity : AppCompatActivity() { } } }.start() - - } catch (e: java.lang.Exception) { - showErrorMessage(e.message!!) + } catch (e: Exception) { + showErrorMessage(e.message ?: "Unknown error") } } @@ -276,25 +247,20 @@ class MainActivity : AppCompatActivity() { } fun onBtnGenerateClick(@Suppress("UNUSED_PARAMETER") view: View) { + val type = EncodeBarcodeType.fromValue(barcodeTypeSpinner.selectedItem.toString()) - val type: EncodeBarcodeType = EncodeBarcodeType.fromValue(barcodeTypeSpinner.selectedItem.toString()) - - val genRequest = GenerateRequestWrapper( - type, barcodeTextEdit.text.toString()); - - genRequest.imageFormat = BarcodeImageFormat.PNG; + val genRequest = GenerateRequestWrapper(type, barcodeTextEdit.text.toString()) + genRequest.imageFormat = BarcodeImageFormat.PNG genRequest.imageHeight = barcodeImgView.measuredHeight.toFloat() genRequest.imageWidth = barcodeImgView.measuredWidth.toFloat() - Thread { try { - val generated: File? = generateApi.generate(genRequest); + val generated = generateApi.generate(genRequest) runOnUiThread { val bitmap = BitmapFactory.decodeFile(generated!!.absolutePath) barcodeImgView.setImageBitmap(bitmap) } - } catch (e: ApiException) { runOnUiThread { var message = e.message + ": " + e.details @@ -319,21 +285,8 @@ class MainActivity : AppCompatActivity() { } fun onBtnSelectImageClick(@Suppress("UNUSED_PARAMETER") view: View) { - requestPermissionAndPickFile(this) - } - - private fun pickFile() { - val getContentIntent = Intent(Intent.ACTION_GET_CONTENT) - getContentIntent.type = "image/*" - getContentIntent.addCategory(Intent.CATEGORY_OPENABLE) - try { - startActivityForResult( - Intent.createChooser(getContentIntent, "Select an Image to Recognize"), - ACTION_GET_CONTENT_CALLBACK_CODE - ) - } catch (ex: java.lang.Exception) { - showErrorMessage("Unable to start file selector") - } - + photoPickerLauncher.launch( + PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly) + ) } } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index bd82711..90dfa53 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -2,6 +2,7 @@ diff --git a/gradle.properties b/gradle.properties index 2e49100..1ee40ba 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,6 +21,5 @@ kotlin.code.style=official # resources declared in the library itself and none from the library's dependencies, # thereby reducing the size of the R class for that library android.nonTransitiveRClass=true -android.defaults.buildfeatures.buildconfig=true android.nonFinalResIds=false org.gradle.configuration-cache=true From dbc285f19b1b26733572149617564126bd218d14 Mon Sep 17 00:00:00 2001 From: Denis Averin Date: Mon, 23 Mar 2026 20:46:04 +0700 Subject: [PATCH 3/3] Update Android build --- app/build.gradle | 47 ++++++++----------- .../barcode/cloud/demo_app/MainActivity.kt | 39 +++++++-------- build.gradle | 6 +-- gradle.properties | 1 - gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle | 2 +- 6 files changed, 44 insertions(+), 53 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 60eddc0..7e0ab8e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,53 +1,46 @@ plugins { id 'com.android.application' - id 'org.jetbrains.kotlin.android' } android { - namespace 'com.aspose.barcode.cloud.demo_app' - compileSdk 35 + namespace = 'com.aspose.barcode.cloud.demo_app' + compileSdk = 36 defaultConfig { - applicationId "com.aspose.barcode.cloud.demo_app" - minSdk 23 - targetSdk 35 - versionCode 1 - versionName "1.0" + applicationId = "com.aspose.barcode.cloud.demo_app" + minSdk = 23 + targetSdk = 36 + versionCode = 1 + versionName = "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { - minifyEnabled false + minifyEnabled = false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = '1.8' + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } buildFeatures { - buildConfig true - viewBinding true + buildConfig = true + viewBinding = true } } dependencies { - implementation fileTree(dir: "libs", include: ["*.jar"]) - implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.0' - implementation 'androidx.constraintlayout:constraintlayout:2.1.4' - implementation 'com.aspose:aspose-barcode-cloud:26.3.0' - implementation 'com.google.android.material:material:1.8.0' + implementation 'androidx.core:core-ktx:1.18.0' + implementation 'androidx.appcompat:appcompat:1.7.1' + implementation 'androidx.constraintlayout:constraintlayout:2.2.1' + implementation 'com.aspose:aspose-barcode-cloud:26.3.2' + implementation 'com.google.android.material:material:1.13.0' testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.5' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' + androidTestImplementation 'androidx.test.ext:junit:1.3.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.7.0' } diff --git a/app/src/main/java/com/aspose/barcode/cloud/demo_app/MainActivity.kt b/app/src/main/java/com/aspose/barcode/cloud/demo_app/MainActivity.kt index c66ab39..353b871 100644 --- a/app/src/main/java/com/aspose/barcode/cloud/demo_app/MainActivity.kt +++ b/app/src/main/java/com/aspose/barcode/cloud/demo_app/MainActivity.kt @@ -44,6 +44,7 @@ import android.widget.Spinner import androidx.activity.result.PickVisualMediaRequest import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity +import androidx.core.os.BundleCompat import androidx.core.view.ViewCompat import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsCompat @@ -59,11 +60,10 @@ import com.google.android.material.snackbar.Snackbar import java.io.File import java.io.FileOutputStream import kotlin.math.floor +import androidx.core.graphics.scale class MainActivity : AppCompatActivity() { companion object { - const val ACTION_IMAGE_CAPTURE_CALLBACK_CODE = 3 - private fun imageSize(width: Int, height: Int, maxSize: Int = 384): Size { val ratio = width.toFloat() / height if (ratio > 1) { @@ -84,7 +84,7 @@ class MainActivity : AppCompatActivity() { private fun reduceBitmapSize(image: Bitmap): Bitmap { val newSize = imageSize(image.width, image.height) - return Bitmap.createScaledBitmap(image, newSize.width, newSize.height, true) + return image.scale(newSize.width, newSize.height) } } @@ -94,7 +94,21 @@ class MainActivity : AppCompatActivity() { private lateinit var scanApi: ScanApi private lateinit var generateApi: GenerateApi - private val encodeTypes = EncodeBarcodeType.values().map { it.toString() }.sorted() + private val encodeTypes = EncodeBarcodeType.entries.map { it.toString() }.sorted() + + private val cameraLauncher = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + if (result.resultCode == Activity.RESULT_OK) { + val bmpImage = result.data?.extras?.let { + BundleCompat.getParcelable(it, "data", Bitmap::class.java) + } + if (bmpImage == null) { + showErrorMessage("No photo captured") + return@registerForActivityResult + } + recognizeBarcode(bmpImage) + } + } private val photoPickerLauncher = registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri -> @@ -150,19 +164,6 @@ class MainActivity : AppCompatActivity() { barcodeTypeSpinner.setSelection(encodeTypes.indexOf("QR")) } - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - - if (requestCode == ACTION_IMAGE_CAPTURE_CALLBACK_CODE && resultCode == Activity.RESULT_OK) { - val bmpImage = data?.extras?.get("data") as? Bitmap - if (bmpImage == null) { - showErrorMessage("No photo captured") - return - } - recognizeBarcode(bmpImage) - } - } - private fun recognizeSelectedImage(uri: Uri) { try { val bytes = contentResolver.openInputStream(uri)?.use { it.readBytes() } @@ -178,7 +179,7 @@ class MainActivity : AppCompatActivity() { } recognizeBarcode(bmpImage) - } catch (e: Exception) { + } catch (_: Exception) { showErrorMessage("Unable to read selected image") } } @@ -280,7 +281,7 @@ class MainActivity : AppCompatActivity() { fun onBtnTakePhotoClick(@Suppress("UNUSED_PARAMETER") view: View) { val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) if (takePictureIntent.resolveActivity(packageManager) != null) { - startActivityForResult(takePictureIntent, ACTION_IMAGE_CAPTURE_CALLBACK_CODE) + cameraLauncher.launch(takePictureIntent) } } diff --git a/build.gradle b/build.gradle index 1f1e200..49d1228 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,5 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id 'com.android.application' version '8.7.3' apply false - id 'com.android.library' version '8.7.3' apply false - id 'org.jetbrains.kotlin.android' version '2.1.0' apply false + id 'com.android.application' version '9.1.0' apply false + id 'com.android.library' version '9.1.0' apply false } -ext.kotlin_version = '2.1.0' diff --git a/gradle.properties b/gradle.properties index 1ee40ba..29c7133 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,5 +21,4 @@ kotlin.code.style=official # resources declared in the library itself and none from the library's dependencies, # thereby reducing the size of the R class for that library android.nonTransitiveRClass=true -android.nonFinalResIds=false org.gradle.configuration-cache=true diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index dd1a159..8eb3695 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Fri Jan 27 19:13:42 YEKT 2023 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/settings.gradle b/settings.gradle index 6c0da42..6bfe3ea 100644 --- a/settings.gradle +++ b/settings.gradle @@ -10,7 +10,7 @@ dependencyResolutionManagement { repositories { google() mavenCentral() - maven { url 'https://releases.aspose.cloud/java/repo/' } + maven { url = 'https://releases.aspose.cloud/java/repo/' } } }