diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index b4113f3..8c7eebd 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -11,8 +11,8 @@ android {
applicationId = "sh.sar.basedbank"
minSdk = 26
targetSdk = 36
- versionCode = 15
- versionName = "1.0.16"
+ versionCode = 16
+ versionName = "1.0.17"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/DashboardFragment.kt b/app/src/main/java/sh/sar/basedbank/ui/home/DashboardFragment.kt
index 9755cf5..39d5fac 100644
--- a/app/src/main/java/sh/sar/basedbank/ui/home/DashboardFragment.kt
+++ b/app/src/main/java/sh/sar/basedbank/ui/home/DashboardFragment.kt
@@ -26,6 +26,7 @@ import sh.sar.basedbank.api.mib.MibCard
import sh.sar.basedbank.api.mib.MibFinanceDeal
import sh.sar.basedbank.util.bmlapi.BmlCardParser
import sh.sar.basedbank.util.CredentialStore
+import sh.sar.basedbank.util.NfcPaymentUtil
import sh.sar.basedbank.util.PaymvQrParser
import kotlin.math.abs
import sh.sar.basedbank.databinding.FragmentDashboardBinding
@@ -426,11 +427,13 @@ class DashboardFragment : Fragment() {
if (isMib) {
Toast.makeText(requireContext(), R.string.mib_qr_nfc_not_supported, Toast.LENGTH_SHORT).show()
} else {
- val accountNumber = (item as CardItem.Bml).account.accountNumber
- (requireActivity() as HomeActivity).navigateTo(
- R.id.nav_pay_with_card,
- CardsFragment.newInstanceWithAutoTapMode(accountNumber)
- )
+ NfcPaymentUtil.checkAndProceed(requireContext()) {
+ val accountNumber = (item as CardItem.Bml).account.accountNumber
+ (requireActivity() as HomeActivity).navigateTo(
+ R.id.nav_pay_with_card,
+ CardsFragment.newInstanceWithAutoTapMode(accountNumber)
+ )
+ }
}
}
}
diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/PayWithCardFragment.kt b/app/src/main/java/sh/sar/basedbank/ui/home/PayWithCardFragment.kt
index 889b635..0b6b05f 100644
--- a/app/src/main/java/sh/sar/basedbank/ui/home/PayWithCardFragment.kt
+++ b/app/src/main/java/sh/sar/basedbank/ui/home/PayWithCardFragment.kt
@@ -48,6 +48,7 @@ import sh.sar.basedbank.util.CardsCache
import sh.sar.basedbank.util.CredentialStore
import sh.sar.basedbank.util.Totp
import sh.sar.basedbank.util.bmlapi.BmlCardParser
+import sh.sar.basedbank.util.NfcPaymentUtil
import sh.sar.basedbank.util.PaymvQrParser
import kotlin.math.abs
@@ -232,11 +233,13 @@ ViewCompat.setOnApplyWindowInsetsListener(binding.contentLayout) { v, insets ->
return@setOnClickListener
}
val bmlItem = item as CardItem.Bml
- val prefs = requireContext().getSharedPreferences("prefs", Context.MODE_PRIVATE)
- if (prefs.getBoolean("biometrics_transfer_confirm", false)) {
- showBiometricPromptForTap(bmlItem)
- } else {
- setTapMode(true, bmlItem)
+ NfcPaymentUtil.checkAndProceed(requireContext()) {
+ val prefs = requireContext().getSharedPreferences("prefs", Context.MODE_PRIVATE)
+ if (prefs.getBoolean("biometrics_transfer_confirm", false)) {
+ showBiometricPromptForTap(bmlItem)
+ } else {
+ setTapMode(true, bmlItem)
+ }
}
}
@@ -742,11 +745,13 @@ ViewCompat.setOnApplyWindowInsetsListener(binding.contentLayout) { v, insets ->
currentCardPosition = pos
binding.rvCards.scrollToPosition(pos)
}
- val prefs = requireContext().getSharedPreferences("prefs", Context.MODE_PRIVATE)
- if (prefs.getBoolean("biometrics_transfer_confirm", false)) {
- showBiometricPromptForTap(targetCard)
- } else {
- setTapMode(true, targetCard)
+ NfcPaymentUtil.checkAndProceed(requireContext()) {
+ val prefs = requireContext().getSharedPreferences("prefs", Context.MODE_PRIVATE)
+ if (prefs.getBoolean("biometrics_transfer_confirm", false)) {
+ showBiometricPromptForTap(targetCard)
+ } else {
+ setTapMode(true, targetCard)
+ }
}
}
}
diff --git a/app/src/main/java/sh/sar/basedbank/util/NfcPaymentUtil.kt b/app/src/main/java/sh/sar/basedbank/util/NfcPaymentUtil.kt
new file mode 100644
index 0000000..277f0f1
--- /dev/null
+++ b/app/src/main/java/sh/sar/basedbank/util/NfcPaymentUtil.kt
@@ -0,0 +1,53 @@
+package sh.sar.basedbank.util
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.nfc.NfcAdapter
+import android.nfc.cardemulation.CardEmulation
+import android.provider.Settings
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import sh.sar.basedbank.R
+import sh.sar.basedbank.nfc.BmlHostCardEmulatorService
+
+object NfcPaymentUtil {
+ fun checkAndProceed(context: Context, onReady: () -> Unit) {
+ val nfcAdapter = NfcAdapter.getDefaultAdapter(context) ?: run {
+ MaterialAlertDialogBuilder(context)
+ .setTitle(R.string.nfc_unsupported_title)
+ .setMessage(R.string.nfc_unsupported_message)
+ .setPositiveButton(android.R.string.ok, null)
+ .show()
+ return
+ }
+
+ if (!nfcAdapter.isEnabled) {
+ MaterialAlertDialogBuilder(context)
+ .setTitle(R.string.nfc_disabled_title)
+ .setMessage(R.string.nfc_disabled_message)
+ .setPositiveButton(R.string.nfc_open_settings) { _, _ ->
+ context.startActivity(Intent(Settings.ACTION_NFC_SETTINGS))
+ }
+ .setNegativeButton(R.string.cancel, null)
+ .show()
+ return
+ }
+
+ val cardEmulation = CardEmulation.getInstance(nfcAdapter)
+ val componentName = ComponentName(context, BmlHostCardEmulatorService::class.java)
+ if (!cardEmulation.isDefaultServiceForCategory(componentName, CardEmulation.CATEGORY_PAYMENT)) {
+ MaterialAlertDialogBuilder(context)
+ .setTitle(R.string.nfc_not_default_title)
+ .setMessage(context.getString(R.string.nfc_not_default_message,
+ context.applicationInfo.loadLabel(context.packageManager)))
+ .setPositiveButton(R.string.nfc_payment_open_settings) { _, _ ->
+ context.startActivity(Intent(Settings.ACTION_NFC_PAYMENT_SETTINGS))
+ }
+ .setNegativeButton(R.string.cancel, null)
+ .show()
+ return
+ }
+
+ onReady()
+ }
+}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 86dbd53..ff467f3 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -334,6 +334,14 @@
Scan to Pay
Tap to Pay
Skill issue on MIB side, Not supported
+ Not Supported
+ Tap to Pay is not supported on this device.
+ NFC is Off
+ Turn on NFC to use Tap to Pay.
+ NFC Settings
+ Set Default Payment App
+ Set %1$s as the default contactless payment app to use Tap to Pay.
+ Payment Settings
Manage Card
Set as Default Card
Hide from Dashboard