Updated on 2026-08-14

This commit is contained in:
Tangem 2020-04-17 15:55:41 +03:00
commit 50cbb087b7
11 changed files with 79 additions and 54 deletions

View file

@ -3,6 +3,7 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply plugin: 'com.google.firebase.crashlytics'
apply plugin: 'com.google.firebase.firebase-perf'
apply plugin: 'com.google.gms.google-services'
static def generateVersionName() {
@ -72,6 +73,7 @@ repositories {
}
configurations {
all*.exclude group: 'com.google.guava', module: 'listenablefuture'
implementation.exclude module:'protobuf-lite'
}
dependencies {
@ -79,22 +81,22 @@ dependencies {
implementation project(':tangem-sdk-old')
implementation project(':server-android')
implementation 'androidx.navigation:navigation-fragment:2.1.0'
implementation 'androidx.navigation:navigation-ui-ktx:2.1.0'
implementation 'androidx.navigation:navigation-fragment:2.2.2'
implementation 'androidx.navigation:navigation-ui-ktx:2.2.2'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0'
implementation "androidx.lifecycle:lifecycle-runtime:2.1.0"
implementation "androidx.lifecycle:lifecycle-common-java8:2.1.0"
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation "androidx.lifecycle:lifecycle-runtime:2.2.0"
implementation "androidx.lifecycle:lifecycle-common-java8:2.2.0"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.fragment:fragment:1.1.0'
implementation 'androidx.fragment:fragment:1.2.4'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation "androidx.preference:preference:1.1.0"
implementation 'androidx.biometric:biometric:1.0.0-beta01'
implementation 'androidx.core:core-ktx:1.1.0'
implementation 'com.google.android.material:material:1.1.0-beta01'
implementation "androidx.preference:preference:1.1.1"
implementation 'androidx.biometric:biometric:1.0.1'
implementation 'androidx.core:core-ktx:1.2.0'
implementation 'com.google.android.material:material:1.1.0'
implementation 'com.google.dagger:dagger:2.21'
implementation 'com.google.dagger:dagger:2.24'
kapt 'com.google.dagger:dagger-compiler:2.21'
annotationProcessor 'com.google.dagger:dagger-compiler:2.21'
implementation 'com.google.zxing:core:3.4.0'
@ -113,8 +115,8 @@ dependencies {
implementation "com.orhanobut:hawk:2.0.1"
implementation 'co.nstant.in:cbor:0.8'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$versions.kotlin"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.2'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.2.2"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3"
// implementation 'org.bitcoinj:bitcoinj-parent:0.14.7' //TODO: is this needed?
implementation 'org.bitcoinj:bitcoinj-core:0.15.2'
implementation 'org.greenrobot:eventbus:3.1.1'
@ -126,8 +128,9 @@ dependencies {
// implementation 'com.github.stellar:java-stellar-sdk:0.4.1'
implementation 'net.i2p.crypto:eddsa:0.3.0'
implementation 'com.google.firebase:firebase-analytics:17.2.3'
implementation 'com.google.firebase:firebase-crashlytics:17.0.0-beta02'
implementation 'com.google.firebase:firebase-analytics:17.3.0'
implementation 'com.google.firebase:firebase-crashlytics:17.0.0-beta04'
implementation 'com.google.firebase:firebase-perf:19.0.6'
implementation files('libs/ripple-core-0.0.1.jar')
//4 dependencies for ripple-core TODO: move to module?

View file

@ -2,8 +2,6 @@ package com.tangem
import android.app.Application
import androidx.appcompat.app.AppCompatDelegate
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.tangem.data.dp.PrefsManager
@ -80,10 +78,7 @@ class App : Application() {
)
}
FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(Analytics.isEnabled())
FirebaseAnalytics.getInstance(this).setAnalyticsCollectionEnabled(
Analytics.isEnabled() && !BuildConfig.DEBUG
)
Analytics.setFirebaseEnabled(this)
}
private fun buildToastHelperComponent(): ToastHelperComponent {

View file

@ -22,6 +22,8 @@ import androidx.core.os.bundleOf
import androidx.lifecycle.ViewModelProviders
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.google.firebase.perf.FirebasePerformance
import com.google.firebase.perf.metrics.Trace
import com.tangem.App
import com.tangem.Constant
import com.tangem.data.Blockchain
@ -77,6 +79,7 @@ class MainFragment : BaseFragment(), NavigationResultListener, NfcAdapter.Reader
override val layoutId = R.layout.fragment_main
private lateinit var viewModel: MainViewModel
private lateinit var nfcDeviceAntenna: NfcDeviceAntennaLocation
private var tapTimerTrace: Trace? = null
private var unsuccessReadCount = 0
private var task: CustomReadCardTask? = null
private var lastTag: Tag? = null
@ -156,6 +159,9 @@ class MainFragment : BaseFragment(), NavigationResultListener, NfcAdapter.Reader
}
override fun onResume() {
tapTimerTrace = FirebasePerformance.getInstance()
.newTrace(AnalyticsEvent.CARD_TAP_USER_TIMER.event)
tapTimerTrace?.start()
super.onResume()
nfcDeviceAntenna.animate()
}
@ -167,6 +173,7 @@ class MainFragment : BaseFragment(), NavigationResultListener, NfcAdapter.Reader
override fun onStop() {
task?.cancel(true)
tapTimerTrace = null
super.onStop()
}
@ -248,6 +255,7 @@ class MainFragment : BaseFragment(), NavigationResultListener, NfcAdapter.Reader
}
override fun onReadFinish(cardProtocol: CardProtocol?) {
tapTimerTrace?.stop()
task = null
if (cardProtocol != null) {
if (cardProtocol.error == null) {
@ -338,7 +346,7 @@ class MainFragment : BaseFragment(), NavigationResultListener, NfcAdapter.Reader
lastTag = null
ReadCardInfoTask.resetLastReadInfo()
(activity as MainActivity).nfcManager.notifyReadResult(false)
(activity as? MainActivity)?.nfcManager?.notifyReadResult(false)
}
}
}

View file

@ -11,7 +11,6 @@ import androidx.preference.Preference
import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceFragmentCompat
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.tangem.util.Analytics
import com.tangem.util.AnalyticsEvent
import com.tangem.wallet.BuildConfig
@ -48,15 +47,13 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
if (key == getString(R.string.pref_analytics)) {
activity?.let {
val analytics = FirebaseAnalytics.getInstance(it)
activity?.let {activity ->
val analytics = FirebaseAnalytics.getInstance(activity)
if (!Analytics.isEnabled()) {
analytics.logEvent(AnalyticsEvent.ANALYTICS_TURNED_OFF.event, bundleOf())
}
analytics.setAnalyticsCollectionEnabled(Analytics.isEnabled() && !BuildConfig.DEBUG)
Analytics.setFirebaseEnabled(activity)
}
FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(Analytics.isEnabled())
}
}

View file

@ -1,8 +1,13 @@
package com.tangem.util
import android.content.Context
import android.os.Bundle
import androidx.core.os.bundleOf
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.google.firebase.perf.FirebasePerformance
import com.tangem.data.dp.PrefsManager
import com.tangem.wallet.BuildConfig
import com.tangem.wallet.R
import com.tangem.wallet.TangemContext
@ -13,6 +18,7 @@ enum class AnalyticsEvent(val event: String) {
READY_TO_SIGN("ready_to_sign"),
SIGNED("signed"),
ANALYTICS_TURNED_OFF("analytics_turned_off"),
CARD_TAP_USER_TIMER("CardTapUserTimer"),
;
}
@ -36,5 +42,13 @@ class Analytics {
fun isEnabled(): Boolean {
return PrefsManager.getInstance().getSettingsBoolean(R.string.pref_analytics, true)
}
fun setFirebaseEnabled(context: Context, enable: Boolean = isEnabled()) {
FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(enable)
FirebaseAnalytics.getInstance(context).setAnalyticsCollectionEnabled(
enable && !BuildConfig.DEBUG
)
FirebasePerformance.getInstance().isPerformanceCollectionEnabled = enable
}
}
}

View file

@ -11,7 +11,8 @@ buildscript {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$versions.kotlin"
classpath "com.github.dcendents:android-maven-gradle-plugin:2.1"
classpath 'com.google.gms:google-services:4.3.3'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.0.0-beta03'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.0.0-beta04'
classpath 'com.google.firebase:perf-plugin:1.3.1'
}
}

View file

@ -1,4 +1,4 @@
ext.versions = [
kotlin : '1.3.71',
kotlin : '1.3.72',
build_gradle: '3.6.2',
]

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Tangem
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,6 +1,5 @@
[![Release](https://jitpack.io/v/Tangem/tangem-sdk-android.svg)]
![Release](https://jitpack.io/v/Tangem/tangem-sdk-android.svg)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
# Welcome to Tangem
The Tangem card is a self-custodial hardware wallet for blockchain assets. The main functions of Tangem cards are to securely create and store a private key from a blockchain wallet and sign blockchain transactions. The Tangem card does not allow users to import/export, backup/restore private keys, thereby guaranteeing that the wallet is unique and unclonable.

View file

@ -27,7 +27,6 @@ class DefaultSessionViewDelegate(private val reader: NfcReader) : SessionViewDel
lateinit var activity: FragmentActivity
private var readingDialog: BottomSheetDialog? = null
private var nfcEnableDialog: NfcEnableDialog? = null
init {
setLogger()
@ -36,7 +35,7 @@ class DefaultSessionViewDelegate(private val reader: NfcReader) : SessionViewDel
override fun onNfcSessionStarted(cardId: String?, message: Message?) {
reader.readingCancelled = false
postUI { showReadingDialog(activity, cardId, message) }
if (!reader.nfcEnabled) showNFCEnableDialog()
if (!reader.nfcEnabled) NfcEnableDialog().show(activity)
}
private fun showReadingDialog(activity: FragmentActivity, cardId: String?, message: Message?) {
@ -69,11 +68,6 @@ class DefaultSessionViewDelegate(private val reader: NfcReader) : SessionViewDel
readingDialog?.show()
}
private fun showNFCEnableDialog() {
nfcEnableDialog = NfcEnableDialog()
activity.supportFragmentManager.let { nfcEnableDialog?.show(it, NfcEnableDialog.TAG) }
}
override fun onSecurityDelay(ms: Int, totalDurationSeconds: Int) {
postUI {
readingDialog?.lTouchCard?.hide()

View file

@ -1,30 +1,23 @@
package com.tangem.tangem_sdk_new.ui
import android.app.Dialog
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.provider.Settings
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment
import com.tangem.tangem_sdk_new.R
class NfcEnableDialog : DialogFragment() {
companion object {
val TAG: String = NfcEnableDialog::class.java.simpleName
}
class NfcEnableDialog {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val builder = AlertDialog.Builder(requireContext())
fun show(activity: Activity) {
val builder = AlertDialog.Builder(activity)
builder.setCancelable(false)
.setIcon(R.drawable.ic_action_nfc_gray)
.setTitle(R.string.dialog_nfc_enable_title)
.setMessage(R.string.dialog_nfc_enable_text)
.setPositiveButton(R.string.general_ok
) { _, _ ->
activity?.startActivity(Intent(Settings.ACTION_NFC_SETTINGS))
activity.startActivity(Intent(Settings.ACTION_NFC_SETTINGS))
}
return builder.create()
builder.create().show()
}
}