diff --git a/app/build.gradle b/app/build.gradle index dcd8d4a866..fb452b53ea 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -110,7 +110,7 @@ dependencies { implementation 'com.google.dagger:dagger:2.21' kapt 'com.google.dagger:dagger-compiler:2.21' annotationProcessor 'com.google.dagger:dagger-compiler:2.21' - implementation 'com.google.zxing:core:3.3.3' + implementation 'com.google.zxing:core:3.4.0' implementation 'com.google.code.gson:gson:2.8.5' implementation 'com.madgag.spongycastle:core:1.56.0.0' implementation 'com.madgag.spongycastle:prov:1.56.0.0' diff --git a/app/src/main/java/com/tangem/ui/activity/MainActivity.kt b/app/src/main/java/com/tangem/ui/activity/MainActivity.kt index 3ec382c142..f4e42ae6db 100644 --- a/app/src/main/java/com/tangem/ui/activity/MainActivity.kt +++ b/app/src/main/java/com/tangem/ui/activity/MainActivity.kt @@ -2,21 +2,16 @@ package com.tangem.ui.activity -import android.Manifest import android.content.Context import android.content.Intent import android.content.pm.ActivityInfo -import android.content.pm.PackageManager import android.nfc.NfcAdapter import android.nfc.Tag import android.os.Bundle import androidx.appcompat.app.AppCompatActivity -import androidx.core.app.ActivityCompat -import androidx.core.content.ContextCompat import androidx.lifecycle.ViewModelProviders import com.scottyab.rootbeer.RootBeer import com.tangem.App -import com.tangem.Constant import com.tangem.di.ToastHelper import com.tangem.tangem_sdk.android.nfc.NfcLifecycleObserver import com.tangem.tangem_sdk.android.reader.NfcManager @@ -59,8 +54,6 @@ class MainActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT - verifyPermissions() - nfcManager = NfcManager(this, this) lifecycle.addObserver(NfcLifecycleObserver(nfcManager)) @@ -79,13 +72,6 @@ class MainActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { RootFoundDialog().show(supportFragmentManager, RootFoundDialog.TAG) } - private fun verifyPermissions() { - NfcManager.verifyPermissions(this) - if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { - ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), Constant.REQUEST_CODE_REQUEST_CAMERA_PERMISSIONS) - } - } - override fun onTagDiscovered(tag: Tag) { val activeFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) ?.childFragmentManager?.primaryNavigationFragment diff --git a/app/src/main/java/com/tangem/ui/fragment/QrScanFragment.kt b/app/src/main/java/com/tangem/ui/fragment/QrScanFragment.kt deleted file mode 100644 index 90063ec96c..0000000000 --- a/app/src/main/java/com/tangem/ui/fragment/QrScanFragment.kt +++ /dev/null @@ -1,70 +0,0 @@ -package com.tangem.ui.fragment - -import android.Manifest -import android.app.Activity -import android.content.Context -import android.content.Intent -import android.content.pm.PackageManager -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.core.app.ActivityCompat -import com.google.zxing.Result -import com.tangem.Constant -import me.dm7.barcodescanner.zxing.ZXingScannerView - -class QrScanFragment : BaseFragment(), ZXingScannerView.ResultHandler { - companion object { - fun callingIntent(context: Context): Intent { - return Intent(context, QrScanFragment::class.java) - } - } - - override val layoutId = 0 - - private var scannerView: ZXingScannerView? = null - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - if (ActivityCompat.checkSelfPermission(context!!, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) - ActivityCompat.requestPermissions(activity!!, arrayOf(Manifest.permission.CAMERA), 1) - } - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - scannerView = ZXingScannerView(activity) - return scannerView - } - - override fun onPause() { - super.onPause() - scannerView?.stopCamera() - - } - - override fun onResume() { - super.onResume() - scannerView?.setResultHandler(this) - scannerView?.startCamera() - } - - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { - when (requestCode) { - 1 -> { - if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) - - else { - navigateBackWithResult(Activity.RESULT_CANCELED) - } - } - } - } - - override fun handleResult(result: Result) { - val data = Bundle() - data.putString(Constant.EXTRA_QR_CODE, result.text) - - navigateBackWithResult(Activity.RESULT_OK, data) - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/ui/fragment/additional/PrepareCryptonitOtherApiWithdrawalFragment.kt b/app/src/main/java/com/tangem/ui/fragment/additional/PrepareCryptonitOtherApiWithdrawalFragment.kt index 9c21c5fb41..f9c5e38416 100644 --- a/app/src/main/java/com/tangem/ui/fragment/additional/PrepareCryptonitOtherApiWithdrawalFragment.kt +++ b/app/src/main/java/com/tangem/ui/fragment/additional/PrepareCryptonitOtherApiWithdrawalFragment.kt @@ -11,6 +11,7 @@ import com.tangem.data.Blockchain import com.tangem.data.network.CryptonitOtherApi import com.tangem.ui.activity.MainActivity import com.tangem.ui.fragment.BaseFragment +import com.tangem.ui.fragment.qr.CameraPermissionManager import com.tangem.ui.navigation.NavigationResultListener import com.tangem.wallet.CoinEngineFactory import com.tangem.wallet.R @@ -27,6 +28,7 @@ class PrepareCryptonitOtherApiWithdrawalFragment : BaseFragment(), NavigationRes override val layoutId = R.layout.fragment_prepare_cryptonit_other_api_withdrawal + private val cameraPermissionManager: CameraPermissionManager by lazy { CameraPermissionManager(this) } private val ctx: TangemContext by lazy { TangemContext.loadFromBundle(context, arguments) } private val cryptonit: CryptonitOtherApi by lazy { CryptonitOtherApi(context) } @@ -69,23 +71,11 @@ class PrepareCryptonitOtherApiWithdrawalFragment : BaseFragment(), NavigationRes // } } - ivCameraKey.setOnClickListener { - navigateForResult( - Constant.REQUEST_CODE_SCAN_QR_KEY, - R.id.action_prepareCryptonitOtherApiWithdrawalFragment_to_qrScanFragment) - } + ivCameraKey.setOnClickListener { checkPermissionsAndRunCamera() } - ivCameraSecret.setOnClickListener { - navigateForResult( - Constant.REQUEST_CODE_SCAN_QR_SECRET, - R.id.action_prepareCryptonitOtherApiWithdrawalFragment_to_qrScanFragment) - } + ivCameraSecret.setOnClickListener { checkPermissionsAndRunCamera() } - ivCameraUserId.setOnClickListener { - navigateForResult( - Constant.REQUEST_CODE_SCAN_QR_USER_ID, - R.id.action_prepareCryptonitOtherApiWithdrawalFragment_to_qrScanFragment) - } + ivCameraUserId.setOnClickListener { checkPermissionsAndRunCamera() } ivRefreshBalance.setOnClickListener { doRequestBalance() } @@ -125,6 +115,14 @@ class PrepareCryptonitOtherApiWithdrawalFragment : BaseFragment(), NavigationRes doRequestBalance() } + private fun checkPermissionsAndRunCamera() { + if (cameraPermissionManager.isPermissionGranted()) { + navigateForResult(Constant.REQUEST_CODE_SCAN_QR, R.id.action_prepareCryptonitOtherApiWithdrawalFragment_to_qrScanFragment) + } else { + cameraPermissionManager.requirePermission() + } + } + override fun onNavigationResult(requestCode: String, resultCode: Int, data: Bundle?) { if (resultCode == Activity.RESULT_OK && data != null && data.containsKey("QRCode")) { when (requestCode) { @@ -166,4 +164,11 @@ class PrepareCryptonitOtherApiWithdrawalFragment : BaseFragment(), NavigationRes } } + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + cameraPermissionManager.handleRequestPermissionResult(requestCode, grantResults) { + navigateForResult(Constant.REQUEST_CODE_SCAN_QR, R.id.action_prepareCryptonitOtherApiWithdrawalFragment_to_qrScanFragment) + } + } + } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/ui/fragment/qr/CameraPermissionManager.kt b/app/src/main/java/com/tangem/ui/fragment/qr/CameraPermissionManager.kt new file mode 100644 index 0000000000..250370d40a --- /dev/null +++ b/app/src/main/java/com/tangem/ui/fragment/qr/CameraPermissionManager.kt @@ -0,0 +1,34 @@ +package com.tangem.ui.fragment.qr + +import android.Manifest +import android.content.pm.PackageManager +import android.widget.Toast +import androidx.core.content.ContextCompat +import androidx.core.content.PermissionChecker +import com.tangem.ui.fragment.BaseFragment +import com.tangem.wallet.R + +class CameraPermissionManager(val fragment: BaseFragment) { + + fun isPermissionGranted(): Boolean { + return ContextCompat.checkSelfPermission(fragment.requireContext(), Manifest.permission.CAMERA) == + PermissionChecker.PERMISSION_GRANTED + } + + fun handleRequestPermissionResult(requestCode: Int, grantResults: IntArray, action: () -> Unit) { + when (requestCode) { + 1 -> { + if (grantResults.isEmpty() || grantResults[0] != PackageManager.PERMISSION_GRANTED) { + Toast.makeText(fragment.requireContext(), R.string.general_toast_no_permission, Toast.LENGTH_LONG).show() + } else { + action.invoke() + } + } + } + } + + fun requirePermission() { + fragment.requestPermissions(arrayOf(Manifest.permission.CAMERA), 1) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/ui/fragment/qr/QrScanFragment.kt b/app/src/main/java/com/tangem/ui/fragment/qr/QrScanFragment.kt new file mode 100644 index 0000000000..9ee01f8cd9 --- /dev/null +++ b/app/src/main/java/com/tangem/ui/fragment/qr/QrScanFragment.kt @@ -0,0 +1,40 @@ +package com.tangem.ui.fragment.qr + +import android.app.Activity +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.google.zxing.Result +import com.tangem.Constant +import com.tangem.ui.fragment.BaseFragment +import me.dm7.barcodescanner.zxing.ZXingScannerView + +class QrScanFragment : BaseFragment(), ZXingScannerView.ResultHandler { + + override val layoutId = 0 + private var scannerView: ZXingScannerView? = null + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + scannerView = ZXingScannerView(activity) + return scannerView + } + + override fun onPause() { + super.onPause() + scannerView?.stopCamera() + } + + override fun onResume() { + super.onResume() + scannerView?.setResultHandler(this) + scannerView?.startCamera() + } + + override fun handleResult(result: Result) { + val data = Bundle() + data.putString(Constant.EXTRA_QR_CODE, result.text) + navigateBackWithResult(Activity.RESULT_OK, data) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/ui/fragment/wallet/LoadedWalletFragment.kt b/app/src/main/java/com/tangem/ui/fragment/wallet/LoadedWalletFragment.kt index 7a1e83b6ef..537e0d4dbb 100644 --- a/app/src/main/java/com/tangem/ui/fragment/wallet/LoadedWalletFragment.kt +++ b/app/src/main/java/com/tangem/ui/fragment/wallet/LoadedWalletFragment.kt @@ -604,14 +604,14 @@ class LoadedWalletFragment : BaseFragment(), NavigationResultListener, NfcAdapte if (tvError?.visibility == View.VISIBLE || tvMessage?.visibility == View.VISIBLE) { timerHideErrorAndMessage = Timer() - timerHideErrorAndMessage!!.schedule( + timerHideErrorAndMessage?.schedule( timerTask { activity?.runOnUiThread { tvMessage?.visibility = View.GONE tvError?.visibility = View.GONE // clear only already viewed messages - if (tvMessage.text == ctx.message) ctx.message = null - if (tvError.text == ctx.error) ctx.error = null + if (tvMessage?.text == ctx.message) ctx.message = null + if (tvError?.text == ctx.error) ctx.error = null } }, 5000) diff --git a/app/src/main/res/navigation/main_graph.xml b/app/src/main/res/navigation/main_graph.xml index 7901818df0..c27d66978d 100644 --- a/app/src/main/res/navigation/main_graph.xml +++ b/app/src/main/res/navigation/main_graph.xml @@ -91,7 +91,8 @@ app:destination="@id/confirmTransactionFragment" /> + app:destination="@id/qrScanFragment" + app:enterAnim="@anim/nav_default_enter_anim" /> + app:destination="@id/qrScanFragment" + app:enterAnim="@anim/nav_default_enter_anim"/> Scanner à nouveau pour vérifier la carte READING… Le porte-monnaie est vide + L\'utilisateur n\'a pas obtenu l\'autorisation d\'utiliser la caméra Paramètres diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 45c2a5bd9f..24812c1f37 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -21,6 +21,8 @@ Scan again to verify the card READING… The wallet is empty + User hasn\'t granted permission to use camera + Settings diff --git a/app/src/tangemAccess/java/com/tangem/ui/PrepareTransactionFragment.kt b/app/src/tangemAccess/java/com/tangem/ui/PrepareTransactionFragment.kt index 295b10b8b9..beeb4f1a33 100644 --- a/app/src/tangemAccess/java/com/tangem/ui/PrepareTransactionFragment.kt +++ b/app/src/tangemAccess/java/com/tangem/ui/PrepareTransactionFragment.kt @@ -15,6 +15,7 @@ import com.tangem.Constant import com.tangem.data.Blockchain import com.tangem.ui.activity.MainActivity import com.tangem.ui.fragment.BaseFragment +import com.tangem.ui.fragment.qr.CameraPermissionManager import com.tangem.ui.navigation.NavigationResultListener import com.tangem.util.UtilHelper import com.tangem.wallet.CoinEngineFactory @@ -31,6 +32,7 @@ class PrepareTransactionFragment : BaseFragment(), NavigationResultListener, Nfc override val layoutId = R.layout.fragment_prepare_transaction private val ctx: TangemContext by lazy { TangemContext.loadFromBundle(context, arguments) } + private val cameraPermissionManager: CameraPermissionManager by lazy { CameraPermissionManager(this) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -119,6 +121,17 @@ class PrepareTransactionFragment : BaseFragment(), NavigationResultListener, Nfc } ivCamera.setOnClickListener { + if (cameraPermissionManager.isPermissionGranted()) { + navigateForResult(Constant.REQUEST_CODE_SCAN_QR, R.id.action_prepareTransactionFragment_to_qrScanFragment) + } else { + cameraPermissionManager.requirePermission() + } + } + } + + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + cameraPermissionManager.handleRequestPermissionResult(requestCode, grantResults) { navigateForResult(Constant.REQUEST_CODE_SCAN_QR, R.id.action_prepareTransactionFragment_to_qrScanFragment) } } @@ -170,5 +183,4 @@ class PrepareTransactionFragment : BaseFragment(), NavigationResultListener, Nfc e.printStackTrace() } } - } \ No newline at end of file