Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RMET-2761 OSBarcodeLib-Android - Scan Instructions and Scan Button #7

Merged
merged 14 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ The changes documented here do not include those from the original repository.

## [Unreleased]

### 16-11-2023
Android - Implement Scan Button (https://outsystemsrd.atlassian.net/browse/RMET-2762)

### 15-11-2023
Android - Implement Scan Instructions (https://outsystemsrd.atlassian.net/browse/RMET-2761)

### 14-11-2023
Android - Implement Torch Button to settings (https://outsystemsrd.atlassian.net/browse/RMET-2759)

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.outsystems</groupId>
<artifactId>osbarcode-android</artifactId>
<version>0.0.20</version>
<version>0.0.23</version>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ data class OSBARCScanParameters(
val scanInstructions: String?,
val cameraDirection: Int?,
val scanOrientation: Int?,
val scanButton: Boolean?,
val scanText: String?,
val scanButton: Boolean,
val scanText: String,
val hint: Int?,
val androidScanningLibrary: String?
) : Serializable
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ import androidx.compose.ui.unit.sp
fun CameraPermissionRequiredDialog(
onDismissRequest: () -> Unit,
onConfirmation: () -> Unit,
permissionGiven: Boolean,
shouldShowDialog: Boolean,
dialogTitle: String,
dialogText: String,
confirmButtonText: String,
dismissButtonText: String
) {
if (shouldShowDialog) {
if (!permissionGiven && shouldShowDialog) {
AlertDialog(
title = {
Text(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,29 +23,37 @@ import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Clear
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.content.ContextCompat
import com.outsystems.plugins.barcode.R
import com.outsystems.plugins.barcode.controller.OSBARCBarcodeAnalyzer
import com.outsystems.plugins.barcode.controller.OSBARCScanLibraryFactory
import com.outsystems.plugins.barcode.controller.helper.OSBARCMLKitHelper
import com.outsystems.plugins.barcode.controller.helper.OSBARCZXingHelper
import com.outsystems.plugins.barcode.model.OSBARCError
import com.outsystems.plugins.barcode.model.OSBARCScanParameters
import com.outsystems.plugins.barcode.view.ui.theme.BarcodeScannerTheme
import com.outsystems.plugins.barcode.view.ui.theme.CustomGray
import com.outsystems.plugins.barcode.R
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to make sure this compiles on MABS because because the R class won't always be under this package.
For instance, on camera, this was the solution:
https://github.com/OutSystems/OSCameraLib-Android/blob/ae2c03c57c82cf8fe852a23a099fc273bb6f2651/src/main/kotlin/com/outsystems/plugins/camera/view/ImageEditorView.kt#L99

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a good point. However, since this is the Android library, the path to the package of the R class will always be the same - import com.outsystems.plugins.barcode.R. Moreover, it is safer to access a resource directly through the R class than using a getResource function based on the resource's id, that may not exist.


/**
* This class is responsible for implementing the UI of the scanning screen using Jetpack Compose.
Expand All @@ -57,6 +65,7 @@ class OSBARCScannerActivity : ComponentActivity() {
private lateinit var selector: CameraSelector
private var permissionRequestCount = 0
private var showDialog by mutableStateOf(false)
private var scanning = true

companion object {
private const val SCAN_SUCCESS_RESULT_CODE = -1
Expand All @@ -74,6 +83,7 @@ class OSBARCScannerActivity : ComponentActivity() {
actionBar?.hide()

val parameters = intent.extras?.getSerializable(SCAN_PARAMETERS) as OSBARCScanParameters
scanning = !parameters.scanButton
selector = CameraSelector.Builder()
.requireLensFacing(if (parameters.cameraDirection == CAM_DIRECTION_FRONT) CameraSelector.LENS_FACING_FRONT else CameraSelector.LENS_FACING_BACK)
.build()
Expand Down Expand Up @@ -119,26 +129,25 @@ class OSBARCScannerActivity : ComponentActivity() {
}
}

if (!permissionGiven) {
CameraPermissionRequiredDialog(
onDismissRequest = {
this.setResult(OSBARCError.CAMERA_PERMISSION_DENIED_ERROR.code)
this.finish()
},
onConfirmation = {
val intent = Intent().apply {
action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
data = Uri.fromParts("package", context.packageName, null)
}
context.startActivity(intent)
},
shouldShowDialog = showDialog,
dialogTitle = "Camera Access Not Enabled",
dialogText = "To continue, please go to the Settings app and enable it.",
confirmButtonText = "Settings",
dismissButtonText = "Ok"
)
}
CameraPermissionRequiredDialog(
onDismissRequest = {
this.setResult(OSBARCError.CAMERA_PERMISSION_DENIED_ERROR.code)
this.finish()
},
onConfirmation = {
val intent = Intent().apply {
action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
data = Uri.fromParts("package", context.packageName, null)
}
context.startActivity(intent)
},
permissionGiven = permissionGiven,
shouldShowDialog = showDialog,
dialogTitle = "Camera Access Not Enabled",
dialogText = "To continue, please go to the Settings app and enable it.",
confirmButtonText = "Settings",
dismissButtonText = "Ok"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a thought.
Could theses strings be moved into the res/strings.xml file? 🤔
I'm not sure though.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a good point. I believe we can do that when we tackle dynamic values for these fields, using different Locales.

)

// rest of the UI
val cameraProviderFuture = remember {
Expand Down Expand Up @@ -174,14 +183,10 @@ class OSBARCScannerActivity : ComponentActivity() {
OSBARCMLKitHelper()
),
{ result ->
val resultIntent = Intent()
resultIntent.putExtra(SCAN_RESULT, result)
setResult(SCAN_SUCCESS_RESULT_CODE, resultIntent)
finish()
processReadSuccess(result)
},
{
setResult(it.code)
finish()
processReadError(it)
}
)
)
Expand All @@ -202,9 +207,59 @@ class OSBARCScannerActivity : ComponentActivity() {
modifier = Modifier.fillMaxSize()
)

// close button
Button(
onClick = {
setResult(OSBARCError.SCAN_CANCELLED_ERROR.code)
finish()
},
colors = ButtonDefaults.buttonColors(
containerColor = Color.Transparent
),
modifier = Modifier.align(Alignment.TopEnd)
) {
Icon(
imageVector = Icons.Default.Clear,
contentDescription = null,
tint = CustomGray
)
}

// flashlight button
if (camera.cameraInfo.hasFlashUnit()) {
TorchButton()
}

// text with scan instructions
if (!parameters.scanInstructions.isNullOrEmpty()) {
Text(
text = parameters.scanInstructions,
modifier = Modifier.align(Alignment.Center),
color = Color.White,
textAlign = TextAlign.Center
)
}

// scan button to turn on scanning when used
if (parameters.scanButton) {
Button(
onClick = {
scanning = true
},
colors = ButtonDefaults.buttonColors(
containerColor = Color.DarkGray
),
shape = RectangleShape,
modifier = Modifier.align(Alignment.BottomCenter)
) {
Text(
text = parameters.scanText,
color = Color.White,
textAlign = TextAlign.Center
)
}
}

}
}

Expand Down Expand Up @@ -243,4 +298,22 @@ class OSBARCScannerActivity : ComponentActivity() {
) == PackageManager.PERMISSION_GRANTED
}

private fun processReadSuccess(result: String) {
// we only want to process the scan result if scanning is active
if (scanning) {
val resultIntent = Intent()
resultIntent.putExtra(SCAN_RESULT, result)
setResult(SCAN_SUCCESS_RESULT_CODE, resultIntent)
finish()
}
}

private fun processReadError(error: OSBARCError) {
// we only want to process the scan result if scanning is active
alexgerardojacinto marked this conversation as resolved.
Show resolved Hide resolved
if (scanning) {
setResult(error.code)
finish()
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ val Pink80 = Color(0xFFEFB8C8)

val Purple40 = Color(0xFF6650a4)
val PurpleGrey40 = Color(0xFF625b71)
val Pink40 = Color(0xFF7D5260)
val Pink40 = Color(0xFF7D5260)

val CustomGray = Color(0xFFB3BAC4)