diff --git a/README.md b/README.md index 8a4d8995..2de9b5ea 100644 --- a/README.md +++ b/README.md @@ -18,27 +18,29 @@ There are two different flavors available on `jcenter()`: | V2 barcode model is used (possibly faster, more accurate) | currently V1 will be downloaded ```kotlin // bundled: -implementation("com.g00fy2.quickie:quickie-bundled:0.3.0") +implementation("com.g00fy2.quickie:quickie-bundled:0.3.1") // unbundled: -implementation("com.g00fy2.quickie:quickie-unbundled:0.3.0") +implementation("com.g00fy2.quickie:quickie-unbundled:0.3.1") ``` ## Quick Start To use the QR scanner simply register the `ScanQRCode()` ActivityResultContract together with a callback during `initialization` or in the `onCreate()` lifecycle of your Activity/Fragment and call `launch(null)` anywhere to start it: ```kotlin -private val scanQrCode = registerForActivityResult(ScanQRCode()) { handleResult(it) } +val scanQrCode = registerForActivityResult(ScanQRCode(), ::handleResult) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - ... - - binding.buttonQrScanner.setOnClickListener { scanQrCode.launch(null) } + … + binding.button.setOnClickListener { scanQrCode.launch(null) } } + +fun handleResult(result: QRResult) { + … ``` -⚠️ **You can't register the ActivityResultContract inside of the OnClickListener. This will fail since the code get's executed after the onCreate lifecycle!** +⚠️ **You can't register the ActivityResultContract inside the OnClickListener lambda. This will fail since the code get's executed after the onCreate lifecycle!** -Check out the [samples](https://github.com/G00fY2/quickie/tree/master/sample) inside this repo or visit the [Activity Result API documentation](https://developer.android.com/training/basics/intents/result) for more information. +Check out the [samples](https://github.com/G00fY2/quickie/tree/develop/sample) inside this repo or visit the [Activity Result API documentation](https://developer.android.com/training/basics/intents/result) for more information. #### Responses The callback you add to the `registerForActivityResult` will receive an instance of the sealed `QRResult` class: diff --git a/quickie/build.gradle.kts b/quickie/build.gradle.kts index bd0c54cd..3a510a3d 100644 --- a/quickie/build.gradle.kts +++ b/quickie/build.gradle.kts @@ -50,7 +50,7 @@ dependencies { } group = "com.g00fy2.quickie" -version = "0.3.0" +version = "0.3.1" tasks.register("androidJavadocJar") { archiveClassifier.set("javadoc") diff --git a/quickie/src/main/kotlin/com/g00fy2/quickie/QROverlayView.kt b/quickie/src/main/kotlin/com/g00fy2/quickie/QROverlayView.kt index 532d7368..ef4f3b61 100644 --- a/quickie/src/main/kotlin/com/g00fy2/quickie/QROverlayView.kt +++ b/quickie/src/main/kotlin/com/g00fy2/quickie/QROverlayView.kt @@ -17,6 +17,7 @@ import android.widget.FrameLayout import androidx.annotation.Px import androidx.appcompat.widget.AppCompatTextView import androidx.core.content.ContextCompat +import com.g00fy2.quickie.databinding.QuickieTextviewBinding import kotlin.math.min import kotlin.math.roundToInt @@ -52,8 +53,7 @@ internal class QROverlayView @JvmOverloads constructor( init { setWillNotDraw(false) - LayoutInflater.from(context).inflate(R.layout.quickie_textview, this) - titleTextView = findViewById(R.id.title_textview) + titleTextView = QuickieTextviewBinding.inflate(LayoutInflater.from(context), this, true).titleTextview } override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { @@ -101,8 +101,15 @@ internal class QROverlayView @JvmOverloads constructor( titleTextView.visibility = if (topInsetsToOuterFrame < titleTextView.height) View.INVISIBLE else View.VISIBLE } - private fun View.getAccentColor() = - TypedValue().let { if (context.theme.resolveAttribute(R.attr.colorAccent, it, true)) it.data else Color.WHITE } + private fun View.getAccentColor(): Int { + return TypedValue().let { + if (context.theme.resolveAttribute(android.R.attr.colorAccent, it, true)) { + it.data + } else { + Color.WHITE + } + } + } private fun View.updateTopMargin(@Px top: Int) { val params = layoutParams as MarginLayoutParams diff --git a/quickie/src/main/kotlin/com/g00fy2/quickie/content/ParcelableContent.kt b/quickie/src/main/kotlin/com/g00fy2/quickie/content/ParcelableContent.kt index 19a75a0c..26fe193c 100644 --- a/quickie/src/main/kotlin/com/g00fy2/quickie/content/ParcelableContent.kt +++ b/quickie/src/main/kotlin/com/g00fy2/quickie/content/ParcelableContent.kt @@ -4,22 +4,19 @@ import android.os.Parcelable import kotlinx.parcelize.Parcelize @Parcelize -internal object EmptyParcelable : Parcelable +internal class WifiParcelable(val encryptionType: Int, val password: String, val ssid: String) : Parcelable @Parcelize -internal data class WifiParcelable(val encryptionType: Int, val password: String, val ssid: String) : Parcelable +internal class UrlBookmarkParcelable(val title: String, val url: String) : Parcelable @Parcelize -internal data class UrlBookmarkParcelable(val title: String, val url: String) : Parcelable +internal class SmsParcelable(val message: String, val phoneNumber: String) : Parcelable @Parcelize -internal data class SmsParcelable(val message: String, val phoneNumber: String) : Parcelable +internal class GeoPointParcelable(val lat: Double, val lng: Double) : Parcelable @Parcelize -internal data class GeoPointParcelable(val lat: Double, val lng: Double) : Parcelable - -@Parcelize -internal data class ContactInfoParcelable( +internal class ContactInfoParcelable( val addressParcelables: List, val emailParcelables: List, val nameParcelable: PersonNameParcelable, @@ -30,14 +27,14 @@ internal data class ContactInfoParcelable( ) : Parcelable @Parcelize -internal data class EmailParcelable(val address: String, val body: String, val subject: String, val type: Int) : +internal class EmailParcelable(val address: String, val body: String, val subject: String, val type: Int) : Parcelable @Parcelize -internal data class PhoneParcelable(val number: String, val type: Int) : Parcelable +internal class PhoneParcelable(val number: String, val type: Int) : Parcelable @Parcelize -internal data class PersonNameParcelable( +internal class PersonNameParcelable( val first: String, val formattedName: String, val last: String, @@ -48,7 +45,7 @@ internal data class PersonNameParcelable( ) : Parcelable @Parcelize -internal data class CalendarEventParcelable( +internal class CalendarEventParcelable( val description: String, val end: CalendarDateTimeParcelable, val location: String, @@ -59,7 +56,7 @@ internal data class CalendarEventParcelable( ) : Parcelable @Parcelize -internal data class CalendarDateTimeParcelable( +internal class CalendarDateTimeParcelable( val day: Int, val hours: Int, val minutes: Int, @@ -70,4 +67,4 @@ internal data class CalendarDateTimeParcelable( ) : Parcelable @Parcelize -internal data class AddressParcelable(val addressLines: List, val type: Int) : Parcelable \ No newline at end of file +internal class AddressParcelable(val addressLines: List, val type: Int) : Parcelable \ No newline at end of file diff --git a/quickie/src/main/kotlin/com/g00fy2/quickie/content/QRContent.kt b/quickie/src/main/kotlin/com/g00fy2/quickie/content/QRContent.kt index c091ec14..15c7351f 100644 --- a/quickie/src/main/kotlin/com/g00fy2/quickie/content/QRContent.kt +++ b/quickie/src/main/kotlin/com/g00fy2/quickie/content/QRContent.kt @@ -8,33 +8,40 @@ sealed class QRContent(val rawValue: String) { /** * Plain text or unknown content QR Code type. */ - class Plain(rawValue: String) : QRContent(rawValue) + data class Plain(private val _rawValue: String) : QRContent(_rawValue) /** * Wi-Fi access point details from a 'WIFI:' or similar QR Code type. */ - class Wifi(rawValue: String, val encryptionType: Int, val password: String, val ssid: String) : QRContent(rawValue) + data class Wifi(private val _rawValue: String, val encryptionType: Int, val password: String, val ssid: String) : + QRContent(_rawValue) /** * A URL or URL bookmark from a 'MEBKM:' or similar QR Code type. */ - class Url(rawValue: String, val title: String, val url: String) : QRContent(rawValue) + data class Url(private val _rawValue: String, val title: String, val url: String) : QRContent(_rawValue) /** * An SMS message from an 'SMS:' or similar QR Code type. */ - class Sms(rawValue: String, val message: String, val phoneNumber: String) : QRContent(rawValue) + data class Sms(private val _rawValue: String, val message: String, val phoneNumber: String) : QRContent(_rawValue) /** * GPS coordinates from a 'GEO:' or similar QR Code type. */ - class GeoPoint(rawValue: String, val lat: Double, val lng: Double) : QRContent(rawValue) + data class GeoPoint(private val _rawValue: String, val lat: Double, val lng: Double) : QRContent(_rawValue) /** * An email message from a 'MAILTO:' or similar QR Code type. */ - class Email(rawValue: String, val address: String, val body: String, val subject: String, val type: EmailType) : - QRContent(rawValue) { + data class Email( + private val _rawValue: String, + val address: String, + val body: String, + val subject: String, + val type: EmailType + ) : + QRContent(_rawValue) { enum class EmailType { UNKNOWN, WORK, HOME } @@ -43,7 +50,7 @@ sealed class QRContent(val rawValue: String) { /** * A phone number from a 'TEL:' or similar QR Code type. */ - class Phone(rawValue: String, val number: String, val type: PhoneType) : QRContent(rawValue) { + data class Phone(private val _rawValue: String, val number: String, val type: PhoneType) : QRContent(_rawValue) { enum class PhoneType { UNKNOWN, WORK, HOME, FAX, MOBILE } @@ -52,8 +59,8 @@ sealed class QRContent(val rawValue: String) { /** * A person's or organization's business card. */ - class ContactInfo( - rawValue: String, + data class ContactInfo( + private val _rawValue: String, val addresses: List
, val emails: List, val name: PersonName, @@ -61,7 +68,7 @@ sealed class QRContent(val rawValue: String) { val phones: List, val title: String, val urls: List - ) : QRContent(rawValue) { + ) : QRContent(_rawValue) { data class Address(val addressLines: List, val type: AddressType) { enum class AddressType { @@ -83,8 +90,8 @@ sealed class QRContent(val rawValue: String) { /** * A calendar event extracted from a QR Code. */ - class CalendarEvent( - rawValue: String, + data class CalendarEvent( + private val _rawValue: String, val description: String, val end: CalendarDateTime, val location: String, @@ -92,7 +99,7 @@ sealed class QRContent(val rawValue: String) { val start: CalendarDateTime, val status: String, val summary: String - ) : QRContent(rawValue) { + ) : QRContent(_rawValue) { data class CalendarDateTime( val day: Int, diff --git a/quickie/src/main/kotlin/com/g00fy2/quickie/extensions/BarcodeExtensions.kt b/quickie/src/main/kotlin/com/g00fy2/quickie/extensions/BarcodeExtensions.kt index ef21b0d8..a5bf336f 100644 --- a/quickie/src/main/kotlin/com/g00fy2/quickie/extensions/BarcodeExtensions.kt +++ b/quickie/src/main/kotlin/com/g00fy2/quickie/extensions/BarcodeExtensions.kt @@ -6,7 +6,6 @@ import com.g00fy2.quickie.content.CalendarDateTimeParcelable import com.g00fy2.quickie.content.CalendarEventParcelable import com.g00fy2.quickie.content.ContactInfoParcelable import com.g00fy2.quickie.content.EmailParcelable -import com.g00fy2.quickie.content.EmptyParcelable import com.g00fy2.quickie.content.GeoPointParcelable import com.g00fy2.quickie.content.PersonNameParcelable import com.g00fy2.quickie.content.PhoneParcelable @@ -15,7 +14,7 @@ import com.g00fy2.quickie.content.UrlBookmarkParcelable import com.g00fy2.quickie.content.WifiParcelable import com.google.mlkit.vision.barcode.Barcode -internal fun Barcode.toParcelableContentType(): Parcelable { +internal fun Barcode.toParcelableContentType(): Parcelable? { return when (valueType) { Barcode.TYPE_CONTACT_INFO -> { ContactInfoParcelable( @@ -58,7 +57,7 @@ internal fun Barcode.toParcelableContentType(): Parcelable { summary = calendarEvent?.summary ?: "" ) } - else -> EmptyParcelable // TYPE_TEXT, TYPE_ISBN, TYPE_PRODUCT, TYPE_DRIVER_LICENSE, TYPE_UNKNOWN + else -> null // TYPE_TEXT, TYPE_ISBN, TYPE_PRODUCT, TYPE_DRIVER_LICENSE, TYPE_UNKNOWN } } diff --git a/quickie/src/main/kotlin/com/g00fy2/quickie/extensions/IntentExtensions.kt b/quickie/src/main/kotlin/com/g00fy2/quickie/extensions/IntentExtensions.kt index 2259ea63..06eade8f 100644 --- a/quickie/src/main/kotlin/com/g00fy2/quickie/extensions/IntentExtensions.kt +++ b/quickie/src/main/kotlin/com/g00fy2/quickie/extensions/IntentExtensions.kt @@ -35,11 +35,12 @@ internal fun Intent?.toQuickieContentType(): QRContent { if (this == null) return Plain("") val rawValue = getStringExtra(QRScannerActivity.EXTRA_RESULT_VALUE) ?: "" - val resultContent = when (getIntExtra(QRScannerActivity.EXTRA_RESULT_TYPE, Barcode.TYPE_UNKNOWN)) { + + return when (getIntExtra(QRScannerActivity.EXTRA_RESULT_TYPE, Barcode.TYPE_UNKNOWN)) { Barcode.TYPE_CONTACT_INFO -> { getParcelableExtra(QRScannerActivity.EXTRA_RESULT_PARCELABLE)?.run { ContactInfo( - rawValue = rawValue, + _rawValue = rawValue, addresses = addressParcelables.map { it.toAddress() }, emails = emailParcelables.map { it.toEmail(rawValue) }, name = nameParcelable.toPersonName(), @@ -53,7 +54,7 @@ internal fun Intent?.toQuickieContentType(): QRContent { Barcode.TYPE_EMAIL -> { getParcelableExtra(QRScannerActivity.EXTRA_RESULT_PARCELABLE)?.run { Email( - rawValue = rawValue, + _rawValue = rawValue, address = address, body = body, subject = subject, @@ -63,33 +64,33 @@ internal fun Intent?.toQuickieContentType(): QRContent { } Barcode.TYPE_PHONE -> { getParcelableExtra(QRScannerActivity.EXTRA_RESULT_PARCELABLE)?.run { - Phone(rawValue = rawValue, number = number, type = PhoneType.values().getOrElse(type) { PhoneType.UNKNOWN }) + Phone(_rawValue = rawValue, number = number, type = PhoneType.values().getOrElse(type) { PhoneType.UNKNOWN }) } } Barcode.TYPE_SMS -> { getParcelableExtra(QRScannerActivity.EXTRA_RESULT_PARCELABLE)?.run { - Sms(rawValue = rawValue, message = message, phoneNumber = phoneNumber) + Sms(_rawValue = rawValue, message = message, phoneNumber = phoneNumber) } } Barcode.TYPE_URL -> { getParcelableExtra(QRScannerActivity.EXTRA_RESULT_PARCELABLE)?.run { - Url(rawValue = rawValue, title = title, url = url) + Url(_rawValue = rawValue, title = title, url = url) } } Barcode.TYPE_WIFI -> { getParcelableExtra(QRScannerActivity.EXTRA_RESULT_PARCELABLE)?.run { - Wifi(rawValue = rawValue, encryptionType = encryptionType, password = password, ssid = ssid) + Wifi(_rawValue = rawValue, encryptionType = encryptionType, password = password, ssid = ssid) } } Barcode.TYPE_GEO -> { getParcelableExtra(QRScannerActivity.EXTRA_RESULT_PARCELABLE)?.run { - GeoPoint(rawValue = rawValue, lat = lat, lng = lng) + GeoPoint(_rawValue = rawValue, lat = lat, lng = lng) } } Barcode.TYPE_CALENDAR_EVENT -> { getParcelableExtra(QRScannerActivity.EXTRA_RESULT_PARCELABLE)?.run { CalendarEvent( - rawValue = rawValue, + _rawValue = rawValue, description = description, end = end.toCalendarEvent(), location = location, @@ -101,8 +102,7 @@ internal fun Intent?.toQuickieContentType(): QRContent { } } else -> null - } - return resultContent ?: Plain(rawValue) + } ?: Plain(rawValue) } internal fun Intent?.getRootException(): Exception { @@ -114,11 +114,11 @@ internal fun Intent?.getRootException(): Exception { } private fun PhoneParcelable.toPhone(rawValue: String) = - Phone(rawValue = rawValue, number = number, type = PhoneType.values().getOrElse(type) { PhoneType.UNKNOWN }) + Phone(_rawValue = rawValue, number = number, type = PhoneType.values().getOrElse(type) { PhoneType.UNKNOWN }) private fun EmailParcelable.toEmail(rawValue: String) = Email( - rawValue = rawValue, + _rawValue = rawValue, address = address, body = body, subject = subject, diff --git a/sample/activity-sample/src/main/kotlin/com/g00fy2/quickieactivitysample/MainActivity.kt b/sample/activity-sample/src/main/kotlin/com/g00fy2/quickieactivitysample/MainActivity.kt index 99c6f3ee..b2b62247 100644 --- a/sample/activity-sample/src/main/kotlin/com/g00fy2/quickieactivitysample/MainActivity.kt +++ b/sample/activity-sample/src/main/kotlin/com/g00fy2/quickieactivitysample/MainActivity.kt @@ -16,9 +16,7 @@ class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding private var snackbar: Snackbar? = null - private val scanQrCode = registerForActivityResult(ScanQRCode()) { - showSnackbar(it) - } + private val scanQrCode = registerForActivityResult(ScanQRCode(), ::showSnackbar) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/sample/advanced-sample/src/main/kotlin/com/g00fy2/quickieadvancedsample/MainActivity.kt b/sample/advanced-sample/src/main/kotlin/com/g00fy2/quickieadvancedsample/MainActivity.kt index 6d2a8453..c50bc5f0 100644 --- a/sample/advanced-sample/src/main/kotlin/com/g00fy2/quickieadvancedsample/MainActivity.kt +++ b/sample/advanced-sample/src/main/kotlin/com/g00fy2/quickieadvancedsample/MainActivity.kt @@ -32,7 +32,7 @@ class MainActivity : AppCompatActivity() { viewModel.scanQRCode() } - viewModel.qrCodeState.observe(this) { showSnackbar(it) } + viewModel.qrCodeState.observe(this, ::showSnackbar) } private fun showSnackbar(result: QRResult) { diff --git a/sample/fragment-sample/src/main/kotlin/com/g00fy2/quickiefragmentsample/MainFragment.kt b/sample/fragment-sample/src/main/kotlin/com/g00fy2/quickiefragmentsample/MainFragment.kt index e0c64adc..b7481668 100644 --- a/sample/fragment-sample/src/main/kotlin/com/g00fy2/quickiefragmentsample/MainFragment.kt +++ b/sample/fragment-sample/src/main/kotlin/com/g00fy2/quickiefragmentsample/MainFragment.kt @@ -20,9 +20,7 @@ class MainFragment : Fragment() { private val binding get() = _binding!! private var snackbar: Snackbar? = null - private val scanQrCode = registerForActivityResult(ScanQRCode()) { - showSnackbar(it) - } + private val scanQrCode = registerForActivityResult(ScanQRCode(), ::showSnackbar) override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { _binding = FragmentMainBinding.inflate(inflater, container, false)